diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..dffe6ca
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "tgl"]
+ path = tgl
+ url = https://github.com/vysheng/tgl.git
diff --git a/Makefile.in b/Makefile.in
index 817b847..d9034bd 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -10,24 +10,16 @@ EXTRA_LIBS=@LIBS@ @EXTRA_LIBS@ @OPENSSL_LIBS@
LOCAL_LDFLAGS=-rdynamic -ggdb -levent ${EXTRA_LIBS}
LINK_FLAGS=${LDFLAGS} ${LOCAL_LDFLAGS}
-DEP=${srcdir}/dep
-AUTO=${srcdir}/auto
-EXE=${srcdir}/bin
-OBJ=${srcdir}/objs
-LIB=${srcdir}/libs
+DEP=dep
+AUTO=auto
+EXE=bin
+OBJ=objs
+LIB=libs
DIR_LIST=${DEP} ${AUTO} ${EXE} ${OBJ} ${LIB} ${DEP}/auto ${OBJ}/auto
-EXE_LIST=${EXE}/generate ${EXE}/tlc ${EXE}/telegram-cli
-LIB_LIST=${LIB}/libtgl.a
+EXE_LIST=${EXE}/telegram-cli
-TG_OBJECTS=${OBJ}/main.o ${OBJ}/loop.o ${OBJ}/interface.o ${OBJ}/net.o ${OBJ}/lua-tg.o ${OBJ}/tgl-timers.o
-TGL_OBJECTS=${OBJ}/mtproto-common.o ${OBJ}/mtproto-client.o ${OBJ}/queries.o ${OBJ}/structures.o ${OBJ}/binlog.o ${OBJ}/auto/auto.o ${OBJ}/tgl.o ${OBJ}/updates.o
-TLC_OBJECTS=${OBJ}/tlc.o ${OBJ}/tl-parser.o ${OBJ}/crc32.o
-TLD_OBJECTS=${OBJ}/dump-tl-file.o
-GENERATE_OBJECTS=${OBJ}/generate.o
-COMMON_OBJECTS=${OBJ}/tools.o
-OBJ_LIST=${TG_OBJECTS} ${TLC_OBJECTS} ${GENERATE_OBJECTS} ${COMMON_OBJECTS} ${TGL_OBJECTS} ${TLD_OBJECTS}
-OBJ_C=${TLC_OBJECTS} ${GENERATE_OBJECTS} ${COMMON_OBJECTS} ${TGL_OBJECTS} ${TLD_OBJECTS}
+TG_OBJECTS=${OBJ}/main.o ${OBJ}/loop.o ${OBJ}/interface.o ${OBJ}/lua-tg.o
DEPENDENCE=$(subst ${OBJ}/,${DEP}/,$(patsubst %.o,%.d,${OBJ_LIST}))
DEPENDENCE_LIST=${DEPENDENCE}
@@ -39,56 +31,24 @@ CC=@CC@
.SUFFIXES: .c .h .o
-all: ${EXE_LIST} ${DIR_LIST} ${LIB_LIST}
+all: ${EXE_LIST} ${DIR_LIST}
create_dirs_and_headers: ${DIR_LIST} ${AUTO}/auto.c ${AUTO}/auto-header.h ${AUTO}/constants.h
create_dirs: ${DIR_LIST}
dump-tl: ${EXE}/dump-tl-file
+include ${srcdir}/Makefile.tl-parser
+include ${srcdir}/Makefile.tgl
+
${DIR_LIST}:
@test -d $@ || mkdir -p $@
-include ${DEPENDENCE_LIST}
-${TG_OBJECTS} ${TGL_OBJECTS}: ${AUTO}/constants.h ${AUTO}/auto-header.h
-
${TG_OBJECTS}: ${OBJ}/%.o: %.c | create_dirs_and_headers
${CC} ${INCLUDE} ${COMPILE_FLAGS} -c -MP -MD -MF ${DEP}/$*.d -MQ ${OBJ}/$*.o -o $@ $<
-${OBJ_C}: ${OBJ}/%.o: %.c | create_dirs
- ${CC} ${INCLUDE} ${COMPILE_FLAGS} -c -MP -MD -MF ${DEP}/$*.d -MQ ${OBJ}/$*.o -o $@ $<
-
-${EXE}/tlc: ${TLC_OBJECTS} ${COMMON_OBJECTS}
- ${CC} ${TLC_OBJECTS} ${COMMON_OBJECTS} ${LINK_FLAGS} -o $@
-
-${EXE}/telegram-cli: ${TG_OBJECTS} ${COMMON_OBJECTS} ${LIB}/libtgl.a
- ${CC} ${TG_OBJECTS} ${COMMON_OBJECTS} ${LINK_FLAGS} -L${LIB} -l tgl -o $@
-
-${LIB}/libtgl.a: ${TGL_OBJECTS} ${COMMON_OBJECTS}
- ar ruv $@ ${TGL_OBJECTS} ${COMMON_OBJECTS}
-
-${EXE}/generate: ${GENERATE_OBJECTS} ${COMMON_OBJECTS}
- ${CC} ${GENERATE_OBJECTS} ${COMMON_OBJECTS} ${LINK_FLAGS} -o $@
-
-${AUTO}/scheme.tlo: ${AUTO}/scheme.tl ${EXE}/tlc
- ${EXE}/tlc -e $@ ${AUTO}/scheme.tl
-
-${AUTO}/scheme.tl: ${srcdir}/scheme.tl ${srcdir}/encrypted_scheme.tl ${srcdir}/binlog.tl ${srcdir}/append.tl | ${AUTO}
- cat $^ > $@
-
-${AUTO}/scheme2.tl: ${AUTO}/scheme.tl ${EXE}/tlc
- ${EXE}/tlc -E ${AUTO}/scheme.tl 2> $@ || ( cat $@ && rm $@ && false )
-
-${AUTO}/auto.c: ${AUTO}/scheme.tlo ${EXE}/generate
- ${EXE}/generate ${AUTO}/scheme.tlo > $@
-
-${AUTO}/auto-header.h: ${AUTO}/scheme.tlo ${EXE}/generate
- ${EXE}/generate -H ${AUTO}/scheme.tlo > $@
-
-${AUTO}/constants.h: ${AUTO}/scheme2.tl ${srcdir}/gen_constants_h.awk
- awk -f ${srcdir}/gen_constants_h.awk < $< > $@
-
-${EXE}/dump-tl-file: ${OBJ}/auto/auto.o ${TLD_OBJECTS}
- ${CC} ${OBJ}/auto/auto.o ${TLD_OBJECTS} ${LINK_FLAGS} -o $@
+${EXE}/telegram-cli: ${TG_OBJECTS} ${LIB}/libtgl.a
+ ${CC} $^ ${LINK_FLAGS} -o $@
clean:
rm -rf ${DIR_LIST} config.log config.status > /dev/null || echo "all clean"
diff --git a/Makefile.tgl b/Makefile.tgl
new file mode 100644
index 0000000..4ed85b6
--- /dev/null
+++ b/Makefile.tgl
@@ -0,0 +1,47 @@
+TGL_OBJECTS=${OBJ}/mtproto-common.o ${OBJ}/mtproto-client.o ${OBJ}/queries.o ${OBJ}/structures.o ${OBJ}/binlog.o ${OBJ}/tgl.o ${OBJ}/updates.o ${OBJ}/tgl-net.o ${OBJ}/tgl-timers.o
+TLD_OBJECTS=${OBJ}/dump-tl-file.o
+GENERATE_OBJECTS=${OBJ}/generate.o
+TGL_COMMON_OBJECTS=${OBJ}/tools.o
+TGL_OBJ_C=${GENERATE_OBJECTS} ${TGL_COMMON_OBJECTS} ${TGL_OBJECTS} ${TLD_OBJECTS}
+
+.SUFFIXES:
+
+.SUFFIXES: .c .h .o
+
+dump-tl: ${EXE}/dump-tl-file
+
+${OBJ}/auto/auto.o ${TGL_OBJECTS}: ${AUTO}/constants.h ${AUTO}/auto-header.h
+
+${TGL_OBJ_C}: ${OBJ}/%.o: ${srcdir}/tgl/%.c | create_dirs
+ ${CC} ${INCLUDE} ${COMPILE_FLAGS} -iquote ${srcdir}/tgl -c -MP -MD -MF ${DEP}/$*.d -MQ ${OBJ}/$*.o -o $@ $<
+
+${OBJ}/auto/auto.o: ${AUTO}/auto.c
+ ${CC} ${INCLUDE} ${COMPILE_FLAGS} -iquote ${srcdir}/tgl -c -MP -MD -MF ${DEP}/auto/auto.d -MQ ${OBJ}/auto/auto.o -o $@ $<
+
+${LIB}/libtgl.a: ${TGL_OBJECTS} ${TGL_COMMON_OBJECTS} ${OBJ}/auto/auto.o
+ ar ruv $@ $^
+
+${EXE}/generate: ${GENERATE_OBJECTS} ${TGL_COMMON_OBJECTS}
+ ${CC} ${GENERATE_OBJECTS} ${TGL_COMMON_OBJECTS} ${LINK_FLAGS} -o $@
+
+${AUTO}/scheme.tlo: ${AUTO}/scheme.tl ${EXE}/tl-parser
+ ${EXE}/tl-parser -e $@ ${AUTO}/scheme.tl
+
+${AUTO}/scheme.tl: ${srcdir}/tgl/scheme.tl ${srcdir}/tgl/encrypted_scheme.tl ${srcdir}/tgl/binlog.tl ${srcdir}/tgl/append.tl | ${AUTO}
+ cat $^ > $@
+
+${AUTO}/scheme2.tl: ${AUTO}/scheme.tl ${EXE}/tl-parser
+ ${EXE}/tl-parser -E ${AUTO}/scheme.tl 2> $@ || ( cat $@ && rm $@ && false )
+
+${AUTO}/auto.c: ${AUTO}/scheme.tlo ${EXE}/generate
+ ${EXE}/generate ${AUTO}/scheme.tlo > $@
+
+${AUTO}/auto-header.h: ${AUTO}/scheme.tlo ${EXE}/generate
+ ${EXE}/generate -H ${AUTO}/scheme.tlo > $@
+
+${AUTO}/constants.h: ${AUTO}/scheme2.tl ${srcdir}/tgl/gen_constants_h.awk
+ awk -f ${srcdir}/tgl/gen_constants_h.awk < $< > $@
+
+${EXE}/dump-tl-file: ${OBJ}/auto/auto.o ${TLD_OBJECTS}
+ ${CC} ${OBJ}/auto/auto.o ${TLD_OBJECTS} ${LINK_FLAGS} -o $@
+
diff --git a/Makefile.tl-parser b/Makefile.tl-parser
new file mode 100644
index 0000000..eb3284d
--- /dev/null
+++ b/Makefile.tl-parser
@@ -0,0 +1,7 @@
+TL_PARSER_OBJECTS=${OBJ}/tl-parser.o ${OBJ}/tlc.o ${OBJ}/crc32.o
+
+${TL_PARSER_OBJECTS}: ${OBJ}/%.o: ${srcdir}/tgl/tl-parser/%.c | create_dirs
+ ${CC} ${INCLUDE} ${COMPILE_FLAGS} -iquote ${srcdir}/tgl/tl-parser -c -MP -MD -MF ${DEP}/$*.d -MQ ${OBJ}/$*.o -o $@ $<
+
+${EXE}/tl-parser: ${TL_PARSER_OBJECTS}
+ ${CC} $^ ${LINK_FLAGS} -o $@
diff --git a/README.md b/README.md
index 656c612..abecd53 100644
--- a/README.md
+++ b/README.md
@@ -22,12 +22,7 @@ Fourth, in peer_name '#' are substitued to '@'. (Not applied to appending of '#%
Clone GitHub Repository
- git clone https://github.com/vysheng/tg.git && cd tg
-
-or download and extract zip
-
- wget https://github.com/vysheng/tg/archive/master.zip -O tg-master.zip
- unzip tg-master.zip && cd tg-master
+ git clone --recursive https://github.com/vysheng/tg.git && cd tg
#### Linux and BSDs
diff --git a/append.tl b/append.tl
deleted file mode 100644
index 0b5711b..0000000
--- a/append.tl
+++ /dev/null
@@ -1,2 +0,0 @@
-decryptedMessageMediaVideoL12#4cee6ef3 thumb:bytes thumb_w:int thumb_h:int duration:int w:int h:int size:int key:bytes iv:bytes = DecryptedMessageMedia;
-decryptedMessageMediaAudioL12#6080758f duration:int size:int key:bytes iv:bytes = DecryptedMessageMedia;
diff --git a/binlog.tl b/binlog.tl
deleted file mode 100644
index 9557b0c..0000000
--- a/binlog.tl
+++ /dev/null
@@ -1,83 +0,0 @@
----types---
-binlog.fileLocation dc:int volume:long local_id:int secret:long = binlog.FileLocation;
-binlog.chatParticipant user:int inviter:int date:int = binlog.ChatParticipant;
-
-binlog.start = binlog.Update;
-
-binlog.dcOption id:int name:string ip:string port:int = binlog.Update;
-binlog.authKey dc:int key_id:long key:64*[int] = binlog.Update;
-binlog.defaultDc dc:int = binlog.Update;
-binlog.ourId id:int = binlog.Update;
-binlog.dcSigned id:int = binlog.Update;
-binlog.dcSalt id:int salt:long = binlog.Update;
-
-binlog.setDhParams root:int prime:64*[int] version:int = binlog.Update;
-binlog.setPts pts:int = binlog.Update;
-binlog.setQts qts:int = binlog.Update;
-binlog.setDate date:int = binlog.Update;
-binlog.setSeq seq:int = binlog.Update;
-
-binlog.userAdd id:int first_name:string last_name:string hash:long phone:string is_contact:int = binlog.Update;
-binlog.userDelete id:int = binlog.Update;
-binlog.userSetAccessHash id:int hash:long = binlog.Update;
-binlog.userSetPhone id:int phone:string = binlog.Update;
-binlog.userSetFriend id:int friend:int = binlog.Update;
-binlog.userSetFullPhoto id:int photo:Photo = binlog.Update;
-binlog.userSetBlocked id:int blocked:int = binlog.Update;
-binlog.userSetRealName id:int real_first_name:string real_last_name:string = binlog.Update;
-binlog.userSetName id:int first_name:string last_name:string = binlog.Update;
-binlog.userSetPhoto id:int photo:UserProfilePhoto = binlog.Update;
-binlog.userSetUsername id:int username:string = binlog.Update;
-
-binlog.encrChatDelete id:int = binlog.Update;
-binlog.encrChatRequested id:int hash:long date:int admin:int user:int key:64*[int] nonce:64*[int] = binlog.Update;
-binlog.encrChatAccepted id:int key:64*[int] nonce:64*[int] fingerprint:long = binlog.Update;
-binlog.encrChatInit id:int user:int key:64*[int] g_key:64*[int] = binlog.Update;
-binlog.encrChatCreate id:int user_id:int admin_id:int name:string = binlog.Update;
-
-binlog.encrChatSetAccessHash id:int hash:long = binlog.Update;
-binlog.encrChatSetDate id:int date:int = binlog.Update;
-binlog.encrChatSetTtl id:int ttl:int = binlog.Update;
-binlog.encrChatSetLayer id:int layer:int = binlog.Update;
-binlog.encrChatSetState id:int state:int = binlog.Update;
-binlog.encrChatSetKey id:int key:64*[int] fingerprint:long = binlog.Update;
-
-binlog.encrChatUpdateSeq id:int in_seq_no:int out_seq_no:int = binlog.Update;
-binlog.encrChatSetSeq id:int in_seq_no:int last_in_seq_no:int out_seq_no:int = binlog.Update;
-
-binlog.chatCreate id:int flags:int title:string user_num:int date:int version:int photo_big:%binlog.FileLocation photo_small:%binlog.FileLocation = binlog.Update;
-binlog.chatChangeFlags id:int set_flags:int clear_flags:int = binlog.Update;
-binlog.chatSetTitle id:int title:string = binlog.Update;
-binlog.chatSetPhoto id:int photo_big:%binlog.FileLocation photo_small:%binlog.FileLocation = binlog.Update;
-binlog.chatSetDate id:int date:int = binlog.Update;
-binlog.chatSetVersion id:int version:int users_num:int = binlog.Update;
-binlog.chatSetAdmin id:int admin:int = binlog.Update;
-binlog.chatSetParticipants id:int version:int participants:%(Vector %binlog.ChatParticipant) = binlog.Update;
-binlog.chatSetFullPhoto id:int photo:Photo = binlog.Update;
-binlog.chatAddParticipant id:int version:int user:%binlog.ChatParticipant = binlog.Update;
-binlog.chatDelParticipant id:int version:int user:int = binlog.Update;
-
-binlog.createMessageText id:int from_id:int to_type:int to_id:int date:int unread:int text:string = binlog.Update;
-binlog.sendMessageText id:long from_id:int to_type:int to_id:int date:int text:string = binlog.Update;
-binlog.sendMessageActionEncr id:long from_id:int to_type:int to_id:int date:int action:DecryptedMessageAction = binlog.Update;
-binlog.createMessageTextFwd id:int from_id:int to_type:int to_id:int date:int fwd_from_id:int fwd_date:int unread:int text:string = binlog.Update;
-binlog.createMessageMedia id:int from_id:int to_type:int to_id:int date:int unread:int text:string media:MessageMedia = binlog.Update;
-binlog.createMessageMediaEncr id:long from_id:int to_type:int to_id:int date:int text:string media:DecryptedMessageMedia file:EncryptedFile = binlog.Update;
-binlog.createMessageMediaEncrPending id:long from_id:int to_type:int to_id:int date:int text:string media:DecryptedMessageMedia = binlog.Update;
-binlog.createMessageMediaEncrSent id:long file:EncryptedFile = binlog.Update;
-binlog.createMessageMediaFwd id:int from_id:int to_type:int to_id:int date:int fwd_from_id:int fwd_date:int unread:int text:string media:MessageMedia = binlog.Update;
-binlog.createMessageService id:int from_id:int to_type:int to_id:int date:int unread:int action:MessageAction = binlog.Update;
-binlog.createMessageServiceEncr id:long from_id:int to_type:int to_id:int date:int action:DecryptedMessageAction = binlog.Update;
-binlog.createMessageServiceFwd id:int from_id:int to_type:int to_id:int date:int fwd_from_id:int fwd_date:int unread:int action:MessageAction = binlog.Update;
-binlog.messageSetUnread id:int = binlog.Update;
-binlog.messageSetUnreadLong id:long = binlog.Update;
-binlog.setMessageSent id:long = binlog.Update;
-binlog.setMsgId old_id:long new_id:int = binlog.Update;
-binlog.deleteMsg id:long = binlog.Update;
-
-binlog.msgSeqUpdate id:long = binlog.Update;
-binlog.msgUpdate id:long = binlog.Update;
-
-binlog.resetAuthorization = binlog.Update;
-
-//binlog.addDc id:int ip:string port:int auth_key_id:long auth_key:64*[int] = binlog.Update;
diff --git a/crc32.c b/crc32.c
deleted file mode 100644
index 1fc4e61..0000000
--- a/crc32.c
+++ /dev/null
@@ -1,668 +0,0 @@
-/*
- This file is part of VK/KittenPHP-DB-Engine Library.
-
- VK/KittenPHP-DB-Engine Library is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 2 of the License, or
- (at your option) any later version.
-
- VK/KittenPHP-DB-Engine Library 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 Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with VK/KittenPHP-DB-Engine Library. If not, see .
-
- Copyright 2009-2012 Vkontakte Ltd
- 2009-2012 Nikolai Durov
- 2009-2012 Andrei Lopatin
- 2012 Anton Maydell
-*/
-
-#include
-#include
-#include
-#include "config.h"
-
-#ifdef HAVE_CONFIG_H
-#include "crc32.h"
-#endif
-
-#ifndef HAVE___BUILTIN_BSWAP32
-static inline unsigned __builtin_bswap32(unsigned x) {
- return ((x << 24) & 0xff000000 ) |
- ((x << 8) & 0x00ff0000 ) |
- ((x >> 8) & 0x0000ff00 ) |
- ((x >> 24) & 0x000000ff );
-}
-#endif
-
-unsigned int crc32_table[256] =
-{
- 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
- 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
- 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
- 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
- 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
- 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
- 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
- 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
- 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
- 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
- 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
- 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
- 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
- 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
- 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
- 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
- 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
- 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
- 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
- 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
- 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
- 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
- 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
- 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
- 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
- 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
- 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
- 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
- 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
- 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
- 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
- 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
- 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
- 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
- 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
- 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
- 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
- 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
- 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
- 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
- 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
- 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
- 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
- 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
- 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
- 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
- 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
- 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
- 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
- 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
- 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
- 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
- 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
- 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
- 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
- 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
- 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
- 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
- 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
- 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
- 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
- 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
- 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
- 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
-};
-
-unsigned int crc32_table2[256] =
-{
- 0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3,
- 0x646cc504, 0x7d77f445, 0x565aa786, 0x4f4196c7,
- 0xc8d98a08, 0xd1c2bb49, 0xfaefe88a, 0xe3f4d9cb,
- 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e, 0x87981ccf,
- 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192,
- 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496,
- 0x821b9859, 0x9b00a918, 0xb02dfadb, 0xa936cb9a,
- 0xe6775d5d, 0xff6c6c1c, 0xd4413fdf, 0xcd5a0e9e,
- 0x958424a2, 0x8c9f15e3, 0xa7b24620, 0xbea97761,
- 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265,
- 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69,
- 0x39316bae, 0x202a5aef, 0x0b07092c, 0x121c386d,
- 0xdf4636f3, 0xc65d07b2, 0xed705471, 0xf46b6530,
- 0xbb2af3f7, 0xa231c2b6, 0x891c9175, 0x9007a034,
- 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38,
- 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c,
- 0xf0794f05, 0xe9627e44, 0xc24f2d87, 0xdb541cc6,
- 0x94158a01, 0x8d0ebb40, 0xa623e883, 0xbf38d9c2,
- 0x38a0c50d, 0x21bbf44c, 0x0a96a78f, 0x138d96ce,
- 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca,
- 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97,
- 0xded79850, 0xc7cca911, 0xece1fad2, 0xf5facb93,
- 0x7262d75c, 0x6b79e61d, 0x4054b5de, 0x594f849f,
- 0x160e1258, 0x0f152319, 0x243870da, 0x3d23419b,
- 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864,
- 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60,
- 0xad24e1af, 0xb43fd0ee, 0x9f12832d, 0x8609b26c,
- 0xc94824ab, 0xd05315ea, 0xfb7e4629, 0xe2657768,
- 0x2f3f79f6, 0x362448b7, 0x1d091b74, 0x04122a35,
- 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31,
- 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d,
- 0x838a36fa, 0x9a9107bb, 0xb1bc5478, 0xa8a76539,
- 0x3b83984b, 0x2298a90a, 0x09b5fac9, 0x10aecb88,
- 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd, 0x74c20e8c,
- 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180,
- 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484,
- 0x71418a1a, 0x685abb5b, 0x4377e898, 0x5a6cd9d9,
- 0x152d4f1e, 0x0c367e5f, 0x271b2d9c, 0x3e001cdd,
- 0xb9980012, 0xa0833153, 0x8bae6290, 0x92b553d1,
- 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5,
- 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a,
- 0xca6b79ed, 0xd37048ac, 0xf85d1b6f, 0xe1462a2e,
- 0x66de36e1, 0x7fc507a0, 0x54e85463, 0x4df36522,
- 0x02b2f3e5, 0x1ba9c2a4, 0x30849167, 0x299fa026,
- 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b,
- 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f,
- 0x2c1c24b0, 0x350715f1, 0x1e2a4632, 0x07317773,
- 0x4870e1b4, 0x516bd0f5, 0x7a468336, 0x635db277,
- 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc, 0xe0d7848d,
- 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189,
- 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85,
- 0x674f9842, 0x7e54a903, 0x5579fac0, 0x4c62cb81,
- 0x8138c51f, 0x9823f45e, 0xb30ea79d, 0xaa1596dc,
- 0xe554001b, 0xfc4f315a, 0xd7626299, 0xce7953d8,
- 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4,
- 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0,
- 0x5e7ef3ec, 0x4765c2ad, 0x6c48916e, 0x7553a02f,
- 0x3a1236e8, 0x230907a9, 0x0824546a, 0x113f652b,
- 0x96a779e4, 0x8fbc48a5, 0xa4911b66, 0xbd8a2a27,
- 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23,
- 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e,
- 0x70d024b9, 0x69cb15f8, 0x42e6463b, 0x5bfd777a,
- 0xdc656bb5, 0xc57e5af4, 0xee530937, 0xf7483876,
- 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33, 0x9324fd72,
-};
-
-unsigned int crc32_table1[256] =
-{
- 0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59,
- 0x0709a8dc, 0x06cbc2eb, 0x048d7cb2, 0x054f1685,
- 0x0e1351b8, 0x0fd13b8f, 0x0d9785d6, 0x0c55efe1,
- 0x091af964, 0x08d89353, 0x0a9e2d0a, 0x0b5c473d,
- 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29,
- 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5,
- 0x1235f2c8, 0x13f798ff, 0x11b126a6, 0x10734c91,
- 0x153c5a14, 0x14fe3023, 0x16b88e7a, 0x177ae44d,
- 0x384d46e0, 0x398f2cd7, 0x3bc9928e, 0x3a0bf8b9,
- 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065,
- 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901,
- 0x3157bf84, 0x3095d5b3, 0x32d36bea, 0x331101dd,
- 0x246be590, 0x25a98fa7, 0x27ef31fe, 0x262d5bc9,
- 0x23624d4c, 0x22a0277b, 0x20e69922, 0x2124f315,
- 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71,
- 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad,
- 0x709a8dc0, 0x7158e7f7, 0x731e59ae, 0x72dc3399,
- 0x7793251c, 0x76514f2b, 0x7417f172, 0x75d59b45,
- 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816, 0x7ccf6221,
- 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd,
- 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9,
- 0x6bb5866c, 0x6a77ec5b, 0x68315202, 0x69f33835,
- 0x62af7f08, 0x636d153f, 0x612bab66, 0x60e9c151,
- 0x65a6d7d4, 0x6464bde3, 0x662203ba, 0x67e0698d,
- 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579,
- 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5,
- 0x46c49a98, 0x4706f0af, 0x45404ef6, 0x448224c1,
- 0x41cd3244, 0x400f5873, 0x4249e62a, 0x438b8c1d,
- 0x54f16850, 0x55330267, 0x5775bc3e, 0x56b7d609,
- 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5,
- 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1,
- 0x5deb9134, 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d,
- 0xe1351b80, 0xe0f771b7, 0xe2b1cfee, 0xe373a5d9,
- 0xe63cb35c, 0xe7fed96b, 0xe5b86732, 0xe47a0d05,
- 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461,
- 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd,
- 0xfd13b8f0, 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9,
- 0xfa1a102c, 0xfbd87a1b, 0xf99ec442, 0xf85cae75,
- 0xf300e948, 0xf2c2837f, 0xf0843d26, 0xf1465711,
- 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd,
- 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339,
- 0xde71f5bc, 0xdfb39f8b, 0xddf521d2, 0xdc374be5,
- 0xd76b0cd8, 0xd6a966ef, 0xd4efd8b6, 0xd52db281,
- 0xd062a404, 0xd1a0ce33, 0xd3e6706a, 0xd2241a5d,
- 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049,
- 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895,
- 0xcb4dafa8, 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1,
- 0xcc440774, 0xcd866d43, 0xcfc0d31a, 0xce02b92d,
- 0x91af9640, 0x906dfc77, 0x922b422e, 0x93e92819,
- 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5,
- 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1,
- 0x98b56f24, 0x99770513, 0x9b31bb4a, 0x9af3d17d,
- 0x8d893530, 0x8c4b5f07, 0x8e0de15e, 0x8fcf8b69,
- 0x8a809dec, 0x8b42f7db, 0x89044982, 0x88c623b5,
- 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1,
- 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d,
- 0xa9e2d0a0, 0xa820ba97, 0xaa6604ce, 0xaba46ef9,
- 0xaeeb787c, 0xaf29124b, 0xad6fac12, 0xacadc625,
- 0xa7f18118, 0xa633eb2f, 0xa4755576, 0xa5b73f41,
- 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d,
- 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89,
- 0xb2cddb0c, 0xb30fb13b, 0xb1490f62, 0xb08b6555,
- 0xbbd72268, 0xba15485f, 0xb853f606, 0xb9919c31,
- 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda, 0xbe9834ed,
-};
-
-unsigned int crc32_table0[256] = {
- 0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee,
- 0x8f629757, 0x37def032, 0x256b5fdc, 0x9dd738b9,
- 0xc5b428ef, 0x7d084f8a, 0x6fbde064, 0xd7018701,
- 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733, 0x58631056,
- 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871,
- 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26,
- 0x95ad7f70, 0x2d111815, 0x3fa4b7fb, 0x8718d09e,
- 0x1acfe827, 0xa2738f42, 0xb0c620ac, 0x087a47c9,
- 0xa032af3e, 0x188ec85b, 0x0a3b67b5, 0xb28700d0,
- 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787,
- 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f,
- 0xeae41086, 0x525877e3, 0x40edd80d, 0xf851bf68,
- 0xf02bf8a1, 0x48979fc4, 0x5a22302a, 0xe29e574f,
- 0x7f496ff6, 0xc7f50893, 0xd540a77d, 0x6dfcc018,
- 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0,
- 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7,
- 0x9b14583d, 0x23a83f58, 0x311d90b6, 0x89a1f7d3,
- 0x1476cf6a, 0xaccaa80f, 0xbe7f07e1, 0x06c36084,
- 0x5ea070d2, 0xe61c17b7, 0xf4a9b859, 0x4c15df3c,
- 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b,
- 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c,
- 0x446f98f5, 0xfcd3ff90, 0xee66507e, 0x56da371b,
- 0x0eb9274d, 0xb6054028, 0xa4b0efc6, 0x1c0c88a3,
- 0x81dbb01a, 0x3967d77f, 0x2bd27891, 0x936e1ff4,
- 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed,
- 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba,
- 0xfe92dfec, 0x462eb889, 0x549b1767, 0xec277002,
- 0x71f048bb, 0xc94c2fde, 0xdbf98030, 0x6345e755,
- 0x6b3fa09c, 0xd383c7f9, 0xc1366817, 0x798a0f72,
- 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825,
- 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d,
- 0x21e91f24, 0x99557841, 0x8be0d7af, 0x335cb0ca,
- 0xed59b63b, 0x55e5d15e, 0x47507eb0, 0xffec19d5,
- 0x623b216c, 0xda874609, 0xc832e9e7, 0x708e8e82,
- 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a,
- 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d,
- 0xbd40e1a4, 0x05fc86c1, 0x1749292f, 0xaff54e4a,
- 0x322276f3, 0x8a9e1196, 0x982bbe78, 0x2097d91d,
- 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0, 0x6a4166a5,
- 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2,
- 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb,
- 0xc2098e52, 0x7ab5e937, 0x680046d9, 0xd0bc21bc,
- 0x88df31ea, 0x3063568f, 0x22d6f961, 0x9a6a9e04,
- 0x07bda6bd, 0xbf01c1d8, 0xadb46e36, 0x15080953,
- 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174,
- 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623,
- 0xd8c66675, 0x607a0110, 0x72cfaefe, 0xca73c99b,
- 0x57a4f122, 0xef189647, 0xfdad39a9, 0x45115ecc,
- 0x764dee06, 0xcef18963, 0xdc44268d, 0x64f841e8,
- 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf,
- 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907,
- 0x3c9b51be, 0x842736db, 0x96929935, 0x2e2efe50,
- 0x2654b999, 0x9ee8defc, 0x8c5d7112, 0x34e11677,
- 0xa9362ece, 0x118a49ab, 0x033fe645, 0xbb838120,
- 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98,
- 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf,
- 0xd67f4138, 0x6ec3265d, 0x7c7689b3, 0xc4caeed6,
- 0x591dd66f, 0xe1a1b10a, 0xf3141ee4, 0x4ba87981,
- 0x13cb69d7, 0xab770eb2, 0xb9c2a15c, 0x017ec639,
- 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e,
- 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949,
- 0x090481f0, 0xb1b8e695, 0xa30d497b, 0x1bb12e1e,
- 0x43d23e48, 0xfb6e592d, 0xe9dbf6c3, 0x516791a6,
- 0xccb0a91f, 0x740cce7a, 0x66b96194, 0xde0506f1,
-};
-
-unsigned crc32_partial_old (const void *data, int len, unsigned crc) {
- const char *p = data;
- for (; len > 0; len--) {
- crc = crc32_table[(crc ^ *p++) & 0xff] ^ (crc >> 8);
- }
- return crc;
-}
-
-/*
-unsigned crc32_partial_fast (const void *data, int len, unsigned crc) {
- const int *p = (const int *) data;
- int x;
- for (x = (len >> 2); x > 0; x--) {
- crc ^= *p++;
- crc = crc32_table0[crc & 0xff] ^ crc32_table1[(crc & 0xff00) >> 8] ^ crc32_table2[(crc & 0xff0000) >> 16] ^ crc32_table[crc >> 24];
- }
- const char *q = (const char *) p;
- switch (len & 3) {
- case 3:
- crc = crc32_table[(crc ^ *q++) & 0xff] ^ (crc >> 8);
- case 2:
- crc = crc32_table[(crc ^ *q++) & 0xff] ^ (crc >> 8);
- case 1:
- crc = crc32_table[(crc ^ *q++) & 0xff] ^ (crc >> 8);
- }
- return crc;
-}
-*/
-
-unsigned crc32_partial (const void *data, int len, unsigned crc) {
- const int *p = (const int *) data;
- int x;
-#define DO_ONE(v) crc ^= v; crc = crc32_table0[crc & 0xff] ^ crc32_table1[(crc & 0xff00) >> 8] ^ crc32_table2[(crc & 0xff0000) >> 16] ^ crc32_table[crc >> 24];
-#define DO_FOUR(p) DO_ONE((p)[0]); DO_ONE((p)[1]); DO_ONE((p)[2]); DO_ONE((p)[3]);
-
- for (x = (len >> 5); x > 0; x--) {
- DO_FOUR (p);
- DO_FOUR (p + 4);
- p += 8;
- }
- if (len & 16) {
- DO_FOUR (p);
- p += 4;
- }
- if (len & 8) {
- DO_ONE (p[0]);
- DO_ONE (p[1]);
- p += 2;
- }
- if (len & 4) {
- DO_ONE (*p++);
- }
- /*
- for (x = (len >> 2) & 7; x > 0; x--) {
- DO_ONE (*p++);
- }
- */
-#undef DO_ONE
-#undef DO_FOUR
- const char *q = (const char *) p;
- if (len & 2) {
- crc = crc32_table[(crc ^ q[0]) & 0xff] ^ (crc >> 8);
- crc = crc32_table[(crc ^ q[1]) & 0xff] ^ (crc >> 8);
- q += 2;
- }
- if (len & 1) {
- crc = crc32_table[(crc ^ *q++) & 0xff] ^ (crc >> 8);
- }
- return crc;
-}
-
-unsigned compute_crc32 (const void *data, int len) {
- return crc32_partial (data, len, -1) ^ -1;
-}
-
-unsigned long long crc64_table[256] = {
- 0x0000000000000000LL, 0xb32e4cbe03a75f6fLL, 0xf4843657a840a05bLL, 0x47aa7ae9abe7ff34LL,
- 0x7bd0c384ff8f5e33LL, 0xc8fe8f3afc28015cLL, 0x8f54f5d357cffe68LL, 0x3c7ab96d5468a107LL,
- 0xf7a18709ff1ebc66LL, 0x448fcbb7fcb9e309LL, 0x0325b15e575e1c3dLL, 0xb00bfde054f94352LL,
- 0x8c71448d0091e255LL, 0x3f5f08330336bd3aLL, 0x78f572daa8d1420eLL, 0xcbdb3e64ab761d61LL,
- 0x7d9ba13851336649LL, 0xceb5ed8652943926LL, 0x891f976ff973c612LL, 0x3a31dbd1fad4997dLL,
- 0x064b62bcaebc387aLL, 0xb5652e02ad1b6715LL, 0xf2cf54eb06fc9821LL, 0x41e11855055bc74eLL,
- 0x8a3a2631ae2dda2fLL, 0x39146a8fad8a8540LL, 0x7ebe1066066d7a74LL, 0xcd905cd805ca251bLL,
- 0xf1eae5b551a2841cLL, 0x42c4a90b5205db73LL, 0x056ed3e2f9e22447LL, 0xb6409f5cfa457b28LL,
- 0xfb374270a266cc92LL, 0x48190ecea1c193fdLL, 0x0fb374270a266cc9LL, 0xbc9d3899098133a6LL,
- 0x80e781f45de992a1LL, 0x33c9cd4a5e4ecdceLL, 0x7463b7a3f5a932faLL, 0xc74dfb1df60e6d95LL,
- 0x0c96c5795d7870f4LL, 0xbfb889c75edf2f9bLL, 0xf812f32ef538d0afLL, 0x4b3cbf90f69f8fc0LL,
- 0x774606fda2f72ec7LL, 0xc4684a43a15071a8LL, 0x83c230aa0ab78e9cLL, 0x30ec7c140910d1f3LL,
- 0x86ace348f355aadbLL, 0x3582aff6f0f2f5b4LL, 0x7228d51f5b150a80LL, 0xc10699a158b255efLL,
- 0xfd7c20cc0cdaf4e8LL, 0x4e526c720f7dab87LL, 0x09f8169ba49a54b3LL, 0xbad65a25a73d0bdcLL,
- 0x710d64410c4b16bdLL, 0xc22328ff0fec49d2LL, 0x85895216a40bb6e6LL, 0x36a71ea8a7ace989LL,
- 0x0adda7c5f3c4488eLL, 0xb9f3eb7bf06317e1LL, 0xfe5991925b84e8d5LL, 0x4d77dd2c5823b7baLL,
- 0x64b62bcaebc387a1LL, 0xd7986774e864d8ceLL, 0x90321d9d438327faLL, 0x231c512340247895LL,
- 0x1f66e84e144cd992LL, 0xac48a4f017eb86fdLL, 0xebe2de19bc0c79c9LL, 0x58cc92a7bfab26a6LL,
- 0x9317acc314dd3bc7LL, 0x2039e07d177a64a8LL, 0x67939a94bc9d9b9cLL, 0xd4bdd62abf3ac4f3LL,
- 0xe8c76f47eb5265f4LL, 0x5be923f9e8f53a9bLL, 0x1c4359104312c5afLL, 0xaf6d15ae40b59ac0LL,
- 0x192d8af2baf0e1e8LL, 0xaa03c64cb957be87LL, 0xeda9bca512b041b3LL, 0x5e87f01b11171edcLL,
- 0x62fd4976457fbfdbLL, 0xd1d305c846d8e0b4LL, 0x96797f21ed3f1f80LL, 0x2557339fee9840efLL,
- 0xee8c0dfb45ee5d8eLL, 0x5da24145464902e1LL, 0x1a083bacedaefdd5LL, 0xa9267712ee09a2baLL,
- 0x955cce7fba6103bdLL, 0x267282c1b9c65cd2LL, 0x61d8f8281221a3e6LL, 0xd2f6b4961186fc89LL,
- 0x9f8169ba49a54b33LL, 0x2caf25044a02145cLL, 0x6b055fede1e5eb68LL, 0xd82b1353e242b407LL,
- 0xe451aa3eb62a1500LL, 0x577fe680b58d4a6fLL, 0x10d59c691e6ab55bLL, 0xa3fbd0d71dcdea34LL,
- 0x6820eeb3b6bbf755LL, 0xdb0ea20db51ca83aLL, 0x9ca4d8e41efb570eLL, 0x2f8a945a1d5c0861LL,
- 0x13f02d374934a966LL, 0xa0de61894a93f609LL, 0xe7741b60e174093dLL, 0x545a57dee2d35652LL,
- 0xe21ac88218962d7aLL, 0x5134843c1b317215LL, 0x169efed5b0d68d21LL, 0xa5b0b26bb371d24eLL,
- 0x99ca0b06e7197349LL, 0x2ae447b8e4be2c26LL, 0x6d4e3d514f59d312LL, 0xde6071ef4cfe8c7dLL,
- 0x15bb4f8be788911cLL, 0xa6950335e42fce73LL, 0xe13f79dc4fc83147LL, 0x521135624c6f6e28LL,
- 0x6e6b8c0f1807cf2fLL, 0xdd45c0b11ba09040LL, 0x9aefba58b0476f74LL, 0x29c1f6e6b3e0301bLL,
- 0xc96c5795d7870f42LL, 0x7a421b2bd420502dLL, 0x3de861c27fc7af19LL, 0x8ec62d7c7c60f076LL,
- 0xb2bc941128085171LL, 0x0192d8af2baf0e1eLL, 0x4638a2468048f12aLL, 0xf516eef883efae45LL,
- 0x3ecdd09c2899b324LL, 0x8de39c222b3eec4bLL, 0xca49e6cb80d9137fLL, 0x7967aa75837e4c10LL,
- 0x451d1318d716ed17LL, 0xf6335fa6d4b1b278LL, 0xb199254f7f564d4cLL, 0x02b769f17cf11223LL,
- 0xb4f7f6ad86b4690bLL, 0x07d9ba1385133664LL, 0x4073c0fa2ef4c950LL, 0xf35d8c442d53963fLL,
- 0xcf273529793b3738LL, 0x7c0979977a9c6857LL, 0x3ba3037ed17b9763LL, 0x888d4fc0d2dcc80cLL,
- 0x435671a479aad56dLL, 0xf0783d1a7a0d8a02LL, 0xb7d247f3d1ea7536LL, 0x04fc0b4dd24d2a59LL,
- 0x3886b22086258b5eLL, 0x8ba8fe9e8582d431LL, 0xcc0284772e652b05LL, 0x7f2cc8c92dc2746aLL,
- 0x325b15e575e1c3d0LL, 0x8175595b76469cbfLL, 0xc6df23b2dda1638bLL, 0x75f16f0cde063ce4LL,
- 0x498bd6618a6e9de3LL, 0xfaa59adf89c9c28cLL, 0xbd0fe036222e3db8LL, 0x0e21ac88218962d7LL,
- 0xc5fa92ec8aff7fb6LL, 0x76d4de52895820d9LL, 0x317ea4bb22bfdfedLL, 0x8250e80521188082LL,
- 0xbe2a516875702185LL, 0x0d041dd676d77eeaLL, 0x4aae673fdd3081deLL, 0xf9802b81de97deb1LL,
- 0x4fc0b4dd24d2a599LL, 0xfceef8632775faf6LL, 0xbb44828a8c9205c2LL, 0x086ace348f355aadLL,
- 0x34107759db5dfbaaLL, 0x873e3be7d8faa4c5LL, 0xc094410e731d5bf1LL, 0x73ba0db070ba049eLL,
- 0xb86133d4dbcc19ffLL, 0x0b4f7f6ad86b4690LL, 0x4ce50583738cb9a4LL, 0xffcb493d702be6cbLL,
- 0xc3b1f050244347ccLL, 0x709fbcee27e418a3LL, 0x3735c6078c03e797LL, 0x841b8ab98fa4b8f8LL,
- 0xadda7c5f3c4488e3LL, 0x1ef430e13fe3d78cLL, 0x595e4a08940428b8LL, 0xea7006b697a377d7LL,
- 0xd60abfdbc3cbd6d0LL, 0x6524f365c06c89bfLL, 0x228e898c6b8b768bLL, 0x91a0c532682c29e4LL,
- 0x5a7bfb56c35a3485LL, 0xe955b7e8c0fd6beaLL, 0xaeffcd016b1a94deLL, 0x1dd181bf68bdcbb1LL,
- 0x21ab38d23cd56ab6LL, 0x9285746c3f7235d9LL, 0xd52f0e859495caedLL, 0x6601423b97329582LL,
- 0xd041dd676d77eeaaLL, 0x636f91d96ed0b1c5LL, 0x24c5eb30c5374ef1LL, 0x97eba78ec690119eLL,
- 0xab911ee392f8b099LL, 0x18bf525d915feff6LL, 0x5f1528b43ab810c2LL, 0xec3b640a391f4fadLL,
- 0x27e05a6e926952ccLL, 0x94ce16d091ce0da3LL, 0xd3646c393a29f297LL, 0x604a2087398eadf8LL,
- 0x5c3099ea6de60cffLL, 0xef1ed5546e415390LL, 0xa8b4afbdc5a6aca4LL, 0x1b9ae303c601f3cbLL,
- 0x56ed3e2f9e224471LL, 0xe5c372919d851b1eLL, 0xa26908783662e42aLL, 0x114744c635c5bb45LL,
- 0x2d3dfdab61ad1a42LL, 0x9e13b115620a452dLL, 0xd9b9cbfcc9edba19LL, 0x6a978742ca4ae576LL,
- 0xa14cb926613cf817LL, 0x1262f598629ba778LL, 0x55c88f71c97c584cLL, 0xe6e6c3cfcadb0723LL,
- 0xda9c7aa29eb3a624LL, 0x69b2361c9d14f94bLL, 0x2e184cf536f3067fLL, 0x9d36004b35545910LL,
- 0x2b769f17cf112238LL, 0x9858d3a9ccb67d57LL, 0xdff2a94067518263LL, 0x6cdce5fe64f6dd0cLL,
- 0x50a65c93309e7c0bLL, 0xe388102d33392364LL, 0xa4226ac498dedc50LL, 0x170c267a9b79833fLL,
- 0xdcd7181e300f9e5eLL, 0x6ff954a033a8c131LL, 0x28532e49984f3e05LL, 0x9b7d62f79be8616aLL,
- 0xa707db9acf80c06dLL, 0x14299724cc279f02LL, 0x5383edcd67c06036LL, 0xe0ada17364673f59LL
-};
-
-unsigned long long crc64_partial (const void *data, int len, unsigned long long crc) {
- const char *p = data;
- for (; len > 0; len--) {
- crc = crc64_table[(crc ^ *p++) & 0xff] ^ (crc >> 8);
- }
- return crc;
-}
-
-unsigned long long crc64 (const void *data, int len) {
- return crc64_partial (data, len, -1LL) ^ -1LL;
-}
-
-static unsigned gf32_matrix_times (unsigned *matrix, unsigned vector) {
- unsigned sum = 0;
- while (vector) {
- if (vector & 1) {
- sum ^= *matrix;
- }
- vector >>= 1;
- matrix++;
- }
- return sum;
-}
-
-static void gf32_matrix_square (unsigned *square, unsigned *matrix) {
- int n = 0;
- do {
- square[n] = gf32_matrix_times (matrix, matrix[n]);
- } while (++n < 32);
-}
-
-unsigned compute_crc32_combine (unsigned crc1, unsigned crc2, int len2) {
- assert (len2 < (1 << 29));
- static int power_buf_initialized = 0;
- static unsigned power_buf[1024];
- int n;
- /* degenerate case (also disallow negative lengths) */
- if (len2 <= 0) {
- return crc1;
- }
- if (!power_buf_initialized) {
- power_buf[0] = 0xedb88320UL;
- for (n = 0; n < 31; n++) {
- power_buf[n+1] = 1U << n;
- }
- for (n = 1; n < 32; n++) {
- gf32_matrix_square (power_buf + (n << 5), power_buf + ((n - 1) << 5));
- }
- power_buf_initialized = 1;
- }
-
- unsigned int *p = power_buf + 64;
- do {
- p += 32;
- if (len2 & 1) {
- crc1 = gf32_matrix_times (p, crc1);
- }
- len2 >>= 1;
- } while (len2);
- return crc1 ^ crc2;
-}
-
-
-/********************************* crc32 repair ************************/
-struct fcb_table_entry {
- unsigned p; //zeta ^ k
- int i;
-};
-
-static inline unsigned gf32_mod (unsigned long long r, int high_bit) {
- int j = high_bit;
- for (j = high_bit; j >= 32; j--) {
- if ((1ULL << j) & r) {
- r ^= 0x04C11DB7ULL << (j - 32);
- }
- }
- return (unsigned) r;
-}
-
-static unsigned gf32_mult (unsigned a, unsigned b) {
- int i;
- const unsigned long long m = b;
- unsigned long long r = 0;
- for (i = 0; i < 32; i++) {
- if (a & (1U << i)) {
- r ^= m << i;
- }
- }
- return gf32_mod (r, 62);
-}
-
-static unsigned gf32_shl (unsigned int a, int shift) {
- unsigned long long r = a;
- r <<= shift;
- return gf32_mod (r, 31 + shift);
-}
-
-static unsigned gf32_pow (unsigned a, int k) {
- if (!k) { return 1; }
- unsigned x = gf32_pow (gf32_mult (a, a), k >> 1);
- if (k & 1) {
- x = gf32_mult (x, a);
- }
- return x;
-}
-
-static int cmp_fcb_table_entry (const void *a, const void *b) {
- const struct fcb_table_entry *x = a;
- const struct fcb_table_entry *y = b;
- if (x->p < y->p) { return -1; }
- if (x->p > y->p) { return 1; }
- if (x->i < y->i) { return -1; }
- if (x->i > y->i) { return 1; }
- return 0;
-}
-
-#define GROUP_SWAP(x,m,s) ((x & m) << s) | ((x & (~m)) >> s)
-static unsigned revbin (unsigned x) {
- x = GROUP_SWAP(x,0x55555555U,1);
- x = GROUP_SWAP(x,0x33333333U,2);
- x = GROUP_SWAP(x,0x0f0f0f0fU,4);
- x = __builtin_bswap32 (x);
- return x;
-}
-#undef GROUP_SWAP
-
-static inline unsigned xmult (unsigned a) {
- unsigned r = a << 1;
- if (a & (1U<<31)) {
- r ^= 0x04C11DB7U;
- }
- return r;
-}
-
-static int find_corrupted_bit (int size, unsigned d) {
- int i, j;
- size += 4;
- d = revbin (d);
- int n = size << 3;
- int r = (int) (sqrt (n) + 0.5);
- struct fcb_table_entry *T = calloc (r, sizeof (struct fcb_table_entry));
- assert (T != NULL);
- T[0].i = 0;
- T[0].p = 1;
- for (i = 1; i < r; i++) {
- T[i].i = i;
- T[i].p = xmult (T[i-1].p);
- }
- assert (xmult (0x82608EDB) == 1);
- qsort (T, r, sizeof (T[0]), cmp_fcb_table_entry);
- unsigned q = gf32_pow (0x82608EDB, r);
-
- unsigned A[32];
- for (i = 0; i < 32; i++) {
- A[i] = gf32_shl (q, i);
- }
-
- unsigned x = d;
- int max_j = n / r, res = -1;
- for (j = 0; j <= max_j; j++) {
- int a = -1, b = r;
- while (b - a > 1) {
- int c = ((a + b) >> 1);
- if (T[c].p <= x) { a = c; } else { b = c; }
- }
- if (a >= 0 && T[a].p == x) {
- res = T[a].i + r * j;
- break;
- }
- x = gf32_matrix_times (A, x);
- }
- free (T);
- return res;
-}
-
-static int repair_bit (unsigned char *input, int l, int k) {
- if (k < 0) {
- return -1;
- }
- int idx = k >> 5, bit = k & 31, i = (l - 1) - (idx - 1) * 4;
- while (bit >= 8) {
- i--;
- bit -= 8;
- }
- if (i < 0) {
- return -2;
- }
- if (i >= l) {
- return -3;
- }
- int j = 7 - bit;
- input[i] ^= 1 << j;
- return 0;
-}
-
-int crc32_check_and_repair (void *input, int l, unsigned *input_crc32, int force_exit) {
- unsigned computed_crc32 = compute_crc32 (input, l);
- const unsigned crc32_diff = computed_crc32 ^ (*input_crc32);
- if (!crc32_diff) {
- return 0;
- }
- int k = find_corrupted_bit (l, crc32_diff);
- int r = repair_bit (input, l, k);
- if (!r) {
- assert (compute_crc32 (input, l) == *input_crc32);
- return 1;
- }
- if (!(crc32_diff & (crc32_diff - 1))) { /* crc32_diff is power of 2 */
- *input_crc32 = computed_crc32;
- return 2;
- }
- assert (!force_exit);
- *input_crc32 = computed_crc32;
- return -1;
-}
diff --git a/crc32.h b/crc32.h
deleted file mode 100644
index fdf8da8..0000000
--- a/crc32.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- This file is part of VK/KittenPHP-DB-Engine Library.
-
- VK/KittenPHP-DB-Engine Library is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation, either version 2 of the License, or
- (at your option) any later version.
-
- VK/KittenPHP-DB-Engine Library 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 Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with VK/KittenPHP-DB-Engine Library. If not, see .
-
- Copyright 2009-2012 Vkontakte Ltd
- 2009-2012 Nikolai Durov
- 2009-2012 Andrei Lopatin
- 2012 Anton Maydell
-*/
-
-#ifndef __CRC32_H__
-#define __CRC32_H__
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern unsigned int crc32_table[256];
-unsigned crc32_partial (const void *data, int len, unsigned crc);
- //unsigned crc32_partial_fast (const void *data, int len, unsigned crc);
- //unsigned crc32_partial_fastest (const void *data, int len, unsigned crc);
-unsigned compute_crc32 (const void *data, int len);
-unsigned compute_crc32_combine (unsigned crc1, unsigned crc2, int len2);
-
-extern unsigned long long crc64_table[256];
-unsigned long long crc64_partial (const void *data, int len, unsigned long long crc);
-unsigned long long crc64 (const void *data, int len);
-
-//unsigned gf32_matrix_times (unsigned *matrix, unsigned vector);
-
-/* crc32_check_and_repair returns
- 0 : Cyclic redundancy check is ok
- 1 : Cyclic redundancy check fails, but we fix one bit in input
- 2 : Cyclic redundancy check fails, but we fix one bit in input_crc32
- -1 : Cyclic redundancy check fails, no repair possible.
- In this case *input_crc32 will be equal crc32 (input, l)
-
- Case force_exit == 1 (case 1, 2: kprintf call, case -1: assert fail).
-*/
-int crc32_check_and_repair (void *input, int l, unsigned *input_crc32, int force_exit);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/encrypted_scheme.tl b/encrypted_scheme.tl
deleted file mode 120000
index b45af3d..0000000
--- a/encrypted_scheme.tl
+++ /dev/null
@@ -1 +0,0 @@
-encrypted_scheme17.tl
\ No newline at end of file
diff --git a/encrypted_scheme16.tl b/encrypted_scheme16.tl
deleted file mode 100644
index eb58ed4..0000000
--- a/encrypted_scheme16.tl
+++ /dev/null
@@ -1,22 +0,0 @@
----types---
-decryptedMessageLayer#99a438cf layer:int message:DecryptedMessage = DecryptedMessageLayer;
-decryptedMessage#1f814f1f random_id:long random_bytes:bytes message:string media:DecryptedMessageMedia = DecryptedMessage;
-decryptedMessageService#aa48327d random_id:long random_bytes:bytes action:DecryptedMessageAction = DecryptedMessage;
-decryptedMessageMediaEmpty#89f5c4a = DecryptedMessageMedia;
-decryptedMessageMediaPhoto#32798a8c thumb:bytes thumb_w:int thumb_h:int w:int h:int size:int key:bytes iv:bytes = DecryptedMessageMedia;
-//decryptedMessageMediaVideo#4cee6ef3 thumb:bytes thumb_w:int thumb_h:int duration:int w:int h:int size:int key:bytes iv:bytes = DecryptedMessageMedia;
-decryptedMessageMediaGeoPoint#35480a59 lat:double long:double = DecryptedMessageMedia;
-decryptedMessageMediaContact#588a0a97 phone_number:string first_name:string last_name:string user_id:int = DecryptedMessageMedia;
-decryptedMessageActionSetMessageTTL#a1733aec ttl_seconds:int = DecryptedMessageAction;
-
-decryptedMessageMediaDocument#b095434b thumb:bytes thumb_w:int thumb_h:int file_name:string mime_type:string size:int key:bytes iv:bytes = DecryptedMessageMedia;
-//decryptedMessageMediaAudio#6080758f duration:int size:int key:bytes iv:bytes = DecryptedMessageMedia;
-
-decryptedMessageMediaVideo#524a415d thumb:bytes thumb_w:int thumb_h:int duration:int mime_type:string w:int h:int size:int key:bytes iv:bytes = DecryptedMessageMedia;
-decryptedMessageMediaAudio#57e0a9cb duration:int mime_type:string size:int key:bytes iv:bytes = DecryptedMessageMedia;
-decryptedMessageActionReadMessages#c4f40be random_ids:Vector = DecryptedMessageAction;
-decryptedMessageActionDeleteMessages#65614304 random_ids:Vector = DecryptedMessageAction;
-decryptedMessageActionScreenshotMessages#8ac1f475 random_ids:Vector = DecryptedMessageAction;
-decryptedMessageActionFlushHistory#6719e45c = DecryptedMessageAction;
-decryptedMessageActionNotifyLayer#f3048883 layer:int = DecryptedMessageAction;
----functions---
diff --git a/encrypted_scheme17.tl b/encrypted_scheme17.tl
deleted file mode 100644
index 95e661b..0000000
--- a/encrypted_scheme17.tl
+++ /dev/null
@@ -1,31 +0,0 @@
----types---
-decryptedMessageLayer#1be31789 layer:int message:DecryptedMessage = DecryptedMessageLayer;
-decryptedMessage_l16#1f814f1f random_id:long random_bytes:bytes message:string media:DecryptedMessageMedia = DecryptedMessage;
-decryptedMessageService_l16#aa48327d random_id:long random_bytes:bytes action:DecryptedMessageAction = DecryptedMessage;
-
-decryptedMessage#204d3878 in_seq_no:int out_seq_no:int ttl:int random_id:long random_bytes:bytes message:string media:DecryptedMessageMedia = DecryptedMessage;
-decryptedMessageService#73164160 in_seq_no:int out_seq_no:int random_id:long random_bytes:bytes action:DecryptedMessageAction = DecryptedMessage;
-
-decryptedMessageMediaEmpty#89f5c4a = DecryptedMessageMedia;
-decryptedMessageMediaPhoto#32798a8c thumb:bytes thumb_w:int thumb_h:int w:int h:int size:int key:bytes iv:bytes = DecryptedMessageMedia;
-//decryptedMessageMediaVideo#4cee6ef3 thumb:bytes thumb_w:int thumb_h:int duration:int w:int h:int size:int key:bytes iv:bytes = DecryptedMessageMedia;
-decryptedMessageMediaGeoPoint#35480a59 lat:double long:double = DecryptedMessageMedia;
-decryptedMessageMediaContact#588a0a97 phone_number:string first_name:string last_name:string user_id:int = DecryptedMessageMedia;
-decryptedMessageActionSetMessageTTL#a1733aec ttl_seconds:int = DecryptedMessageAction;
-
-decryptedMessageMediaDocument#b095434b thumb:bytes thumb_w:int thumb_h:int file_name:string mime_type:string size:int key:bytes iv:bytes = DecryptedMessageMedia;
-//decryptedMessageMediaAudio#6080758f duration:int size:int key:bytes iv:bytes = DecryptedMessageMedia;
-
-decryptedMessageMediaVideo#524a415d thumb:bytes thumb_w:int thumb_h:int duration:int mime_type:string w:int h:int size:int key:bytes iv:bytes = DecryptedMessageMedia;
-decryptedMessageMediaAudio#57e0a9cb duration:int mime_type:string size:int key:bytes iv:bytes = DecryptedMessageMedia;
-decryptedMessageActionReadMessages#c4f40be random_ids:Vector = DecryptedMessageAction;
-decryptedMessageActionDeleteMessages#65614304 random_ids:Vector = DecryptedMessageAction;
-decryptedMessageActionScreenshotMessages#8ac1f475 random_ids:Vector = DecryptedMessageAction;
-decryptedMessageActionFlushHistory#6719e45c = DecryptedMessageAction;
-decryptedMessageActionNotifyLayer#f3048883 layer:int = DecryptedMessageAction;
-
-decryptedMessageActionResend#511110b0 start_seq_no:int end_seq_no:int = DecryptedMessageAction;
-
-decryptedMessageActionTyping#ccb27641 action:SendMessageAction = DecryptedMessageAction;
-
----functions---
diff --git a/gen_constants_h.awk b/gen_constants_h.awk
deleted file mode 100644
index 17e7e12..0000000
--- a/gen_constants_h.awk
+++ /dev/null
@@ -1,37 +0,0 @@
-BEGIN {
- print "/*";
- print " This file is part of telegram-client.";
- print "";
- print " Telegram-client is free software: you can redistribute it and/or modify";
- print " it under the terms of the GNU General Public License as published by";
- print " the Free Software Foundation, either version 2 of the License, or";
- print " (at your option) any later version.";
- print "";
- print " Telegram-client is distributed in the hope that it will be useful,";
- print " but WITHOUT ANY WARRANTY; without even the implied warranty of";
- print " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the";
- print " GNU General Public License for more details.";
- print "";
- print " You should have received a copy of the GNU General Public License";
- print " along with this telegram-client. If not, see .";
- print "";
- print " Copyright Vitaly Valtman 2013";
- print "*/";
- print "#ifndef CONSTANTS_H";
- print "#define CONSTANTS_H";
-}
-// {
- if (split ($1, a, "#") == 2) {
- gsub (/[ABCDEFGHIJKLMNOPQRSTUVWXYZ]/, "_&", a[1]);
- gsub (/[.]/, "_", a[1]);
- if (a[2] in h) {
- print "ERROR: Duplicate magic " a[2] " for define " a[1] " and " h[a[2]] >"/dev/stderr/"
- exit 1;
- }
- h[a[2]] = a[1];
- print "#define", "CODE_" tolower(a[1]), "0x" a[2];
- }
-}
-END {
- print "#endif";
-}
diff --git a/generate.c b/generate.c
deleted file mode 100644
index f42177c..0000000
--- a/generate.c
+++ /dev/null
@@ -1,1829 +0,0 @@
-/*
- This file is part of tgl-libary/generate
-
- Tgl-library/generate 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.
-
- Tgl-library/generate 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.
-
- You should have received a copy of the GNU General Public License
- along with this tgl-library/generate. If not, see .
-
- Copyright Vitaly Valtman 2014
-
- It is derivative work of VK/KittenPHP-DB-Engine (https://github.com/vk-com/kphp-kdb/)
- Copyright 2012-2013 Vkontakte Ltd
- 2012-2013 Vitaliy Valtman
-*/
-
-#define _GNU_SOURCE
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "tl-tl.h"
-#include "generate.h"
-
-#include "tree.h"
-#include "config.h"
-
-int header;
-
-#define tl_type_name_cmp(a,b) (a->name > b->name ? 1 : a->name < b->name ? -1 : 0)
-
-DEFINE_TREE (tl_type, struct tl_type *, tl_type_name_cmp, 0)
-DEFINE_TREE (tl_combinator, struct tl_combinator *, tl_type_name_cmp, 0)
-
-struct tree_tl_type *type_tree;
-struct tree_tl_combinator *function_tree;
-
-void tl_function_insert_by_name (struct tl_combinator *c) {
- function_tree = tree_insert_tl_combinator (function_tree, c, lrand48 ());
-}
-
-struct tl_type *tl_type_get_by_name (int name) {
- static struct tl_type t;
- t.name = name;
-
- return tree_lookup_tl_type (type_tree, &t);
-}
-
-void tl_type_insert_by_name (struct tl_type *t) {
- type_tree = tree_insert_tl_type (type_tree, t, lrand48 ());
-}
-
-int is_empty (struct tl_type *t) {
- if (t->name == NAME_INT || t->name == NAME_LONG || t->name == NAME_DOUBLE || t->name == NAME_STRING) { return 1; }
- if (t->constructors_num != 1) { return 0; }
- int count = 0;
- int i;
- struct tl_combinator *c = t->constructors[0];
- for (i = 0; i < c->args_num; i++) {
- if (!(c->args[i]->flags & FLAG_OPT_VAR)) { count ++; }
- }
- return count == 1;
-}
-
-
-static char buf[1 << 20];
-int buf_size;
-int *buf_ptr = (int *)buf;
-int *buf_end;
-#ifndef DISABLE_EXTF
-int skip_only = 0;
-#else
-int skip_only = 1;
-#endif
-
-int verbosity;
-
-int get_int (void) {
- assert (buf_ptr < buf_end);
- return *(buf_ptr ++);
-}
-
-long long get_long (void) {
- assert (buf_ptr + 1 < buf_end);
- long long r = *(long long *)buf_ptr;
- buf_ptr += 2;
- return r;
-}
-
-static void *malloc0 (int size) {
- void *r = malloc (size);
- assert (r);
- memset (r, 0, size);
- return r;
-}
-
-char *get_string (void) {
- int l = *(unsigned char *)buf_ptr;
- assert (l != 0xff);
-
- char *res;
- int tlen = 0;
- if (l == 0xfe) {
- l = ((unsigned)get_int ()) >> 8;
- res = (char *)buf_ptr;
- tlen = l;
- } else {
- res = ((char *)buf_ptr) + 1;
- tlen = 1 + l;
- }
-
- int len = l;
-
- tlen += ((-tlen) & 3);
- assert (!(tlen & 3));
-
- buf_ptr += tlen / 4;
- assert (buf_ptr <= buf_end);
-
- char *r = strndup (res, len);
- assert (r);
- return r;
-}
-
-
-int tn, fn, cn;
-struct tl_type **tps;
-struct tl_combinator **fns;
-
-struct tl_tree *read_tree (int *var_num);
-struct tl_tree *read_nat_expr (int *var_num);
-struct tl_tree *read_type_expr (int *var_num);
-int read_args_list (struct arg **args, int args_num, int *var_num);
-
-#define use_var_nat_full_form(x) 0
-
-void *int_to_var_nat_const_init (long long x) {
- if (use_var_nat_full_form (x)) {
- struct tl_tree_nat_const *T = malloc (sizeof (*T));
- assert (T);
- T->self.flags = 0;
- T->self.methods = &tl_pnat_const_full_methods;
- T->value = x;
- return T;
- } else {
- return (void *)(long)(x * 2 - 0x80000001l);
- }
-}
-
-long long var_nat_const_to_int (void *x) {
- if (((long)x) & 1) {
- return (((long)x) + 0x80000001l) / 2;
- } else {
- return ((struct tl_tree_nat_const *)x)->value;
- }
-}
-
-int tl_tree_type_type (struct tl_tree *x) {
- return NODE_TYPE_TYPE;
-}
-
-int tl_tree_type_array (struct tl_tree *x) {
- return NODE_TYPE_ARRAY;
-}
-
-int tl_tree_type_nat_const (struct tl_tree *x) {
- return NODE_TYPE_NAT_CONST;
-}
-
-int tl_tree_type_var_num (struct tl_tree *x) {
- return NODE_TYPE_VAR_NUM;
-}
-
-int tl_tree_type_var_type (struct tl_tree *x) {
- return NODE_TYPE_VAR_TYPE;
-}
-
-struct tl_tree_methods tl_var_num_methods = {
- .type = tl_tree_type_var_num
-};
-
-struct tl_tree_methods tl_var_type_methods = {
- .type = tl_tree_type_var_type
-};
-
-struct tl_tree_methods tl_type_methods = {
- .type = tl_tree_type_type
-};
-
-struct tl_tree_methods tl_nat_const_methods = {
- .type = tl_tree_type_nat_const
-};
-
-struct tl_tree_methods tl_array_methods = {
- .type = tl_tree_type_array
-};
-
-struct tl_tree_methods tl_ptype_methods = {
- .type = tl_tree_type_type
-};
-
-struct tl_tree_methods tl_parray_methods = {
- .type = tl_tree_type_array
-};
-
-struct tl_tree_methods tl_pvar_num_methods = {
- .type = tl_tree_type_var_num
-};
-
-struct tl_tree_methods tl_pvar_type_methods = {
- .type = tl_tree_type_var_type
-};
-
-struct tl_tree_methods tl_nat_const_full_methods = {
- .type = tl_tree_type_nat_const
-};
-
-struct tl_tree_methods tl_pnat_const_full_methods = {
- .type = tl_tree_type_nat_const
-};
-
-struct tl_tree *read_num_const (int *var_num) {
- return (void *)int_to_var_nat_const_init (get_int ());
-}
-
-
-int gen_uni_skip (struct tl_tree *t, char *cur_name, int *vars, int first, int fun) {
- assert (t);
- int x = TL_TREE_METHODS (t)->type (t);
- int l = 0;
- int i;
- int j;
- struct tl_tree_type *t1;
- struct tl_tree_array *t2;
- int y;
- int L = strlen (cur_name);
- char *fail = fun ? "return 0;" : "return -1;";
- switch (x) {
- case NODE_TYPE_TYPE:
- t1 = (void *)t;
- if (!first) {
- printf (" if (ODDP(%s) || %s->type->name != 0x%08x) { %s }\n", cur_name, cur_name, t1->type->name, fail);
- } else {
- printf (" if (ODDP(%s) || (%s->type->name != 0x%08x && %s->type->name != 0x%08x)) { %s }\n", cur_name, cur_name, t1->type->name, cur_name, ~t1->type->name, fail);
- }
- for (i = 0; i < t1->children_num; i++) {
- sprintf (cur_name + L, "->params[%d]", i);
- gen_uni_skip (t1->children[i], cur_name, vars, 0, fun);
- cur_name[L] = 0;
- }
- return 0;
- case NODE_TYPE_NAT_CONST:
- printf (" if (EVENP(%s) || ((long)%s) != %lld) { %s }\n", cur_name, cur_name, var_nat_const_to_int (t) * 2 + 1, fail);
- return 0;
- case NODE_TYPE_ARRAY:
- printf (" if (ODDP(%s) || %s->type->name != TL_TYPE_ARRAY) { %s }\n", cur_name, cur_name, fail);
- t2 = (void *)t;
-
- sprintf (cur_name + L, "->params[0]");
- y = gen_uni_skip (t2->multiplicity, cur_name, vars, 0, fun);
- cur_name[L] = 0;
-
- sprintf (cur_name + L, "->params[1]");
- y += gen_uni_skip (t2->args[0]->type, cur_name, vars, 0, fun);
- cur_name[L] = 0;
- return 0;
- case NODE_TYPE_VAR_TYPE:
- printf (" if (ODDP(%s)) { %s }\n", cur_name, fail);
- i = ((struct tl_tree_var_type *)t)->var_num;
- if (!vars[i]) {
- printf (" struct paramed_type *var%d = %s; assert (var%d);\n", i, cur_name, i);
- vars[i] = 1;
- } else if (vars[i] == 1) {
- printf (" if (compare_types (var%d, %s) < 0) { %s }\n", i, cur_name, fail);
- } else {
- assert (0);
- return -1;
- }
- return l;
- case NODE_TYPE_VAR_NUM:
- printf (" if (EVENP(%s)) { %s }\n", cur_name, fail);
- i = ((struct tl_tree_var_num *)t)->var_num;
- j = ((struct tl_tree_var_num *)t)->dif;
- if (!vars[i]) {
- printf (" struct paramed_type *var%d = ((void *)%s) + %d; assert (var%d);\n", i, cur_name, 2 * j, i);
- vars[i] = 2;
- } else if (vars[i] == 2) {
- printf (" if (var%d != ((void *)%s) + %d) { %s }\n", i, cur_name, 2 * j, fail);
- } else {
- assert (0);
- return -1;
- }
- return 0;
- default:
- assert (0);
- return -1;
- }
-}
-
-void print_offset (int len) {
- int i;
- for (i = 0; i < len; i++) { printf (" "); }
-}
-
-int gen_create (struct tl_tree *t, int *vars, int offset) {
- int x = TL_TREE_METHODS (t)->type (t);
- int i;
- struct tl_tree_type *t1;
- struct tl_tree_array *t2;
- switch (x) {
- case NODE_TYPE_TYPE:
- print_offset (offset);
- printf ("&(struct paramed_type){\n");
- print_offset (offset + 2);
- t1 = (void *)t;
- if (t1->self.flags & FLAG_BARE) {
- printf (".type = &(struct tl_type_descr) {.name = 0x%08x, .id = \"Bare_%s\", .params_num = %d, .params_types = %lld},\n", ~t1->type->name, t1->type->id, t1->type->arity, t1->type->params_types);
- } else {
- printf (".type = &(struct tl_type_descr) {.name = 0x%08x, .id = \"%s\", .params_num = %d, .params_types = %lld},\n", t1->type->name, t1->type->id, t1->type->arity, t1->type->params_types);
- }
- if (t1->children_num) {
- print_offset (offset + 2);
- printf (".params = (struct paramed_type *[]){\n");
- for (i = 0; i < t1->children_num; i++) {
- assert (gen_create (t1->children[i], vars, offset + 4) >= 0);
- printf (",\n");
- }
- print_offset (offset + 2);
- printf ("}\n");
- } else {
- print_offset (offset + 2);
- printf (".params = 0,\n");
- }
- print_offset (offset);
- printf ("}");
- return 0;
- case NODE_TYPE_NAT_CONST:
- print_offset (offset);
- printf ("INT2PTR (%d)", (int)var_nat_const_to_int (t));
- return 0;
- case NODE_TYPE_ARRAY:
- print_offset (offset);
- printf ("&(struct paramed_type){\n");
- print_offset (offset + 2);
- t2 = (void *)t;
- printf (".type = &(struct tl_type_descr) {.name = NAME_ARRAY, .id = \"array\", .params_num = 2, .params_types = 1},\n");
- print_offset (offset + 2);
- printf (".params = (struct paramed_type **){\n");
- gen_create (t2->multiplicity, vars, offset + 4);
- printf (",\n");
- gen_create (t2->args[0]->type, vars, offset + 4);
- printf (",\n");
- print_offset (offset + 2);
- printf ("}\n");
- print_offset (offset);
- printf ("}");
- return 0;
- case NODE_TYPE_VAR_TYPE:
- print_offset (offset);
- printf ("var%d", ((struct tl_tree_var_type *)t)->var_num);
- return 0;
- case NODE_TYPE_VAR_NUM:
- print_offset (offset);
- printf ("((void *)var%d) + %d", ((struct tl_tree_var_type *)t)->var_num, 2 * ((struct tl_tree_var_num *)t)->dif);
- return 0;
- default:
- assert (0);
- return -1;
- }
-}
-
-int gen_field_skip (struct arg *arg, int *vars, int num) {
- assert (arg);
- char *offset = " ";
- int o = 0;
- if (arg->exist_var_num >= 0) {
- printf (" if (PTR2INT (var%d) & (1 << %d)) {\n", arg->exist_var_num, arg->exist_var_bit);
- offset = " ";
- o = 2;
- }
- if (arg->var_num >= 0) {
- assert (TL_TREE_METHODS (arg->type)->type (arg->type) == NODE_TYPE_TYPE);
- int t = ((struct tl_tree_type *)arg->type)->type->name;
- if (t == NAME_VAR_TYPE) {
- fprintf (stderr, "Not supported yet\n");
- assert (0);
- } else {
- assert (t == NAME_VAR_NUM);
- if (vars[arg->var_num] == 0) {
- printf ("%sif (in_remaining () < 4) { return -1;}\n", offset);
- printf ("%sstruct paramed_type *var%d = INT2PTR (fetch_int ());\n", offset, arg->var_num);
- vars[arg->var_num] = 2;
- } else if (vars[arg->var_num] == 2) {
- printf ("%sif (in_remaining () < 4) { return -1;}\n", offset);
- printf ("%sif (vars%d != INT2PTR (fetch_int ())) { return -1; }\n", offset, arg->var_num);
- } else {
- assert (0);
- return -1;
- }
- }
- } else {
- int t = TL_TREE_METHODS (arg->type)->type (arg->type);
- if (t == NODE_TYPE_TYPE || t == NODE_TYPE_VAR_TYPE) {
- printf ("%sstruct paramed_type *field%d = \n", offset, num);
- assert (gen_create (arg->type, vars, 2 + o) >= 0);
- printf (";\n");
- int bare = arg->flags & FLAG_BARE;
- if (!bare && t == NODE_TYPE_TYPE) {
- bare = ((struct tl_tree_type *)arg->type)->self.flags & FLAG_BARE;
- }
- if (!bare) {
- printf ("%sif (skip_type_%s (field%d) < 0) { return -1;}\n", offset, t == NODE_TYPE_VAR_TYPE ? "any" : ((struct tl_tree_type *)arg->type)->type->print_id, num);
- } else {
- printf ("%sif (skip_type_bare_%s (field%d) < 0) { return -1;}\n", offset, t == NODE_TYPE_VAR_TYPE ? "any" : ((struct tl_tree_type *)arg->type)->type->print_id, num);
- }
- } else {
- assert (t == NODE_TYPE_ARRAY);
- printf ("%sint multiplicity%d = PTR2INT (\n", offset, num);
- assert (gen_create (((struct tl_tree_array *)arg->type)->multiplicity, vars, 2 + o) >= 0);
- printf ("%s);\n", offset);
- printf ("%sstruct paramed_type *field%d = \n", offset, num);
- assert (gen_create (((struct tl_tree_array *)arg->type)->args[0]->type, vars, 2 + o) >= 0);
- printf (";\n");
- printf ("%swhile (multiplicity%d -- > 0) {\n", offset, num);
- printf ("%s if (skip_type_%s (field%d) < 0) { return -1;}\n", offset, "any", num);
- printf ("%s}\n", offset);
- }
- }
- if (arg->exist_var_num >= 0) {
- printf (" }\n");
- }
- return 0;
-}
-
-int gen_field_fetch (struct arg *arg, int *vars, int num, int empty) {
- assert (arg);
- char *offset = " ";
- int o = 0;
- if (arg->exist_var_num >= 0) {
- printf (" if (PTR2INT (var%d) & (1 << %d)) {\n", arg->exist_var_num, arg->exist_var_bit);
- offset = " ";
- o = 2;
- }
- if (!empty) {
- printf("%sif (multiline_output >= 2) { print_offset (); }\n", offset);
- }
- if (arg->id && strlen (arg->id) && !empty) {
- printf ("%sif (!disable_field_names) { eprintf (\" %s :\"); }\n", offset, arg->id);
- }
- if (arg->var_num >= 0) {
- assert (TL_TREE_METHODS (arg->type)->type (arg->type) == NODE_TYPE_TYPE);
- int t = ((struct tl_tree_type *)arg->type)->type->name;
- if (t == NAME_VAR_TYPE) {
- fprintf (stderr, "Not supported yet\n");
- assert (0);
- } else {
- assert (t == NAME_VAR_NUM);
- if (vars[arg->var_num] == 0) {
- printf ("%sif (in_remaining () < 4) { return -1;}\n", offset);
- printf ("%seprintf (\" %%d\", prefetch_int ());\n", offset);
- printf ("%sstruct paramed_type *var%d = INT2PTR (fetch_int ());\n", offset, arg->var_num);
- vars[arg->var_num] = 2;
- } else if (vars[arg->var_num] == 2) {
- printf ("%sif (in_remaining () < 4) { return -1;}\n", offset);
- printf ("%seprintf (\" %%d\", prefetch_int ());\n", offset);
- printf ("%sif (vars%d != INT2PTR (fetch_int ())) { return -1; }\n", offset, arg->var_num);
- } else {
- assert (0);
- return -1;
- }
- }
- } else {
- int t = TL_TREE_METHODS (arg->type)->type (arg->type);
- if (t == NODE_TYPE_TYPE || t == NODE_TYPE_VAR_TYPE) {
- printf ("%sstruct paramed_type *field%d = \n", offset, num);
- assert (gen_create (arg->type, vars, 2 + o) >= 0);
- printf (";\n");
- int bare = arg->flags & FLAG_BARE;
- if (!bare && t == NODE_TYPE_TYPE) {
- bare = ((struct tl_tree_type *)arg->type)->self.flags & FLAG_BARE;
- }
- if (!bare) {
- printf ("%sif (fetch_type_%s (field%d) < 0) { return -1;}\n", offset, t == NODE_TYPE_VAR_TYPE ? "any" : ((struct tl_tree_type *)arg->type)->type->print_id, num);
- } else {
- printf ("%sif (fetch_type_bare_%s (field%d) < 0) { return -1;}\n", offset, t == NODE_TYPE_VAR_TYPE ? "any" : ((struct tl_tree_type *)arg->type)->type->print_id, num);
- }
- } else {
- assert (t == NODE_TYPE_ARRAY);
- printf ("%sint multiplicity%d = PTR2INT (\n", offset, num);
- assert (gen_create (((struct tl_tree_array *)arg->type)->multiplicity, vars, 2 + o) >= 0);
- printf ("%s);\n", offset);
- printf ("%sstruct paramed_type *field%d = \n", offset, num);
- assert (gen_create (((struct tl_tree_array *)arg->type)->args[0]->type, vars, 2 + o) >= 0);
- printf (";\n");
- printf ("%seprintf (\" [\");\n", offset);
- printf ("%sif (multiline_output >= 1) { eprintf (\"\\n\"); }\n", offset);
- printf ("%sif (multiline_output >= 1) { multiline_offset += multiline_offset_size;}\n", offset);
- printf ("%swhile (multiplicity%d -- > 0) {\n", offset, num);
- printf ("%s if (multiline_output >= 1) { print_offset (); }\n", offset);
- printf ("%s if (fetch_type_%s (field%d) < 0) { return -1;}\n", offset, "any", num);
- printf ("%s if (multiline_output >= 1) { eprintf (\"\\n\"); }\n", offset);
- printf ("%s}\n", offset);
- printf ("%sif (multiline_output >= 1) { multiline_offset -= multiline_offset_size; print_offset ();}\n", offset);
- printf ("%seprintf (\" ]\");\n", offset);
- }
- }
- if (!empty) {
- printf("%sif (multiline_output >= 2) { eprintf (\"\\n\"); }\n", offset);
- }
- if (arg->exist_var_num >= 0) {
- printf (" }\n");
- }
- return 0;
-}
-
-int gen_field_store (struct arg *arg, int *vars, int num, int from_func) {
- assert (arg);
- char *offset = " ";
- int o = 0;
- if (arg->exist_var_num >= 0) {
- printf (" if (PTR2INT (var%d) & (1 << %d)) {\n", arg->exist_var_num, arg->exist_var_bit);
- offset = " ";
- o = 2;
- }
- char *fail = from_func ? "0" : "-1";
- char *expect = from_func ? "expect_token_ptr" : "expect_token";
- if (arg->id && strlen (arg->id) > 0) {
- printf ("%sif (cur_token_len >= 0 && cur_token_len == %d && !cur_token_quoted && !memcmp (cur_token, \"%s\", cur_token_len)) {\n", offset, (int)(strlen (arg->id)), arg->id);
- printf ("%s local_next_token ();\n", offset);
- printf ("%s %s (\":\", 1);\n", offset, expect);
- printf ("%s}\n", offset);
- }
- if (arg->var_num >= 0) {
- printf ("%sif (cur_token_len < 0) { return %s; }\n", offset, fail);
- assert (TL_TREE_METHODS (arg->type)->type (arg->type) == NODE_TYPE_TYPE);
- int t = ((struct tl_tree_type *)arg->type)->type->name;
- if (t == NAME_VAR_TYPE) {
- fprintf (stderr, "Not supported yet\n");
- assert (0);
- } else {
- assert (t == NAME_VAR_NUM);
- if (vars[arg->var_num] == 0) {
- printf ("%sif (!is_int ()) { return %s;}\n", offset, fail);
- printf ("%sstruct paramed_type *var%d = INT2PTR (get_int ());\n", offset, arg->var_num);
- printf ("%sout_int (get_int ());\n", offset);
- printf ("%sassert (var%d);\n", offset, arg->var_num);
- printf ("%slocal_next_token ();\n", offset);
- vars[arg->var_num] = 2;
- } else if (vars[arg->var_num] == 2) {
- printf ("%sif (!is_int ()) { return %s;}\n", offset, fail);
- printf ("%sif (vars%d != INT2PTR (get_int ())) { return %s; }\n", offset, arg->var_num, fail);
- printf ("%sout_int (get_int ());\n", offset);
- printf ("%slocal_next_token ();\n", offset);
- } else {
- assert (0);
- return -1;
- }
- }
- } else {
- int t = TL_TREE_METHODS (arg->type)->type (arg->type);
- if (t == NODE_TYPE_TYPE || t == NODE_TYPE_VAR_TYPE) {
- printf ("%sstruct paramed_type *field%d = \n", offset, num);
- assert (gen_create (arg->type, vars, 2 + o) >= 0);
- printf (";\n");
- int bare = arg->flags & FLAG_BARE;
- if (!bare && t == NODE_TYPE_TYPE) {
- bare = ((struct tl_tree_type *)arg->type)->self.flags & FLAG_BARE;
- }
- if (!bare) {
- printf ("%sif (store_type_%s (field%d) < 0) { return %s;}\n", offset, t == NODE_TYPE_VAR_TYPE ? "any" : ((struct tl_tree_type *)arg->type)->type->print_id, num, fail);
- } else {
- printf ("%sif (store_type_bare_%s (field%d) < 0) { return %s;}\n", offset, t == NODE_TYPE_VAR_TYPE ? "any" : ((struct tl_tree_type *)arg->type)->type->print_id, num, fail);
- }
- } else {
- printf ("%s%s (\"[\", 1);\n", offset, expect);
-
- assert (t == NODE_TYPE_ARRAY);
- printf ("%sint multiplicity%d = PTR2INT (\n", offset, num);
- assert (gen_create (((struct tl_tree_array *)arg->type)->multiplicity, vars, 2 + o) >= 0);
- printf ("%s);\n", offset);
- printf ("%sstruct paramed_type *field%d = \n", offset, num);
- assert (gen_create (((struct tl_tree_array *)arg->type)->args[0]->type, vars, 2 + o) >= 0);
- printf (";\n");
- printf ("%swhile (multiplicity%d -- > 0) {\n", offset, num);
- printf ("%s if (store_type_%s (field%d) < 0) { return %s;}\n", offset, "any", num, fail);
- printf ("%s}\n", offset);
-
- printf ("%s%s (\"]\", 1);\n", offset, expect);
- }
- }
- if (arg->exist_var_num >= 0) {
- printf (" }\n");
- }
- return 0;
-}
-
-int gen_field_autocomplete (struct arg *arg, int *vars, int num, int from_func) {
- assert (arg);
- char *offset = " ";
- int o = 0;
- if (arg->exist_var_num >= 0) {
- printf (" if (PTR2INT (var%d) & (1 << %d)) {\n", arg->exist_var_num, arg->exist_var_bit);
- offset = " ";
- o = 2;
- }
- char *fail = from_func ? "0" : "-1";
- char *expect = from_func ? "expect_token_ptr_autocomplete" : "expect_token_autocomplete";
- if (arg->id && strlen (arg->id) > 0) {
- printf ("%sif (cur_token_len == -3 && cur_token_real_len <= %d && !cur_token_quoted && !memcmp (cur_token, \"%s\", cur_token_real_len)) {\n", offset, (int)(strlen (arg->id)), arg->id);
- printf ("%s set_autocomplete_string (\"%s\");\n", offset, arg->id);
- printf ("%s return %s;\n", offset, fail);
- printf ("%s}\n", offset);
-
- printf ("%sif (cur_token_len >= 0 && cur_token_len == %d && !memcmp (cur_token, \"%s\", cur_token_len)) {\n", offset, (int)(strlen (arg->id)), arg->id);
- printf ("%s local_next_token ();\n", offset);
- printf ("%s %s (\":\", 1);\n", offset, expect);
- printf ("%s}\n", offset);
- }
- if (arg->var_num >= 0) {
- printf ("%sif (cur_token_len < 0) { return %s; }\n", offset, fail);
- assert (TL_TREE_METHODS (arg->type)->type (arg->type) == NODE_TYPE_TYPE);
- int t = ((struct tl_tree_type *)arg->type)->type->name;
- if (t == NAME_VAR_TYPE) {
- fprintf (stderr, "Not supported yet\n");
- assert (0);
- } else {
- assert (t == NAME_VAR_NUM);
- if (vars[arg->var_num] == 0) {
- printf ("%sif (!is_int ()) { return %s;}\n", offset, fail);
- printf ("%sstruct paramed_type *var%d = INT2PTR (get_int ());\n", offset, arg->var_num);
- printf ("%sassert (var%d);\n", offset, arg->var_num);
- printf ("%slocal_next_token ();\n", offset);
- vars[arg->var_num] = 2;
- } else if (vars[arg->var_num] == 2) {
- printf ("%sif (!is_int ()) { return %s;}\n", offset, fail);
- printf ("%sif (vars%d != INT2PTR (get_int ())) { return %s; }\n", offset, arg->var_num, fail);
- printf ("%slocal_next_token ();\n", offset);
- } else {
- assert (0);
- return -1;
- }
- }
- } else {
- int t = TL_TREE_METHODS (arg->type)->type (arg->type);
- if (t == NODE_TYPE_TYPE || t == NODE_TYPE_VAR_TYPE) {
- printf ("%sstruct paramed_type *field%d = \n", offset, num);
- assert (gen_create (arg->type, vars, 2 + o) >= 0);
- printf (";\n");
- int bare = arg->flags & FLAG_BARE;
- if (!bare && t == NODE_TYPE_TYPE) {
- bare = ((struct tl_tree_type *)arg->type)->self.flags & FLAG_BARE;
- }
- if (!bare) {
- printf ("%sif (autocomplete_type_%s (field%d) < 0) { return %s;}\n", offset, t == NODE_TYPE_VAR_TYPE ? "any" : ((struct tl_tree_type *)arg->type)->type->print_id, num, fail);
- } else {
- printf ("%sif (autocomplete_type_bare_%s (field%d) < 0) { return %s;}\n", offset, t == NODE_TYPE_VAR_TYPE ? "any" : ((struct tl_tree_type *)arg->type)->type->print_id, num, fail);
- }
- } else {
- printf ("%s%s (\"[\", 1);\n", offset, expect);
-
- assert (t == NODE_TYPE_ARRAY);
- printf ("%sint multiplicity%d = PTR2INT (\n", offset, num);
- assert (gen_create (((struct tl_tree_array *)arg->type)->multiplicity, vars, 2 + o) >= 0);
- printf ("%s);\n", offset);
- printf ("%sstruct paramed_type *field%d = \n", offset, num);
- assert (gen_create (((struct tl_tree_array *)arg->type)->args[0]->type, vars, 2 + o) >= 0);
- printf (";\n");
- printf ("%swhile (multiplicity%d -- > 0) {\n", offset, num);
- printf ("%s if (autocomplete_type_%s (field%d) < 0) { return %s;}\n", offset, "any", num, fail);
- printf ("%s}\n", offset);
-
- printf ("%s%s (\"]\", 1);\n", offset, expect);
- }
- }
- if (arg->exist_var_num >= 0) {
- printf (" }\n");
- }
- return 0;
-}
-
-int gen_field_autocomplete_excl (struct arg *arg, int *vars, int num, int from_func) {
- assert (arg);
- assert (arg->var_num < 0);
- char *offset = " ";
- if (arg->exist_var_num >= 0) {
- printf (" if (PTR2INT (var%d) & (1 << %d)) {\n", arg->exist_var_num, arg->exist_var_bit);
- offset = " ";
- }
- char *fail = from_func ? "0" : "-1";
- char *expect = from_func ? "expect_token_ptr_autocomplete" : "expect_token_autocomplete";
- if (arg->id && strlen (arg->id) > 0) {
- printf ("%sif (cur_token_len == -3 && cur_token_real_len <= %d && !cur_token_quoted && !memcmp (cur_token, \"%s\", cur_token_real_len)) {\n", offset, (int)(strlen (arg->id)), arg->id);
- printf ("%s set_autocomplete_string (\"%s\");\n", offset, arg->id);
- printf ("%s return %s;\n", offset, fail);
- printf ("%s}\n", offset);
-
- printf ("%sif (cur_token_len >= 0 && cur_token_len == %d && !memcmp (cur_token, \"%s\", cur_token_len)) {\n", offset, (int)(strlen (arg->id)), arg->id);
- printf ("%s local_next_token ();\n", offset);
- printf ("%s %s (\":\", 1);\n", offset, expect);
- printf ("%s}\n", offset);
- }
- int t = TL_TREE_METHODS (arg->type)->type (arg->type);
- assert (t == NODE_TYPE_TYPE || t == NODE_TYPE_VAR_TYPE);
- printf ("%sstruct paramed_type *field%d = autocomplete_function_any ();\n", offset, num);
- printf ("%sif (!field%d) { return 0; }\n", offset, num);
- printf ("%sadd_var_to_be_freed (field%d);\n", offset, num);
- static char s[20];
- sprintf (s, "field%d", num);
- gen_uni_skip (arg->type, s, vars, 1, 1);
- if (arg->exist_var_num >= 0) {
- printf (" }\n");
- }
- return 0;
-}
-
-int gen_field_store_excl (struct arg *arg, int *vars, int num, int from_func) {
- assert (arg);
- assert (arg->var_num < 0);
- char *offset = " ";
- if (arg->exist_var_num >= 0) {
- printf (" if (PTR2INT (var%d) & (1 << %d)) {\n", arg->exist_var_num, arg->exist_var_bit);
- offset = " ";
- }
- char *expect = from_func ? "expect_token_ptr" : "expect_token";
- if (arg->id && strlen (arg->id) > 0) {
- printf ("%sif (cur_token_len >= 0 && cur_token_len == %d && !cur_token_quoted && !memcmp (cur_token, \"%s\", cur_token_len)) {\n", offset, (int)(strlen (arg->id)), arg->id);
- printf ("%s local_next_token ();\n", offset);
- printf ("%s %s (\":\", 1);\n", offset, expect);
- printf ("%s}\n", offset);
- }
- int t = TL_TREE_METHODS (arg->type)->type (arg->type);
- assert (t == NODE_TYPE_TYPE || t == NODE_TYPE_VAR_TYPE);
- printf ("%sstruct paramed_type *field%d = store_function_any ();\n", offset, num);
- printf ("%sif (!field%d) { return 0; }\n", offset, num);
- static char s[20];
- sprintf (s, "field%d", num);
- gen_uni_skip (arg->type, s, vars, 1, 1);
- if (arg->exist_var_num >= 0) {
- printf (" }\n");
- }
- return 0;
-}
-
-void gen_constructor_skip (struct tl_combinator *c) {
- printf ("int skip_constructor_%s (struct paramed_type *T) {\n", c->print_id);
- int i;
- for (i = 0; i < c->args_num; i++) if (c->args[i]->flags & FLAG_EXCL) {
- printf (" return -1;\n");
- printf ("}\n");
- return;
- }
- static char s[10000];
- sprintf (s, "T");
-
- int *vars = malloc0 (c->var_num * 4);;
- gen_uni_skip (c->result, s, vars, 1, 0);
-
- if (c->name == NAME_INT) {
- printf (" if (in_remaining () < 4) { return -1;}\n");
- printf (" fetch_int ();\n");
- printf (" return 0;\n");
- printf ("}\n");
- return;
- } else if (c->name == NAME_LONG) {
- printf (" if (in_remaining () < 8) { return -1;}\n");
- printf (" fetch_long ();\n");
- printf (" return 0;\n");
- printf ("}\n");
- return;
- } else if (c->name == NAME_STRING) {
- printf (" int l = prefetch_strlen ();\n");
- printf (" if (l < 0) { return -1;}\n");
- printf (" fetch_str (l);\n");
- printf (" return 0;\n");
- printf ("}\n");
- return;
- } else if (c->name == NAME_DOUBLE) {
- printf (" if (in_remaining () < 8) { return -1;}\n");
- printf (" fetch_double ();\n");
- printf (" return 0;\n");
- printf ("}\n");
- return;
- }
-
- for (i = 0; i < c->args_num; i++) if (!(c->args[i]->flags & FLAG_OPT_VAR)) {
- assert (gen_field_skip (c->args[i], vars, i + 1) >= 0);
- }
- free (vars);
- printf (" return 0;\n");
- printf ("}\n");
-}
-
-void gen_constructor_fetch (struct tl_combinator *c) {
- printf ("int fetch_constructor_%s (struct paramed_type *T) {\n", c->print_id);
- int i;
- for (i = 0; i < c->args_num; i++) if (c->args[i]->flags & FLAG_EXCL) {
- printf (" return -1;\n");
- printf ("}\n");
- return;
- }
- static char s[10000];
- sprintf (s, "T");
-
- int *vars = malloc0 (c->var_num * 4);;
- gen_uni_skip (c->result, s, vars, 1, 0);
-
- if (c->name == NAME_INT) {
- printf (" if (in_remaining () < 4) { return -1;}\n");
- printf (" eprintf (\" %%d\", fetch_int ());\n");
- printf (" return 0;\n");
- printf ("}\n");
- return;
- } else if (c->name == NAME_LONG) {
- printf (" if (in_remaining () < 8) { return -1;}\n");
- printf (" eprintf (\" %%lld\", fetch_long ());\n");
- printf (" return 0;\n");
- printf ("}\n");
- return;
- } else if (c->name == NAME_STRING) {
- printf (" static char buf[1 << 22];\n");
- printf (" int l = prefetch_strlen ();\n");
- printf (" if (l < 0 || (l >= (1 << 22) - 2)) { return -1; }\n");
- printf (" memcpy (buf, fetch_str (l), l);\n");
- printf (" buf[l] = 0;\n");
- printf (" print_escaped_string (buf, l);\n");
- printf (" return 0;\n");
- printf ("}\n");
- return;
- } else if (c->name == NAME_DOUBLE) {
- printf (" if (in_remaining () < 8) { return -1;}\n");
- printf (" eprintf (\" %%lf\", fetch_double ());\n");
- printf (" return 0;\n");
- printf ("}\n");
- return;
- }
-
- assert (c->result->methods->type (c->result) == NODE_TYPE_TYPE);
- int empty = is_empty (((struct tl_tree_type *)c->result)->type);
- if (!empty) {
- printf (" eprintf (\" %s\");\n", c->id);
- printf (" if (multiline_output >= 2) { eprintf (\"\\n\"); }\n");
- }
-
-
- for (i = 0; i < c->args_num; i++) if (!(c->args[i]->flags & FLAG_OPT_VAR)) {
- assert (gen_field_fetch (c->args[i], vars, i + 1, empty) >= 0);
- }
- free (vars);
- printf (" return 0;\n");
- printf ("}\n");
-}
-
-void gen_constructor_store (struct tl_combinator *c) {
- printf ("int store_constructor_%s (struct paramed_type *T) {\n", c->print_id);
- int i;
- for (i = 0; i < c->args_num; i++) if (c->args[i]->flags & FLAG_EXCL) {
- printf (" return -1;\n");
- printf ("}\n");
- return;
- }
- static char s[10000];
- sprintf (s, "T");
-
- int *vars = malloc0 (c->var_num * 4);;
- assert (c->var_num <= 10);
- gen_uni_skip (c->result, s, vars, 1, 0);
-
- if (c->name == NAME_INT) {
- printf (" if (is_int ()) {\n");
- printf (" out_int (get_int ());\n");
- printf (" local_next_token ();\n");
- printf (" return 0;\n");
- printf (" } else {\n");
- printf (" return -1;\n");
- printf (" }\n");
- printf ("}\n");
- return;
- } else if (c->name == NAME_LONG) {
- printf (" if (is_int ()) {\n");
- printf (" out_long (get_int ());\n");
- printf (" local_next_token ();\n");
- printf (" return 0;\n");
- printf (" } else {\n");
- printf (" return -1;\n");
- printf (" }\n");
- printf ("}\n");
- return;
- } else if (c->name == NAME_STRING) {
- printf (" if (cur_token_len >= 0) {\n");
- printf (" out_cstring (cur_token, cur_token_len);\n");
- printf (" local_next_token ();\n");
- printf (" return 0;\n");
- printf (" } else {\n");
- printf (" return -1;\n");
- printf (" }\n");
- printf ("}\n");
- return;
- } else if (c->name == NAME_DOUBLE) {
- printf (" if (is_double ()) {\n");
- printf (" out_double (get_double());\n");
- printf (" local_next_token ();\n");
- printf (" return 0;\n");
- printf (" } else {\n");
- printf (" return -1;\n");
- printf (" }\n");
- printf ("}\n");
- return;
- }
-
- for (i = 0; i < c->args_num; i++) if (!(c->args[i]->flags & FLAG_OPT_VAR)) {
- assert (gen_field_store (c->args[i], vars, i + 1, 0) >= 0);
- }
-
- free (vars);
- printf (" return 0;\n");
- printf ("}\n");
-}
-
-void gen_constructor_autocomplete (struct tl_combinator *c) {
- printf ("int autocomplete_constructor_%s (struct paramed_type *T) {\n", c->print_id);
- int i;
- for (i = 0; i < c->args_num; i++) if (c->args[i]->flags & FLAG_EXCL) {
- printf (" return -1;\n");
- printf ("}\n");
- return;
- }
- static char s[10000];
- sprintf (s, "T");
-
- int *vars = malloc0 (c->var_num * 4);;
- assert (c->var_num <= 10);
- gen_uni_skip (c->result, s, vars, 1, 0);
-
- if (c->name == NAME_INT) {
- printf (" if (is_int ()) {\n");
- printf (" local_next_token ();\n");
- printf (" return 0;\n");
- printf (" } else {\n");
- printf (" return -1;\n");
- printf (" }\n");
- printf ("}\n");
- return;
- } else if (c->name == NAME_LONG) {
- printf (" if (is_int ()) {\n");
- printf (" local_next_token ();\n");
- printf (" return 0;\n");
- printf (" } else {\n");
- printf (" return -1;\n");
- printf (" }\n");
- printf ("}\n");
- return;
- } else if (c->name == NAME_STRING) {
- printf (" if (cur_token_len >= 0) {\n");
- printf (" local_next_token ();\n");
- printf (" return 0;\n");
- printf (" } else {\n");
- printf (" return -1;\n");
- printf (" }\n");
- printf ("}\n");
- return;
- } else if (c->name == NAME_DOUBLE) {
- printf (" if (is_double ()) {\n");
- printf (" local_next_token ();\n");
- printf (" return 0;\n");
- printf (" } else {\n");
- printf (" return -1;\n");
- printf (" }\n");
- printf ("}\n");
- return;
- }
-
- for (i = 0; i < c->args_num; i++) if (!(c->args[i]->flags & FLAG_OPT_VAR)) {
- assert (gen_field_autocomplete (c->args[i], vars, i + 1, 0) >= 0);
- }
-
- free (vars);
- printf (" return 0;\n");
- printf ("}\n");
-}
-
-void gen_type_skip (struct tl_type *t) {
- printf ("int skip_type_%s (struct paramed_type *T) {\n", t->print_id);
- printf (" if (in_remaining () < 4) { return -1;}\n");
- printf (" int magic = fetch_int ();\n");
- printf (" switch (magic) {\n");
- int i;
- for (i = 0; i < t->constructors_num; i++) {
- printf (" case 0x%08x: return skip_constructor_%s (T);\n", t->constructors[i]->name, t->constructors[i]->print_id);
- }
- printf (" default: return -1;\n");
- printf (" }\n");
- printf ("}\n");
- printf ("int skip_type_bare_%s (struct paramed_type *T) {\n", t->print_id);
- if (t->constructors_num > 1) {
- printf (" int *save_in_ptr = in_ptr;\n");
- for (i = 0; i < t->constructors_num; i++) {
- printf (" if (skip_constructor_%s (T) >= 0) { return 0; }\n", t->constructors[i]->print_id);
- printf (" in_ptr = save_in_ptr;\n");
- }
- } else {
- for (i = 0; i < t->constructors_num; i++) {
- printf (" if (skip_constructor_%s (T) >= 0) { return 0; }\n", t->constructors[i]->print_id);
- }
- }
- printf (" return -1;\n");
- printf ("}\n");
-}
-
-void gen_type_fetch (struct tl_type *t) {
- int empty = is_empty (t);;
- printf ("int fetch_type_%s (struct paramed_type *T) {\n", t->print_id);
- printf (" if (in_remaining () < 4) { return -1;}\n");
- if (!empty) {
- printf (" if (multiline_output >= 2) { multiline_offset += multiline_offset_size; }\n");
- printf (" eprintf (\" (\");\n");
- }
- printf (" int magic = fetch_int ();\n");
- printf (" int res = -1;\n");
- printf (" switch (magic) {\n");
- int i;
- for (i = 0; i < t->constructors_num; i++) {
- printf (" case 0x%08x: res = fetch_constructor_%s (T); break;\n", t->constructors[i]->name, t->constructors[i]->print_id);
- }
- printf (" default: return -1;\n");
- printf (" }\n");
- if (!empty) {
- printf (" if (res >= 0) {\n");
- printf (" if (multiline_output >= 2) { multiline_offset -= multiline_offset_size; print_offset (); }\n");
- printf (" eprintf (\" )\");\n");
- //printf (" if (multiline_output >= 2) { printf (\"\\n\"); }\n");
- printf (" }\n");
- }
- printf (" return res;\n");
- printf ("}\n");
- printf ("int fetch_type_bare_%s (struct paramed_type *T) {\n", t->print_id);
- if (t->constructors_num > 1) {
- printf (" int *save_in_ptr = in_ptr;\n");
-
- if (!empty) {
- printf (" if (multiline_output >= 2) { multiline_offset += multiline_offset_size; }\n");
- }
- for (i = 0; i < t->constructors_num; i++) {
- printf (" if (skip_constructor_%s (T) >= 0) { in_ptr = save_in_ptr; %sassert (!fetch_constructor_%s (T)); %sreturn 0; }\n", t->constructors[i]->print_id, empty ? "" : "eprintf (\" (\"); ", t->constructors[i]->print_id , empty ? "" : "if (multiline_output >= 2) { multiline_offset -= multiline_offset_size; print_offset (); } eprintf (\" )\");");
- printf (" in_ptr = save_in_ptr;\n");
- }
- } else {
- for (i = 0; i < t->constructors_num; i++) {
- if (!empty) {
- printf (" if (multiline_output >= 2) { multiline_offset += multiline_offset_size; }\n");
- printf (" eprintf (\" (\");\n");
- }
- printf (" if (fetch_constructor_%s (T) >= 0) { %sreturn 0; }\n", t->constructors[i]->print_id, empty ? "" : "if (multiline_output >= 2) { multiline_offset -= multiline_offset_size; print_offset (); } eprintf (\" )\");" );
- }
- }
- printf (" return -1;\n");
- printf ("}\n");
-}
-
-void gen_type_store (struct tl_type *t) {
- int empty = is_empty (t);;
- int k = 0;
- for (k = 0; k < 2; k++) {
- printf ("int store_type_%s%s (struct paramed_type *T) {\n", k == 0 ? "" : "bare_", t->print_id);
- if (empty) {
- printf (" if (store_constructor_%s (T) < 0) { return -1; }\n", t->constructors[0]->print_id);
- printf (" return 0;\n");
- printf ("}\n");
- } else {
- printf (" expect_token (\"(\", 1);\n");
- printf (" if (cur_token_len < 0) { return -1; }\n");
- printf (" if (cur_token_len < 0) { return -1; }\n");
- int i;
- for (i = 0; i < t->constructors_num; i++) {
- printf (" if (cur_token_len == %d && !memcmp (cur_token, \"%s\", cur_token_len)) {\n", (int)strlen (t->constructors[i]->id), t->constructors[i]->id);
- if (!k) {
- printf (" out_int (0x%08x);\n", t->constructors[i]->name);
- }
- printf (" local_next_token ();\n");
- printf (" if (store_constructor_%s (T) < 0) { return -1; }\n", t->constructors[i]->print_id);
- printf (" expect_token (\")\", 1);\n");
- printf (" return 0;\n");
- printf (" }\n");
- }
- /*if (t->constructors_num == 1) {
- printf (" if (!force) {\n");
- if (!k) {
- printf (" out_int (0x%08x);\n", t->constructors[0]->name);
- }
- printf (" if (store_constructor_%s (T) < 0) { return -1; }\n", t->constructors[0]->print_id);
- printf (" expect_token (\")\", 1);\n");
- printf (" return 0;\n");
- printf (" }\n");
- }*/
- printf (" return -1;\n");
- printf ("}\n");
- }
- }
-}
-
-void gen_type_autocomplete (struct tl_type *t) {
- int empty = is_empty (t);;
- int k = 0;
- for (k = 0; k < 2; k++) {
- printf ("int autocomplete_type_%s%s (struct paramed_type *T) {\n", k == 0 ? "" : "bare_", t->print_id);
- if (empty) {
- printf (" if (autocomplete_constructor_%s (T) < 0) { return -1; }\n", t->constructors[0]->print_id);
- printf (" return 0;\n");
- printf ("}\n");
- } else {
- printf (" expect_token_autocomplete (\"(\", 1);\n");
- printf (" if (cur_token_len == -3) { set_autocomplete_type (do_autocomplete_type_%s); return -1; }\n", t->print_id);
- printf (" if (cur_token_len < 0) { return -1; }\n");
- int i;
- for (i = 0; i < t->constructors_num; i++) {
- printf (" if (cur_token_len == %d && !memcmp (cur_token, \"%s\", cur_token_len)) {\n", (int)strlen (t->constructors[i]->id), t->constructors[i]->id);
- printf (" local_next_token ();\n");
- printf (" if (autocomplete_constructor_%s (T) < 0) { return -1; }\n", t->constructors[i]->print_id);
- printf (" expect_token_autocomplete (\")\", 1);\n");
- printf (" return 0;\n");
- printf (" }\n");
- }
- /*if (t->constructors_num == 1) {
- printf (" if (!force) {\n");
- printf (" if (autocomplete_constructor_%s (T) < 0) { return -1; }\n", t->constructors[0]->print_id);
- printf (" expect_token_autocomplete (\")\", 1);\n");
- printf (" return 0;\n");
- printf (" }\n");
- }*/
- printf (" return -1;\n");
- printf ("}\n");
- }
- }
-}
-
-void gen_function_store (struct tl_combinator *f) {
- printf ("struct paramed_type *store_function_%s (void) {\n", f->print_id);
- int i;
-
- int *vars = malloc0 (f->var_num * 4);;
- assert (f->var_num <= 10);
-
- for (i = 0; i < f->args_num; i++) if (!(f->args[i]->flags & FLAG_OPT_VAR)) {
- if (f->args[i]->flags & FLAG_EXCL) {
- assert (gen_field_store_excl (f->args[i], vars, i + 1, 1) >= 0);
- } else {
- assert (gen_field_store (f->args[i], vars, i + 1, 1) >= 0);
- }
- }
-
-
- printf (" struct paramed_type *R = \n");
- assert (gen_create (f->result, vars, 2) >= 0);
- printf (";\n");
-
- free (vars);
- printf (" return paramed_type_dup (R);\n");
- printf ("}\n");
-}
-
-void gen_function_autocomplete (struct tl_combinator *f) {
- printf ("struct paramed_type *autocomplete_function_%s (void) {\n", f->print_id);
- int i;
-
- int *vars = malloc0 (f->var_num * 4);;
- assert (f->var_num <= 10);
-
- for (i = 0; i < f->args_num; i++) if (!(f->args[i]->flags & FLAG_OPT_VAR)) {
- if (f->args[i]->flags & FLAG_EXCL) {
- assert (gen_field_autocomplete_excl (f->args[i], vars, i + 1, 1) >= 0);
- } else {
- assert (gen_field_autocomplete (f->args[i], vars, i + 1, 1) >= 0);
- }
- }
-
- printf (" struct paramed_type *R = \n");
- assert (gen_create (f->result, vars, 2) >= 0);
- printf (";\n");
-
- free (vars);
- printf (" return paramed_type_dup (R);\n");
- printf ("}\n");
-}
-
-void gen_type_do_autocomplete (struct tl_type *t) {
- printf ("int do_autocomplete_type_%s (const char *text, int text_len, int index, char **R) {\n", t->print_id);
- printf (" index ++;\n");
- int i;
- for (i = 0; i < t->constructors_num; i++) {
- printf (" if (index == %d) { if (!strncmp (text, \"%s\", text_len)) { *R = tstrdup (\"%s\"); return index; } else { index ++; }}\n", i, t->constructors[i]->id, t->constructors[i]->id);
- }
- printf (" *R = 0;\n");
- printf (" return 0;\n");
- printf ("}\n");
-}
-
-struct tl_tree *read_num_var (int *var_num) {
- struct tl_tree_var_num *T = malloc0 (sizeof (*T));
- T->self.flags = 0;
- T->self.methods = &tl_pvar_num_methods;;
- T->dif = get_int ();
- T->var_num = get_int ();
-
- if (T->var_num >= *var_num) {
- *var_num = T->var_num + 1;
- }
- assert (!(T->self.flags & FLAG_NOVAR));
- return (void *)T;
-}
-
-struct tl_tree *read_type_var (int *var_num) {
- struct tl_tree_var_type *T = malloc0 (sizeof (*T));
- T->self.methods = &tl_pvar_type_methods;
- T->var_num = get_int ();
- T->self.flags = get_int ();
- if (T->var_num >= *var_num) {
- *var_num = T->var_num + 1;
- }
- assert (!(T->self.flags & (FLAG_NOVAR | FLAG_BARE)));
- return (void *)T;
-}
-
-struct tl_tree *read_array (int *var_num) {
- struct tl_tree_array *T = malloc0 (sizeof (*T));
- T->self.methods = &tl_parray_methods;
- T->self.flags = 0;
- T->multiplicity = read_nat_expr (var_num);
- assert (T->multiplicity);
-
- T->args_num = get_int ();
- assert (T->args_num >= 0 && T->args_num <= 1000);
- T->args = malloc0 (sizeof (void *) * T->args_num);
-
- assert (read_args_list (T->args, T->args_num, var_num) >= 0);
- T->self.flags |= FLAG_NOVAR;
- int i;
- for (i = 0; i < T->args_num; i++) {
- if (!(T->args[i]->flags & FLAG_NOVAR)) {
- T->self.flags &= ~FLAG_NOVAR;
- }
- }
- return (void *)T;
-}
-
-struct tl_tree *read_type (int *var_num) {
- struct tl_tree_type *T = malloc0 (sizeof (*T));
- T->self.methods = &tl_ptype_methods;
-
- T->type = tl_type_get_by_name (get_int ());
- assert (T->type);
- T->self.flags = get_int ();
- T->children_num = get_int ();
- assert (T->type->arity == T->children_num);
- T->children = malloc0 (sizeof (void *) * T->children_num);
- int i;
- T->self.flags |= FLAG_NOVAR;
- for (i = 0; i < T->children_num; i++) {
- int t = get_int ();
- if (t == (int)TLS_EXPR_NAT) {
- assert ((T->type->params_types & (1 << i)));
- T->children[i] = read_nat_expr (var_num);
- } else if (t == (int)TLS_EXPR_TYPE) {
- assert (!(T->type->params_types & (1 << i)));
- T->children[i] = read_type_expr (var_num);
- } else {
- assert (0);
- }
- if (!TL_IS_NAT_VAR (T->children[i]) && !(T->children[i]->flags & FLAG_NOVAR)) {
- T->self.flags &= ~FLAG_NOVAR;
- }
- }
- return (void *)T;
-}
-
-struct tl_tree *read_tree (int *var_num) {
- int x = get_int ();
- if (verbosity >= 2) {
- fprintf (stderr, "read_tree: constructor = 0x%08x\n", x);
- }
- switch (x) {
- case TLS_TREE_NAT_CONST:
- return read_num_const (var_num);
- case TLS_TREE_NAT_VAR:
- return read_num_var (var_num);
- case TLS_TREE_TYPE_VAR:
- return read_type_var (var_num);
- case TLS_TREE_TYPE:
- return read_type (var_num);
- case TLS_TREE_ARRAY:
- return read_array (var_num);
- default:
- if (verbosity) {
- fprintf (stderr, "x = %d\n", x);
- }
- assert (0);
- return 0;
- }
-}
-
-struct tl_tree *read_type_expr (int *var_num) {
- int x = get_int ();
- if (verbosity >= 2) {
- fprintf (stderr, "read_type_expr: constructor = 0x%08x\n", x);
- }
- switch (x) {
- case TLS_TYPE_VAR:
- return read_type_var (var_num);
- case TLS_TYPE_EXPR:
- return read_type (var_num);
- case TLS_ARRAY:
- return read_array (var_num);
- default:
- if (verbosity) {
- fprintf (stderr, "x = %d\n", x);
- }
- assert (0);
- return 0;
- }
-}
-
-struct tl_tree *read_nat_expr (int *var_num) {
- int x = get_int ();
- if (verbosity >= 2) {
- fprintf (stderr, "read_nat_expr: constructor = 0x%08x\n", x);
- }
- switch (x) {
- case TLS_NAT_CONST:
- return read_num_const (var_num);
- case TLS_NAT_VAR:
- return read_num_var (var_num);
- default:
- if (verbosity) {
- fprintf (stderr, "x = %d\n", x);
- }
- assert (0);
- return 0;
- }
-}
-
-struct tl_tree *read_expr (int *var_num) {
- int x = get_int ();
- if (verbosity >= 2) {
- fprintf (stderr, "read_nat_expr: constructor = 0x%08x\n", x);
- }
- switch (x) {
- case TLS_EXPR_NAT:
- return read_nat_expr (var_num);
- case TLS_EXPR_TYPE:
- return read_type_expr (var_num);
- default:
- if (verbosity) {
- fprintf (stderr, "x = %d\n", x);
- }
- assert (0);
- return 0;
- }
-}
-
-int read_args_list (struct arg **args, int args_num, int *var_num) {
- int i;
- for (i = 0; i < args_num; i++) {
- args[i] = malloc0 (sizeof (struct arg));
- args[i]->exist_var_num = -1;
- args[i]->exist_var_bit = 0;
- assert (get_int () == TLS_ARG_V2);
- args[i]->id = get_string ();
- args[i]->flags = get_int ();
-
- if (args[i]->flags & 2) {
- args[i]->flags &= ~2;
- args[i]->flags |= (1 << 20);
- }
- if (args[i]->flags & 4) {
- args[i]->flags &= ~4;
- args[i]->var_num = get_int ();
- } else {
- args[i]->var_num = -1;
- }
-
- int x = args[i]->flags & 6;
- args[i]->flags &= ~6;
- if (x & 2) { args[i]->flags |= 4; }
- if (x & 4) { args[i]->flags |= 2; }
-
- if (args[i]->var_num >= *var_num) {
- *var_num = args[i]->var_num + 1;
- }
- if (args[i]->flags & FLAG_OPT_FIELD) {
- args[i]->exist_var_num = get_int ();
- args[i]->exist_var_bit = get_int ();
- }
- args[i]->type = read_type_expr (var_num);
- assert (args[i]->type);
-
- if (args[i]->var_num < 0 && args[i]->exist_var_num < 0 && (TL_IS_NAT_VAR(args[i]->type) || (args[i]->type->flags & FLAG_NOVAR))) {
- args[i]->flags |= FLAG_NOVAR;
- }
- }
- return 1;
-}
-
-int read_combinator_args_list (struct tl_combinator *c) {
- c->args_num = get_int ();
- if (verbosity >= 2) {
- fprintf (stderr, "c->id = %s, c->args_num = %d\n", c->id, c->args_num);
- }
- assert (c->args_num >= 0 && c->args_num <= 1000);
- c->args = malloc0 (sizeof (void *) * c->args_num);
- c->var_num = 0;
- return read_args_list (c->args, c->args_num, &c->var_num);
-}
-
-int read_combinator_right (struct tl_combinator *c) {
- assert (get_int () == TLS_COMBINATOR_RIGHT_V2);
- c->result = read_type_expr (&c->var_num);
- assert (c->result);
- return 1;
-}
-
-int read_combinator_left (struct tl_combinator *c) {
- int x = get_int ();
-
- if (x == (int)TLS_COMBINATOR_LEFT_BUILTIN) {
- c->args_num = 0;
- c->var_num = 0;
- c->args = 0;
- return 1;
- } else if (x == TLS_COMBINATOR_LEFT) {
- return read_combinator_args_list (c);
- } else {
- assert (0);
- return -1;
- }
-}
-
-char *gen_print_id (const char *id) {
- static char s[1000];
- char *ptr = s;
- int first = 1;
- while (*id) {
- if (*id == '.') {
- *(ptr ++) = '_';
- } else if (*id >= 'A' && *id <= 'Z') {
- if (!first && *(ptr - 1) != '_') {
- *(ptr ++) = '_';
- }
- *(ptr ++) = *id - 'A' + 'a';
- } else {
- *(ptr ++) = *id;
- }
- id ++;
- first = 0;
- }
- *ptr = 0;
- return s;
-}
-
-struct tl_combinator *read_combinators (int v) {
- struct tl_combinator *c = malloc0 (sizeof (*c));
- c->name = get_int ();
- c->id = get_string ();
- c->print_id = strdup (gen_print_id (c->id));
- assert (c->print_id);
- //char *s = c->id;
- //while (*s) { if (*s == '.') { *s = '_'; } ; s ++;}
- int x = get_int ();
- struct tl_type *t = tl_type_get_by_name (x);
- assert (t || (!x && v == 3));
-
- if (v == 2) {
- assert (t->extra < t->constructors_num);
- t->constructors[t->extra ++] = c;
- c->is_fun = 0;
- } else {
- assert (v == 3);
- tl_function_insert_by_name (c);
- c->is_fun = 1;
- }
- assert (read_combinator_left (c) >= 0);
- assert (read_combinator_right (c) >= 0);
- return c;
-}
-
-struct tl_type *read_types (void) {
- struct tl_type *t = malloc0 (sizeof (*t));
- t->name = get_int ();
- t->id = get_string ();
- t->print_id = strdup (gen_print_id (t->id));
- assert (t->print_id);
-
- t->constructors_num = get_int ();
- assert (t->constructors_num >= 0 && t->constructors_num <= 1000);
-
- t->constructors = malloc0 (sizeof (void *) * t->constructors_num);
- t->flags = get_int ();
- t->arity = get_int ();
- t->params_types = get_long (); // params_types
- t->extra = 0;
- tl_type_insert_by_name (t);
- return t;
-}
-
-
-
-int parse_tlo_file (void) {
- buf_end = buf_ptr + (buf_size / 4);
- assert (get_int () == TLS_SCHEMA_V2);
-
- get_int (); // version
- get_int (); // date
-
- tn = 0;
- fn = 0;
- cn = 0;
- int i;
-
- tn = get_int ();
- assert (tn >= 0 && tn < 10000);
- tps = malloc0 (sizeof (void *) * tn);
-
- if (verbosity >= 2) {
- fprintf (stderr, "Found %d types\n", tn);
- }
-
- for (i = 0; i < tn; i++) {
- assert (get_int () == TLS_TYPE);
- tps[i] = read_types ();
- assert (tps[i]);
- }
-
- cn = get_int ();
- assert (cn >= 0);
-
- if (verbosity >= 2) {
- fprintf (stderr, "Found %d constructors\n", cn);
- }
-
- for (i = 0; i < cn; i++) {
- assert (get_int () == TLS_COMBINATOR);
- assert (read_combinators (2));
- }
-
- fn = get_int ();
- assert (fn >= 0 && fn < 10000);
-
- fns = malloc0 (sizeof (void *) * fn);
-
- if (verbosity >= 2) {
- fprintf (stderr, "Found %d functions\n", fn);
- }
-
- for (i = 0; i < fn; i++) {
- assert (get_int () == TLS_COMBINATOR);
- fns[i] = read_combinators (3);
- assert (fns[i]);
- }
-
- assert (buf_ptr == buf_end);
-
-
- int j;
- for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type")) {
- tps[i]->name = 0;
- for (j = 0; j < tps[i]->constructors_num; j ++) {
- tps[i]->name ^= tps[i]->constructors[j]->name;
- }
- }
-
- if (!header) {
- printf ("#include \"auto.h\"\n");
- printf ("#include \n");
-
-
- printf ("#include \"auto-static.c\"\n");
- for (i = 0; i < tn; i++) {
- for (j = 0; j < tps[i]->constructors_num; j ++) {
- gen_constructor_skip (tps[i]->constructors[j]);
- if (!skip_only) {
- gen_constructor_store (tps[i]->constructors[j]);
- gen_constructor_fetch (tps[i]->constructors[j]);
- gen_constructor_autocomplete (tps[i]->constructors[j]);
- }
- }
- }
- for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type")) {
- gen_type_skip (tps[i]);
- if (!skip_only) {
- gen_type_store (tps[i]);
- gen_type_fetch (tps[i]);
- gen_type_autocomplete (tps[i]);
- gen_type_do_autocomplete (tps[i]);
- }
- }
- if (!skip_only) {
- for (i = 0; i < fn; i++) {
- gen_function_store (fns[i]);
- gen_function_autocomplete (fns[i]);
- }
- }
- printf ("int skip_type_any (struct paramed_type *T) {\n");
- printf (" switch (T->type->name) {\n");
- for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type") && tps[i]->name) {
- printf (" case 0x%08x: return skip_type_%s (T);\n", tps[i]->name, tps[i]->print_id);
- printf (" case 0x%08x: return skip_type_bare_%s (T);\n", ~tps[i]->name, tps[i]->print_id);
- }
- printf (" default: return -1; }\n");
- printf ("}\n");
- if (!skip_only) {
- printf ("int store_type_any (struct paramed_type *T) {\n");
- printf (" switch (T->type->name) {\n");
- for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type") && tps[i]->name) {
- printf (" case 0x%08x: return store_type_%s (T);\n", tps[i]->name, tps[i]->print_id);
- printf (" case 0x%08x: return store_type_bare_%s (T);\n", ~tps[i]->name, tps[i]->print_id);
- }
- printf (" default: return -1; }\n");
- printf ("}\n");
- printf ("int fetch_type_any (struct paramed_type *T) {\n");
- printf (" switch (T->type->name) {\n");
- for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type") && tps[i]->name) {
- printf (" case 0x%08x: return fetch_type_%s (T);\n", tps[i]->name, tps[i]->print_id);
- printf (" case 0x%08x: return fetch_type_bare_%s (T);\n", ~tps[i]->name, tps[i]->print_id);
- }
- printf (" default: return -1; }\n");
- printf ("}\n");
- printf ("int autocomplete_type_any (struct paramed_type *T) {\n");
- printf (" switch (T->type->name) {\n");
- for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type") && tps[i]->name) {
- printf (" case 0x%08x: return autocomplete_type_%s (T);\n", tps[i]->name, tps[i]->print_id);
- printf (" case 0x%08x: return autocomplete_type_bare_%s (T);\n", ~tps[i]->name, tps[i]->print_id);
- }
- printf (" default: return -1; }\n");
- printf ("}\n");
- printf ("struct paramed_type *store_function_any (void) {\n");
- printf (" if (cur_token_len != 1 || *cur_token != '(') { return 0; }\n");
- printf (" local_next_token ();\n");
- printf (" if (cur_token_len == 1 || *cur_token == '.') { \n");
- printf (" local_next_token ();\n");
- printf (" if (cur_token_len != 1 || *cur_token != '=') { return 0; }\n");
- printf (" local_next_token ();\n");
- printf (" };\n");
- printf (" if (cur_token_len < 0) { return 0; }\n");
- for (i = 0; i < fn; i++) {
- printf (" if (cur_token_len == %d && !memcmp (cur_token, \"%s\", cur_token_len)) {\n", (int)strlen (fns[i]->id), fns[i]->id);
- printf (" out_int (0x%08x);\n", fns[i]->name);
- printf (" local_next_token ();\n");
- printf (" struct paramed_type *P = store_function_%s ();\n", fns[i]->print_id);
- printf (" if (!P) { return 0; }\n");
- printf (" if (cur_token_len != 1 || *cur_token != ')') { return 0; }\n");
- printf (" local_next_token ();\n");
- printf (" return P;\n");
- printf (" }\n");
- }
- printf (" return 0;\n");
- printf ("}\n");
- printf ("int do_autocomplete_function (const char *text, int text_len, int index, char **R) {\n");
- printf (" index ++;\n");
- int i;
- for (i = 0; i < fn; i++) {
- printf (" if (index == %d) { if (!strncmp (text, \"%s\", text_len)) { *R = tstrdup (\"%s\"); return index; } else { index ++; }}\n", i, fns[i]->id, fns[i]->id);
- }
- printf (" *R = 0;\n");
- printf (" return 0;\n");
- printf ("}\n");
- printf ("struct paramed_type *autocomplete_function_any (void) {\n");
- printf (" expect_token_ptr_autocomplete (\"(\", 1);\n");
- printf (" if (cur_token_len == -3) { set_autocomplete_type (do_autocomplete_function); }\n");
- printf (" if (cur_token_len < 0) { return 0; }\n");
- for (i = 0; i < fn; i++) {
- printf (" if (cur_token_len == %d && !memcmp (cur_token, \"%s\", cur_token_len)) {\n", (int)strlen (fns[i]->id), fns[i]->id);
- printf (" local_next_token ();\n");
- printf (" struct paramed_type *P = autocomplete_function_%s ();\n", fns[i]->print_id);
- printf (" if (!P) { return 0; }\n");
- printf (" expect_token_ptr_autocomplete (\")\", 1);\n");
- printf (" return P;\n");
- printf (" }\n");
- }
- printf (" return 0;\n");
- printf ("}\n");
- }
- } else {
- for (i = 0; i < tn; i++) {
- for (j = 0; j < tps[i]->constructors_num; j ++) {
- printf ("int skip_constructor_%s (struct paramed_type *T);\n", tps[i]->constructors[j]->print_id);
- printf ("int store_constructor_%s (struct paramed_type *T);\n", tps[i]->constructors[j]->print_id);
- printf ("int fetch_constructor_%s (struct paramed_type *T);\n", tps[i]->constructors[j]->print_id);
- printf ("int autocomplete_constructor_%s (struct paramed_type *T);\n", tps[i]->constructors[j]->print_id);
- }
- }
- for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type")) {
- printf ("int skip_type_%s (struct paramed_type *T);\n", tps[i]->print_id);
- printf ("int skip_type_bare_%s (struct paramed_type *T);\n", tps[i]->print_id);
- printf ("int store_type_%s (struct paramed_type *T);\n", tps[i]->print_id);
- printf ("int store_type_bare_%s (struct paramed_type *T);\n", tps[i]->print_id);
- printf ("int fetch_type_%s (struct paramed_type *T);\n", tps[i]->print_id);
- printf ("int fetch_type_bare_%s (struct paramed_type *T);\n", tps[i]->print_id);
- printf ("int autocomplete_type_%s (struct paramed_type *T);\n", tps[i]->print_id);
- printf ("int do_autocomplete_type_%s (const char *text, int len, int index, char **R);\n", tps[i]->print_id);
- printf ("int autocomplete_type_bare_%s (struct paramed_type *T);\n", tps[i]->print_id);
- }
- for (i = 0; i < fn; i++) {
- printf ("struct paramed_type *store_function_%s (void);\n", fns[i]->print_id);
- printf ("struct paramed_type *autocomplete_function_%s (void);\n", fns[i]->print_id);
- }
- printf ("int skip_type_any (struct paramed_type *T);\n");
- printf ("int store_type_any (struct paramed_type *T);\n");
- printf ("int fetch_type_any (struct paramed_type *T);\n");
- printf ("int autocomplete_type_any (struct paramed_type *T);\n");
- printf ("struct paramed_type *store_function_any (void);\n");
- printf ("struct paramed_type *autocomplete_function_any (void);\n");
-
- /*for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#') {
- printf ("extern struct tl_type tl_type_%s;\n", tps[i]->id);
- }*/
- for (i = 0; i < tn; i++) if (tps[i]->id[0] != '#' && strcmp (tps[i]->id, "Type")) {
- printf ("static struct tl_type_descr tl_type_%s __attribute__ ((unused));\n", tps[i]->print_id);
- printf ("static struct tl_type_descr tl_type_%s = {\n", tps[i]->print_id);
- printf (" .name = 0x%08x,\n", tps[i]->name);
- printf (" .id = \"%s\"\n,", tps[i]->id);
- printf (" .params_num = %d,\n", tps[i]->arity);
- printf (" .params_types = %lld\n", tps[i]->params_types);
- printf ("};\n");
- printf ("static struct tl_type_descr tl_type_bare_%s __attribute__ ((unused));\n", tps[i]->print_id);
- printf ("static struct tl_type_descr tl_type_bare_%s = {\n", tps[i]->print_id);
- printf (" .name = 0x%08x,\n", ~tps[i]->name);
- printf (" .id = \"Bare_%s\",\n", tps[i]->id);
- printf (" .params_num = %d,\n", tps[i]->arity);
- printf (" .params_types = %lld\n", tps[i]->params_types);
- printf ("};\n");
- }
- }
-
-
- return 0;
-}
-
-void usage (void) {
- printf ("usage: generate [-v] [-h] \n"
- );
- exit (2);
-}
-
-void logprintf (const char *format, ...) __attribute__ ((format (printf, 1, 2)));
-void logprintf (const char *format __attribute__ ((unused)), ...) {
-}
-/*
-void hexdump (int *in_ptr, int *in_end) {
- int *ptr = in_ptr;
- while (ptr < in_end) { printf (" %08x", *(ptr ++)); }
- printf ("\n");
-}*/
-
-#ifdef HAVE_EXECINFO_H
-void print_backtrace (void) {
- void *buffer[255];
- const int calls = backtrace (buffer, sizeof (buffer) / sizeof (void *));
- backtrace_symbols_fd (buffer, calls, 1);
-}
-#else
-void print_backtrace (void) {
- if (write (1, "No libexec. Backtrace disabled\n", 32) < 0) {
- // Sad thing
- }
-}
-#endif
-
-void sig_segv_handler (int signum __attribute__ ((unused))) {
- if (write (1, "SIGSEGV received\n", 18) < 0) {
- // Sad thing
- }
- print_backtrace ();
- exit (EXIT_FAILURE);
-}
-
-void sig_abrt_handler (int signum __attribute__ ((unused))) {
- if (write (1, "SIGABRT received\n", 18) < 0) {
- // Sad thing
- }
- print_backtrace ();
- exit (EXIT_FAILURE);
-}
-
-int main (int argc, char **argv) {
- signal (SIGSEGV, sig_segv_handler);
- signal (SIGABRT, sig_abrt_handler);
- int i;
- while ((i = getopt (argc, argv, "vhH")) != -1) {
- switch (i) {
- case 'h':
- usage ();
- return 2;
- case 'v':
- verbosity++;
- break;
- case 'H':
- header ++;
- break;
- }
- }
-
- if (argc != optind + 1) {
- usage ();
- }
-
- int fd = open (argv[optind], O_RDONLY);
- if (fd < 0) {
- fprintf (stderr, "Can not open file '%s'. Error %m\n", argv[optind]);
- exit (1);
- }
- buf_size = read (fd, buf, (1 << 20));
- if (fd == (1 << 20)) {
- fprintf (stderr, "Too big tlo file\n");
- exit (2);
- }
- return parse_tlo_file ();
-}
diff --git a/generate.h b/generate.h
deleted file mode 100644
index be5bc94..0000000
--- a/generate.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- This file is part of tgl-libary/generate
-
- Tgl-library/generate 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.
-
- Tgl-library/generate 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.
-
- You should have received a copy of the GNU General Public License
- along with this tgl-library/generate. If not, see .
-
- Copyright Vitaly Valtman 2014
-
- It is derivative work of VK/KittenPHP-DB-Engine (https://github.com/vk-com/kphp-kdb/)
- Copyright 2012-2013 Vkontakte Ltd
- 2012-2013 Vitaliy Valtman
-*/
-
-#ifndef __GENERATE_H__
-#define __GENERATE_H__
-
-struct tl_combinator;
-
-struct tl_type {
-// struct tl_type_methods *methods;
- char *id;
- char *print_id;
- unsigned name;
- int arity;
- int flags;
- int constructors_num;
- struct tl_combinator **constructors;
- long long params_types;
- int extra;
-};
-
-#define NODE_TYPE_TYPE 1
-#define NODE_TYPE_NAT_CONST 2
-#define NODE_TYPE_VAR_TYPE 3
-#define NODE_TYPE_VAR_NUM 4
-#define NODE_TYPE_ARRAY 5
-
-#define MAX_COMBINATOR_VARS 64
-
-#define NAME_VAR_NUM 0x70659eff
-#define NAME_VAR_TYPE 0x2cecf817
-#define NAME_INT 0xa8509bda
-#define NAME_LONG 0x22076cba
-#define NAME_DOUBLE 0x2210c154
-#define NAME_STRING 0xb5286e24
-#define NAME_VECTOR 0x1cb5c415
-#define NAME_MAYBE_TRUE 0x3f9c8ef8
-#define NAME_MAYBE_FALSE 0x27930a7b
-#define NAME_BOOL_FALSE 0xbc799737
-#define NAME_BOOL_TRUE 0x997275b5
-
-#define FLAG_OPT_VAR (1 << 17)
-#define FLAG_EXCL (1 << 18)
-#define FLAG_OPT_FIELD (1 << 20)
-#define FLAG_NOVAR (1 << 21)
-#define FLAG_BARE 1
-#define FLAGS_MASK ((1 << 16) - 1)
-#define FLAG_DEFAULT_CONSTRUCTOR (1 << 25)
-#define FLAG_NOCONS (1 << 1)
-
-extern struct tl_tree_methods tl_nat_const_methods;
-extern struct tl_tree_methods tl_nat_const_full_methods;
-extern struct tl_tree_methods tl_pnat_const_full_methods;
-extern struct tl_tree_methods tl_array_methods;
-extern struct tl_tree_methods tl_type_methods;
-extern struct tl_tree_methods tl_parray_methods;
-extern struct tl_tree_methods tl_ptype_methods;
-extern struct tl_tree_methods tl_var_num_methods;
-extern struct tl_tree_methods tl_var_type_methods;
-extern struct tl_tree_methods tl_pvar_num_methods;
-extern struct tl_tree_methods tl_pvar_type_methods;
-#define TL_IS_NAT_VAR(x) (((long)x) & 1)
-#define TL_TREE_METHODS(x) (TL_IS_NAT_VAR (x) ? &tl_nat_const_methods : ((struct tl_tree *)(x))->methods)
-
-#define DEC_REF(x) (TL_TREE_METHODS(x)->dec_ref ((void *)x))
-#define INC_REF(x) (TL_TREE_METHODS(x)->inc_ref ((void *)x))
-#define TYPE(x) (TL_TREE_METHODS(x)->type ((void *)x))
-
-typedef unsigned long long tl_tree_hash_t;
-struct tl_tree;
-
-struct tl_tree_methods {
- int (*type)(struct tl_tree *T);
- int (*eq)(struct tl_tree *T, struct tl_tree *U);
- void (*inc_ref)(struct tl_tree *T);
- void (*dec_ref)(struct tl_tree *T);
-};
-
-struct tl_tree {
- int ref_cnt;
- int flags;
- //tl_tree_hash_t hash;
- struct tl_tree_methods *methods;
-};
-/*
-struct tl_tree_nat_const {
- struct tl_tree self;
- int value;
-};*/
-
-struct tl_tree_type {
- struct tl_tree self;
-
- struct tl_type *type;
- int children_num;
- struct tl_tree **children;
-};
-
-struct tl_tree_array {
- struct tl_tree self;
-
- struct tl_tree *multiplicity;
- int args_num;
- struct arg **args;
-};
-
-struct tl_tree_var_type {
- struct tl_tree self;
-
- int var_num;
-};
-
-struct tl_tree_var_num {
- struct tl_tree self;
-
- int var_num;
- int dif;
-};
-
-struct tl_tree_nat_const {
- struct tl_tree self;
-
- long long value;
-};
-
-struct arg {
- char *id;
- int var_num;
- int flags;
- int exist_var_num;
- int exist_var_bit;
- struct tl_tree *type;
-};
-
-struct tl_combinator {
- //struct tl_combinator_methods *methods;
- char *id;
- char *print_id;
- unsigned name;
- int is_fun;
- int var_num;
- int args_num;
- struct arg **args;
- struct tl_tree *result;
- void **IP;
- void **fIP;
- int IP_len;
- int fIP_len;
-};
-
-#endif
diff --git a/include.h b/include.h
deleted file mode 100644
index bf290a1..0000000
--- a/include.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- This file is part of telegram-client.
-
- 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,
- 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.
-
- You should have received a copy of the GNU General Public License
- along with this telegram-client. If not, see .
-
- Copyright Vitaly Valtman 2013
-*/
-#ifndef __INCLUDE_H__
-#define __INCLUDE_H__
-
-#define UU __attribute__ ((unused))
-
-#endif
diff --git a/interface.c b/interface.c
index 8c7e225..057b0e0 100644
--- a/interface.c
+++ b/interface.c
@@ -38,7 +38,6 @@
#endif
#include
-#include "include.h"
//#include "queries.h"
#include "interface.h"
@@ -62,7 +61,7 @@
//#include "mtproto-common.h"
-#include "tgl.h"
+#include
#include "loop.h"
#ifndef PATH_MAX
@@ -496,7 +495,7 @@ char *get_default_prompt (void) {
return buf;
}
-char *complete_none (const char *text UU, int state UU) {
+char *complete_none (const char *text, int state) {
return 0;
}
@@ -1371,7 +1370,7 @@ char *command_generator (const char *text, int state) {
}
}
-char **complete_text (char *text, int start UU, int end UU) {
+char **complete_text (char *text, int start, int end) {
return (char **) rl_completion_matches (text, command_generator);
}
@@ -2045,7 +2044,7 @@ struct tgl_update_callback upd_cb = {
};
-void interpreter_ex (char *line UU, void *ex) {
+void interpreter_ex (char *line, void *ex) {
force_end_mode = 1;
assert (!in_readline);
in_readline = 1;
@@ -2279,7 +2278,7 @@ void interpreter_ex (char *line UU, void *ex) {
in_readline = 0;
}
-void interpreter (char *line UU) {
+void interpreter (char *line) {
interpreter_ex (line, 0);
}
diff --git a/interface.h b/interface.h
index 81fa41b..cc9c64c 100644
--- a/interface.h
+++ b/interface.h
@@ -18,8 +18,8 @@
*/
#ifndef __INTERFACE_H__
#define __INTERFACE_H__
-#include "structures.h"
-#include "tgl-layout.h"
+#include
+#include
#define COLOR_RED "\033[0;31m"
#define COLOR_REDB "\033[1;31m"
diff --git a/loop.c b/loop.c
index 65e6335..1c7892e 100644
--- a/loop.c
+++ b/loop.c
@@ -57,10 +57,10 @@
#include "telegram.h"
#include "loop.h"
#include "lua-tg.h"
-#include "tgl.h"
-#include "binlog.h"
-#include "net.h"
-#include "tgl-timers.h"
+#include
+#include
+#include
+#include
int verbosity;
extern int readline_disabled;
@@ -708,6 +708,7 @@ int loop (void) {
tgl_set_ev_base (TLS, ev);
tgl_set_net_methods (TLS, &tgl_conn_methods);
tgl_set_timer_methods (TLS, &tgl_libevent_timers);
+ assert (TLS->timer_methods);
tgl_set_download_directory (TLS, get_downloads_directory ());
tgl_init (TLS);
diff --git a/lua-tg.c b/lua-tg.c
index f27ccb0..57bb119 100644
--- a/lua-tg.c
+++ b/lua-tg.c
@@ -24,7 +24,6 @@
#ifdef USE_LUA
#include "lua-tg.h"
-#include "include.h"
#include
#include
@@ -42,7 +41,7 @@ lua_State *luaState;
//#include "interface.h"
//#include "auto/constants.h"
-#include "tgl.h"
+#include
#include "interface.h"
#include
@@ -52,7 +51,7 @@ extern struct tgl_state *TLS;
static int have_file;
#define my_lua_checkstack(L,x) assert (lua_checkstack (L, x))
-void push_user (tgl_peer_t *P UU);
+void push_user (tgl_peer_t *P);
void push_peer (tgl_peer_id_t id, tgl_peer_t *P);
void lua_add_string_field (const char *name, const char *value) {
@@ -96,7 +95,7 @@ void push_tgl_peer_type (int x) {
}
}
-void push_user (tgl_peer_t *P UU) {
+void push_user (tgl_peer_t *P) {
my_lua_checkstack (luaState, 4);
lua_add_string_field ("first_name", P->user.first_name);
lua_add_string_field ("last_name", P->user.last_name);
@@ -387,7 +386,7 @@ void lua_our_id (int id) {
}
}
-void lua_new_msg (struct tgl_message *M UU) {
+void lua_new_msg (struct tgl_message *M) {
if (!have_file) { return; }
lua_settop (luaState, 0);
//lua_checkstack (luaState, 20);
diff --git a/lua-tg.h b/lua-tg.h
index 65346a6..2db43b8 100644
--- a/lua-tg.h
+++ b/lua-tg.h
@@ -20,8 +20,7 @@
#define __LUA_TG_H__
#include
-#include "lua-tg.h"
-#include "tgl.h"
+#include
void lua_init (const char *file);
void lua_new_msg (struct tgl_message *M);
diff --git a/main.c b/main.c
index 83fa3c1..16e2bf9 100644
--- a/main.c
+++ b/main.c
@@ -64,13 +64,13 @@
#include "telegram.h"
#include "loop.h"
#include "interface.h"
-#include "tools.h"
+#include
#ifdef USE_LUA
# include "lua-tg.h"
#endif
-#include "tgl.h"
+#include
#define PROGNAME "telegram-cli"
#define VERSION "0.07"
diff --git a/mtproto-client.c b/mtproto-client.c
deleted file mode 100644
index e97423e..0000000
--- a/mtproto-client.c
+++ /dev/null
@@ -1,1462 +0,0 @@
-/*
- This file is part of tgl-library
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library 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
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
- Copyright Nikolay Durov, Andrey Lopatin 2012-2013
- Vitaly Valtman 2013-2014
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#define _FILE_OFFSET_BITS 64
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#if defined(__FreeBSD__) || defined(__OpenBSD__)
-#include
-#endif
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-//#include "telegram.h"
-#include "include.h"
-#include "queries.h"
-//#include "loop.h"
-#include "structures.h"
-#include "binlog.h"
-#include "auto.h"
-#include "tgl.h"
-#include "mtproto-client.h"
-#include "tools.h"
-#include "tree.h"
-#include "updates.h"
-
-#if defined(__FreeBSD__)
-#define __builtin_bswap32(x) bswap32(x)
-#endif
-
-#if defined(__OpenBSD__)
-#define __builtin_bswap32(x) __swap32gen(x)
-#endif
-
-#define sha1 SHA1
-
-#include "mtproto-common.h"
-
-#define MAX_NET_RES (1L << 16)
-//extern int log_level;
-
-#if !defined(HAVE___BUILTIN_BSWAP32) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
-static inline unsigned __builtin_bswap32(unsigned x) {
- return ((x << 24) & 0xff000000 ) |
- ((x << 8) & 0x00ff0000 ) |
- ((x >> 8) & 0x0000ff00 ) |
- ((x >> 24) & 0x000000ff );
-}
-#endif
-
-//int verbosity;
-//static enum tgl_dc_state c_state;
-//extern int binlog_enabled;
-//extern int disable_auto_accept;
-//extern int allow_weak_random;
-
-static int total_packets_sent;
-static long long total_data_sent;
-
-
-static int rpc_execute (struct tgl_state *TLS, struct connection *c, int op, int len);
-static int rpc_becomes_ready (struct tgl_state *TLS, struct connection *c);
-static int rpc_close (struct tgl_state *TLS, struct connection *c);
-
-static long long precise_time;
-
-static double get_utime (int clock_id) {
- struct timespec T;
- tgl_my_clock_gettime (clock_id, &T);
- double res = T.tv_sec + (double) T.tv_nsec * 1e-9;
- if (clock_id == CLOCK_REALTIME) {
- precise_time = (long long) (res * (1LL << 32));
- }
- return res;
-}
-
-
-//#define STATS_BUFF_SIZE (64 << 10)
-//static int stats_buff_len;
-//static char stats_buff[STATS_BUFF_SIZE];
-
-#define MAX_RESPONSE_SIZE (1L << 24)
-
-//static int Response_len;
-
-/*
- *
- * STATE MACHINE
- *
- */
-
-#define TG_SERVER_PUBKEY_FILENAME "tg-server.pub"
-//static char *rsa_public_key_name; // = TG_SERVER_PUBKEY_FILENAME;
-//static RSA *pubKey;
-static long long pk_fingerprint;
-
-static int rsa_load_public_key (struct tgl_state *TLS, const char *public_key_name) {
- TLS->pubKey = NULL;
- FILE *f = fopen (public_key_name, "r");
- if (f == NULL) {
- vlogprintf (E_WARNING, "Couldn't open public key file: %s\n", public_key_name);
- return -1;
- }
- TLS->pubKey = PEM_read_RSAPublicKey (f, NULL, NULL, NULL);
- fclose (f);
- if (TLS->pubKey == NULL) {
- vlogprintf (E_WARNING, "PEM_read_RSAPublicKey returns NULL.\n");
- return -1;
- }
-
- vlogprintf (E_WARNING, "public key '%s' loaded successfully\n", public_key_name);
-
- return 0;
-}
-
-
-
-
-
-/*
- *
- * UNAUTHORIZED (DH KEY EXCHANGE) PROTOCOL PART
- *
- */
-
-static BIGNUM dh_prime, dh_g, g_a, auth_key_num;
-static char s_power [256];
-
-static struct {
- long long auth_key_id;
- long long out_msg_id;
- int msg_len;
-} unenc_msg_header;
-
-
-#define ENCRYPT_BUFFER_INTS 16384
-static int encrypt_buffer[ENCRYPT_BUFFER_INTS];
-
-#define DECRYPT_BUFFER_INTS 16384
-static int decrypt_buffer[ENCRYPT_BUFFER_INTS];
-
-static int encrypt_packet_buffer (struct tgl_state *TLS) {
- return tgl_pad_rsa_encrypt (TLS, (char *) packet_buffer, (packet_ptr - packet_buffer) * 4, (char *) encrypt_buffer, ENCRYPT_BUFFER_INTS * 4, ((RSA *)TLS->pubKey)->n, ((RSA *)TLS->pubKey)->e);
-}
-
-static int encrypt_packet_buffer_aes_unauth (const char server_nonce[16], const char hidden_client_nonce[32]) {
- tgl_init_aes_unauth (server_nonce, hidden_client_nonce, AES_ENCRYPT);
- return tgl_pad_aes_encrypt ((char *) packet_buffer, (packet_ptr - packet_buffer) * 4, (char *) encrypt_buffer, ENCRYPT_BUFFER_INTS * 4);
-}
-
-
-static int rpc_send_packet (struct tgl_state *TLS, struct connection *c) {
- int len = (packet_ptr - packet_buffer) * 4;
- //c->out_packet_num ++;
- TLS->net_methods->incr_out_packet_num (c);
- long long next_msg_id = (long long) ((1LL << 32) * get_utime (CLOCK_REALTIME)) & -4;
- if (next_msg_id <= unenc_msg_header.out_msg_id) {
- unenc_msg_header.out_msg_id += 4;
- } else {
- unenc_msg_header.out_msg_id = next_msg_id;
- }
- unenc_msg_header.msg_len = len;
-
- int total_len = len + 20;
- assert (total_len > 0 && !(total_len & 0xfc000003));
- total_len >>= 2;
- vlogprintf (E_DEBUG, "writing packet: total_len = %d, len = %d\n", total_len, len);
- if (total_len < 0x7f) {
- assert (TLS->net_methods->write_out (c, &total_len, 1) == 1);
- } else {
- total_len = (total_len << 8) | 0x7f;
- assert (TLS->net_methods->write_out (c, &total_len, 4) == 4);
- }
- TLS->net_methods->write_out (c, &unenc_msg_header, 20);
- TLS->net_methods->write_out (c, packet_buffer, len);
- TLS->net_methods->flush_out (c);
-
- total_packets_sent ++;
- total_data_sent += total_len;
- return 1;
-}
-
-static int rpc_send_message (struct tgl_state *TLS, struct connection *c, void *data, int len) {
- assert (len > 0 && !(len & 0xfc000003));
- int total_len = len >> 2;
- if (total_len < 0x7f) {
- assert (TLS->net_methods->write_out (c, &total_len, 1) == 1);
- } else {
- total_len = (total_len << 8) | 0x7f;
- assert (TLS->net_methods->write_out (c, &total_len, 4) == 4);
- }
-
- TLS->net_methods->incr_out_packet_num (c);
- assert (TLS->net_methods->write_out (c, data, len) == len);
- TLS->net_methods->flush_out (c);
-
- total_packets_sent ++;
- total_data_sent += total_len;
- return 1;
-}
-
-static int send_req_pq_packet (struct tgl_state *TLS, struct connection *c) {
- struct tgl_dc *D = TLS->net_methods->get_dc (c);
- assert (D->state == st_init);
-
- tglt_secure_random (D->nonce, 16);
- unenc_msg_header.out_msg_id = 0;
- clear_packet ();
- out_int (CODE_req_pq);
- out_ints ((int *)D->nonce, 4);
- rpc_send_packet (TLS, c);
-
- D->state = st_reqpq_sent;
- return 1;
-}
-
-static int send_req_pq_temp_packet (struct tgl_state *TLS, struct connection *c) {
- struct tgl_dc *D = TLS->net_methods->get_dc (c);
- assert (D->state == st_authorized);
-
- tglt_secure_random (D->nonce, 16);
- unenc_msg_header.out_msg_id = 0;
- clear_packet ();
- out_int (CODE_req_pq);
- out_ints ((int *)D->nonce, 4);
- rpc_send_packet (TLS, c);
-
- D->state = st_reqpq_sent_temp;
- return 1;
-}
-
-
-static unsigned long long gcd (unsigned long long a, unsigned long long b) {
- return b ? gcd (b, a % b) : a;
-}
-
-//typedef unsigned int uint128_t __attribute__ ((mode(TI)));
-
-static int process_respq_answer (struct tgl_state *TLS, struct connection *c, char *packet, int len, int temp_key) {
- struct tgl_dc *D = TLS->net_methods->get_dc (c);
- unsigned long long what;
- unsigned p1, p2;
- int i;
-
- long long packet_auth_key_id = *(long long *)packet;
- if (packet_auth_key_id) {
- assert (temp_key);
- vlogprintf (E_WARNING, "received packet during creation of temp auth key. Probably answer on old query. Drop\n");
- return 0;
- }
- vlogprintf (E_DEBUG, "process_respq_answer(), len=%d, op=0x%08x\n", len, *(int *)(packet + 20));
- assert (len >= 76);
- assert (!*(long long *) packet);
- assert (*(int *) (packet + 16) == len - 20);
- assert (!(len & 3));
- assert (*(int *) (packet + 20) == CODE_resPQ);
- assert (!memcmp (packet + 24, D->nonce, 16));
- memcpy (D->server_nonce, packet + 40, 16);
- char *from = packet + 56;
- int clen = *from++;
- assert (clen <= 8);
- what = 0;
- for (i = 0; i < clen; i++) {
- what = (what << 8) + (unsigned char)*from++;
- }
-
- while (((unsigned long)from) & 3) ++from;
-
- p1 = 0, p2 = 0;
-
- int it = 0;
- unsigned long long g = 0;
- for (i = 0; i < 3 || it < 1000; i++) {
- int q = ((lrand48() & 15) + 17) % what;
- unsigned long long x = (long long)lrand48 () % (what - 1) + 1, y = x;
- int lim = 1 << (i + 18);
- int j;
- for (j = 1; j < lim; j++) {
- ++it;
- unsigned long long a = x, b = x, c = q;
- while (b) {
- if (b & 1) {
- c += a;
- if (c >= what) {
- c -= what;
- }
- }
- a += a;
- if (a >= what) {
- a -= what;
- }
- b >>= 1;
- }
- x = c;
- unsigned long long z = x < y ? what + x - y : x - y;
- g = gcd (z, what);
- if (g != 1) {
- break;
- }
- if (!(j & (j - 1))) {
- y = x;
- }
- }
- if (g > 1 && g < what) break;
- }
-
- assert (g > 1 && g < what);
- p1 = g;
- p2 = what / g;
- if (p1 > p2) {
- unsigned t = p1; p1 = p2; p2 = t;
- }
-
-
- /// ++p1; ///
-
- assert (*(int *) (from) == CODE_vector);
- int fingerprints_num = *(int *)(from + 4);
- assert (fingerprints_num >= 1 && fingerprints_num <= 64 && len == fingerprints_num * 8 + 8 + (from - packet));
- long long *fingerprints = (long long *) (from + 8);
- for (i = 0; i < fingerprints_num; i++) {
- if (fingerprints[i] == pk_fingerprint) {
- //logprintf ( "found our public key at position %d\n", i);
- break;
- }
- }
- if (i == fingerprints_num) {
- vlogprintf (E_ERROR, "fatal: don't have any matching keys (%016llx expected)\n", pk_fingerprint);
- exit (2);
- }
- // create inner part (P_Q_inner_data)
- clear_packet ();
- packet_ptr += 5;
- out_int (temp_key ? CODE_p_q_inner_data_temp : CODE_p_q_inner_data);
- out_cstring (packet + 57, clen);
- //out_int (0x0f01); // pq=15
-
- if (p1 < 256) {
- clen = 1;
- } else if (p1 < 65536) {
- clen = 2;
- } else if (p1 < 16777216) {
- clen = 3;
- } else {
- clen = 4;
- }
- p1 = __builtin_bswap32 (p1);
- out_cstring ((char *)&p1 + 4 - clen, clen);
- p1 = __builtin_bswap32 (p1);
-
- if (p2 < 256) {
- clen = 1;
- } else if (p2 < 65536) {
- clen = 2;
- } else if (p2 < 16777216) {
- clen = 3;
- } else {
- clen = 4;
- }
- p2 = __builtin_bswap32 (p2);
- out_cstring ((char *)&p2 + 4 - clen, clen);
- p2 = __builtin_bswap32 (p2);
-
- //out_int (0x0301); // p=3
- //out_int (0x0501); // q=5
- out_ints ((int *) D->nonce, 4);
- out_ints ((int *) D->server_nonce, 4);
- tglt_secure_random (D->new_nonce, 32);
- out_ints ((int *) D->new_nonce, 8);
- if (temp_key) {
- out_int (TLS->temp_key_expire_time);
- }
- sha1 ((unsigned char *) (packet_buffer + 5), (packet_ptr - packet_buffer - 5) * 4, (unsigned char *) packet_buffer);
-
- int l = encrypt_packet_buffer (TLS);
-
- clear_packet ();
- out_int (CODE_req_DH_params);
- out_ints ((int *) D->nonce, 4);
- out_ints ((int *) D->server_nonce, 4);
- //out_int (0x0301); // p=3
- //out_int (0x0501); // q=5
- if (p1 < 256) {
- clen = 1;
- } else if (p1 < 65536) {
- clen = 2;
- } else if (p1 < 16777216) {
- clen = 3;
- } else {
- clen = 4;
- }
- p1 = __builtin_bswap32 (p1);
- out_cstring ((char *)&p1 + 4 - clen, clen);
- p1 = __builtin_bswap32 (p1);
- if (p2 < 256) {
- clen = 1;
- } else if (p2 < 65536) {
- clen = 2;
- } else if (p2 < 16777216) {
- clen = 3;
- } else {
- clen = 4;
- }
- p2 = __builtin_bswap32 (p2);
- out_cstring ((char *)&p2 + 4 - clen, clen);
- p2 = __builtin_bswap32 (p2);
-
- out_long (pk_fingerprint);
- out_cstring ((char *) encrypt_buffer, l);
-
- D->state = temp_key ? st_reqdh_sent_temp : st_reqdh_sent;
-
- return rpc_send_packet (TLS, c);
-}
-
-static int check_prime (struct tgl_state *TLS, BIGNUM *p) {
- int r = BN_is_prime (p, BN_prime_checks, 0, TLS->BN_ctx, 0);
- ensure (r >= 0);
- return r;
-}
-
-int tglmp_check_DH_params (struct tgl_state *TLS, BIGNUM *p, int g) {
- if (g < 2 || g > 7) { return -1; }
- if (BN_num_bits (p) != 2048) { return -1; }
- BIGNUM t;
- BN_init (&t);
-
- BN_init (&dh_g);
- ensure (BN_set_word (&dh_g, 4 * g));
-
- ensure (BN_mod (&t, p, &dh_g, TLS->BN_ctx));
- int x = BN_get_word (&t);
- assert (x >= 0 && x < 4 * g);
-
- BN_free (&dh_g);
-
- switch (g) {
- case 2:
- if (x != 7) { return -1; }
- break;
- case 3:
- if (x % 3 != 2 ) { return -1; }
- break;
- case 4:
- break;
- case 5:
- if (x % 5 != 1 && x % 5 != 4) { return -1; }
- break;
- case 6:
- if (x != 19 && x != 23) { return -1; }
- break;
- case 7:
- if (x % 7 != 3 && x % 7 != 5 && x % 7 != 6) { return -1; }
- break;
- }
-
- if (!check_prime (TLS, p)) { return -1; }
-
- BIGNUM b;
- BN_init (&b);
- ensure (BN_set_word (&b, 2));
- ensure (BN_div (&t, 0, p, &b, TLS->BN_ctx));
- if (!check_prime (TLS, &t)) { return -1; }
- BN_free (&b);
- BN_free (&t);
- return 0;
-}
-
-int tglmp_check_g (struct tgl_state *TLS, unsigned char p[256], BIGNUM *g) {
- static unsigned char s[256];
- memset (s, 0, 256);
- assert (BN_num_bytes (g) <= 256);
- BN_bn2bin (g, s + (256 - BN_num_bytes (g)));
- int ok = 0;
- int i;
- for (i = 0; i < 64; i++) {
- if (s[i]) {
- ok = 1;
- break;
- }
- }
- if (!ok) { return -1; }
- ok = 0;
- for (i = 0; i < 64; i++) {
- if (s[255 - i]) {
- ok = 1;
- break;
- }
- }
- if (!ok) { return -1; }
- ok = 0;
- for (i = 0; i < 64; i++) {
- if (s[i] < p[i]) {
- ok = 1;
- break;
- } else if (s[i] > p[i]) {
- vlogprintf (E_WARNING, "i = %d (%d %d)\n", i, (int)s[i], (int)p[i]);
- return -1;
- }
- }
- if (!ok) { return -1; }
- return 0;
-}
-
-int tglmp_check_g_bn (struct tgl_state *TLS, BIGNUM *p, BIGNUM *g) {
- static unsigned char s[256];
- memset (s, 0, 256);
- assert (BN_num_bytes (p) == 256);
- BN_bn2bin (p, s);
- return tglmp_check_g (TLS, s, g);
-}
-
-static int process_dh_answer (struct tgl_state *TLS, struct connection *c, char *packet, int len, int temp_key) {
- struct tgl_dc *D = TLS->net_methods->get_dc (c);
- vlogprintf (E_DEBUG, "process_dh_answer(), len=%d\n", len);
- //if (len < 116) {
- // vlogprintf (E_ERROR, "%u * %u = %llu", p1, p2, what);
- //}
- long long packet_auth_key_id = *(long long *)packet;
- if (packet_auth_key_id) {
- assert (temp_key);
- vlogprintf (E_WARNING, "received packet during creation of temp auth key. Probably answer on old query. Drop\n");
- return 0;
- }
- assert (len >= 116);
- assert (!*(long long *) packet);
- assert (*(int *) (packet + 16) == len - 20);
- assert (!(len & 3));
- assert (*(int *) (packet + 20) == (int)CODE_server_DH_params_ok);
- assert (!memcmp (packet + 24, D->nonce, 16));
- assert (!memcmp (packet + 40, D->server_nonce, 16));
- tgl_init_aes_unauth (D->server_nonce, D->new_nonce, AES_DECRYPT);
- in_ptr = (int *)(packet + 56);
- in_end = (int *)(packet + len);
- int l = prefetch_strlen ();
- assert (l > 0);
- l = tgl_pad_aes_decrypt (fetch_str (l), l, (char *) decrypt_buffer, DECRYPT_BUFFER_INTS * 4 - 16);
- assert (in_ptr == in_end);
- assert (l >= 60);
- assert (decrypt_buffer[5] == (int)CODE_server_DH_inner_data);
- assert (!memcmp (decrypt_buffer + 6, D->nonce, 16));
- assert (!memcmp (decrypt_buffer + 10, D->server_nonce, 16));
- int g = decrypt_buffer[14];
- in_ptr = decrypt_buffer + 15;
- in_end = decrypt_buffer + (l >> 2);
- BN_init (&dh_prime);
- BN_init (&g_a);
- assert (fetch_bignum (&dh_prime) > 0);
- assert (fetch_bignum (&g_a) > 0);
- assert (tglmp_check_g_bn (TLS, &dh_prime, &g_a) >= 0);
- int server_time = *in_ptr++;
- assert (in_ptr <= in_end);
-
- assert (tglmp_check_DH_params (TLS, &dh_prime, g) >= 0);
-
- static char sha1_buffer[20];
- sha1 ((unsigned char *) decrypt_buffer + 20, (in_ptr - decrypt_buffer - 5) * 4, (unsigned char *) sha1_buffer);
- assert (!memcmp (decrypt_buffer, sha1_buffer, 20));
- assert ((char *) in_end - (char *) in_ptr < 16);
-
- D->server_time_delta = server_time - time (0);
- D->server_time_udelta = server_time - get_utime (CLOCK_MONOTONIC);
- //logprintf ( "server time is %d, delta = %d\n", server_time, server_time_delta);
-
- // Build set_client_DH_params answer
- clear_packet ();
- packet_ptr += 5;
- out_int (CODE_client_DH_inner_data);
- out_ints ((int *) D->nonce, 4);
- out_ints ((int *) D->server_nonce, 4);
- out_long (0LL);
-
- BN_init (&dh_g);
- ensure (BN_set_word (&dh_g, g));
-
- tglt_secure_random (s_power, 256);
- BIGNUM *dh_power = BN_bin2bn ((unsigned char *)s_power, 256, 0);
- ensure_ptr (dh_power);
-
- BIGNUM *y = BN_new ();
- ensure_ptr (y);
- ensure (BN_mod_exp (y, &dh_g, dh_power, &dh_prime, TLS->BN_ctx));
- out_bignum (y);
- BN_free (y);
-
- BN_init (&auth_key_num);
- ensure (BN_mod_exp (&auth_key_num, &g_a, dh_power, &dh_prime, TLS->BN_ctx));
- l = BN_num_bytes (&auth_key_num);
- assert (l >= 250 && l <= 256);
- assert (BN_bn2bin (&auth_key_num, (unsigned char *)(temp_key ? D->temp_auth_key : D->auth_key)));
- if (l < 256) {
- char *key = temp_key ? D->temp_auth_key : D->auth_key;
- memmove (key + 256 - l, key, l);
- memset (key, 0, 256 - l);
- }
-
- BN_free (dh_power);
- BN_free (&auth_key_num);
- BN_free (&dh_g);
- BN_free (&g_a);
- BN_free (&dh_prime);
-
- //hexdump (auth_key, auth_key + 256);
-
- sha1 ((unsigned char *) (packet_buffer + 5), (packet_ptr - packet_buffer - 5) * 4, (unsigned char *) packet_buffer);
-
- //hexdump ((char *)packet_buffer, (char *)packet_ptr);
-
- l = encrypt_packet_buffer_aes_unauth (D->server_nonce, D->new_nonce);
-
- clear_packet ();
- out_int (CODE_set_client_DH_params);
- out_ints ((int *) D->nonce, 4);
- out_ints ((int *) D->server_nonce, 4);
- out_cstring ((char *) encrypt_buffer, l);
-
- D->state = temp_key ? st_client_dh_sent_temp : st_client_dh_sent;;
-
- return rpc_send_packet (TLS, c);
-}
-
-static void create_temp_auth_key (struct tgl_state *TLS, struct connection *c) {
- send_req_pq_temp_packet (TLS, c);
-}
-
-int tglmp_encrypt_inner_temp (struct tgl_state *TLS, struct connection *c, int *msg, int msg_ints, int useful, void *data, long long msg_id);
-static long long generate_next_msg_id (struct tgl_state *TLS, struct tgl_dc *DC);
-static long long msg_id_override;
-static void mpc_on_get_config (struct tgl_state *TLS, void *extra, int success);
-static int process_auth_complete (struct tgl_state *TLS, struct connection *c UU, char *packet, int len, int temp_key) {
- struct tgl_dc *D = TLS->net_methods->get_dc (c);
- vlogprintf (E_DEBUG - 1, "process_dh_answer(), len=%d\n", len);
-
- long long packet_auth_key_id = *(long long *)packet;
- if (packet_auth_key_id) {
- assert (temp_key);
- vlogprintf (E_WARNING, "received packet during creation of temp auth key. Probably answer on old query. Drop\n");
- return 0;
- }
- assert (len == 72);
- assert (!*(long long *) packet);
- assert (*(int *) (packet + 16) == len - 20);
- assert (!(len & 3));
- assert (*(int *) (packet + 20) == CODE_dh_gen_ok);
- assert (!memcmp (packet + 24, D->nonce, 16));
- assert (!memcmp (packet + 40, D->server_nonce, 16));
- static unsigned char tmp[44], sha1_buffer[20];
- memcpy (tmp, D->new_nonce, 32);
- tmp[32] = 1;
- //GET_DC(c)->auth_key_id = *(long long *)(sha1_buffer + 12);
-
- if (!temp_key) {
- bl_do_set_auth_key_id (TLS, D->id, (unsigned char *)D->auth_key);
- sha1 ((unsigned char *)D->auth_key, 256, sha1_buffer);
- } else {
- sha1 ((unsigned char *)D->temp_auth_key, 256, sha1_buffer);
- D->temp_auth_key_id = *(long long *)(sha1_buffer + 12);
- }
-
- memcpy (tmp + 33, sha1_buffer, 8);
- sha1 (tmp, 41, sha1_buffer);
- assert (!memcmp (packet + 56, sha1_buffer + 4, 16));
- D->server_salt = *(long long *)D->server_nonce ^ *(long long *)D->new_nonce;
-
- //kprintf ("OK\n");
-
- //c->status = conn_error;
- //sleep (1);
-
- D->state = st_authorized;
- //return 1;
- vlogprintf (E_DEBUG, "Auth success\n");
- if (temp_key) {
- //D->flags |= 2;
-
- long long msg_id = generate_next_msg_id (TLS, D);
- clear_packet ();
- out_int (CODE_bind_auth_key_inner);
- long long rand;
- tglt_secure_random (&rand, 8);
- out_long (rand);
- out_long (D->temp_auth_key_id);
- out_long (D->auth_key_id);
-
- struct tgl_session *S = TLS->net_methods->get_session (c);
- if (!S->session_id) {
- tglt_secure_random (&S->session_id, 8);
- }
- out_long (S->session_id);
- int expires = time (0) + D->server_time_delta + TLS->temp_key_expire_time;
- out_int (expires);
-
- static int data[1000];
- int len = tglmp_encrypt_inner_temp (TLS, c, packet_buffer, packet_ptr - packet_buffer, 0, data, msg_id);
- msg_id_override = msg_id;
- tgl_do_send_bind_temp_key (TLS, D, rand, expires, (void *)data, len, msg_id);
- msg_id_override = 0;
- } else {
- D->flags |= 1;
- if (TLS->enable_pfs) {
- create_temp_auth_key (TLS, c);
- } else {
- D->temp_auth_key_id = D->auth_key_id;
- memcpy (D->temp_auth_key, D->auth_key, 256);
- D->flags |= 2;
- if (!(D->flags & 4)) {
- tgl_do_help_get_config_dc (TLS, D, mpc_on_get_config, D);
- }
- }
- }
-
- //write_auth_file ();
-
- return 1;
-}
-
-/*
- *
- * AUTHORIZED (MAIN) PROTOCOL PART
- *
- */
-
-static struct encrypted_message enc_msg;
-
-static long long client_last_msg_id, server_last_msg_id;
-
-static double get_server_time (struct tgl_dc *DC) {
- if (!DC->server_time_udelta) {
- DC->server_time_udelta = get_utime (CLOCK_REALTIME) - get_utime (CLOCK_MONOTONIC);
- }
- return get_utime (CLOCK_MONOTONIC) + DC->server_time_udelta;
-}
-
-static long long generate_next_msg_id (struct tgl_state *TLS, struct tgl_dc *DC) {
- long long next_id = (long long) (get_server_time (DC) * (1LL << 32)) & -4;
- if (next_id <= client_last_msg_id) {
- next_id = client_last_msg_id += 4;
- } else {
- client_last_msg_id = next_id;
- }
- return next_id;
-}
-
-static void init_enc_msg (struct tgl_state *TLS, struct tgl_session *S, int useful) {
- struct tgl_dc *DC = S->dc;
- assert (DC->state == st_authorized);
- //assert (DC->flags & 2);
- assert (DC->temp_auth_key_id);
- vlogprintf (E_DEBUG, "temp_auth_key_id = 0x%016llx, auth_key_id = 0x%016llx\n", DC->temp_auth_key_id, DC->auth_key_id);
- enc_msg.auth_key_id = DC->temp_auth_key_id;
-// assert (DC->server_salt);
- enc_msg.server_salt = DC->server_salt;
- if (!S->session_id) {
- tglt_secure_random (&S->session_id, 8);
- }
- enc_msg.session_id = S->session_id;
- //enc_msg.auth_key_id2 = auth_key_id;
- enc_msg.msg_id = msg_id_override ? msg_id_override : generate_next_msg_id (TLS, DC);
- //enc_msg.msg_id -= 0x10000000LL * (lrand48 () & 15);
- //kprintf ("message id %016llx\n", enc_msg.msg_id);
- enc_msg.seq_no = S->seq_no;
- if (useful) {
- enc_msg.seq_no |= 1;
- }
- S->seq_no += 2;
-};
-
-static void init_enc_msg_inner_temp (struct tgl_dc *DC, long long msg_id) {
- enc_msg.auth_key_id = DC->auth_key_id;
- tglt_secure_random (&enc_msg.server_salt, 8);
- tglt_secure_random (&enc_msg.session_id, 8);
- enc_msg.msg_id = msg_id;
- enc_msg.seq_no = 0;
-};
-
-
-static int aes_encrypt_message (struct tgl_state *TLS, char *key, struct encrypted_message *enc) {
- unsigned char sha1_buffer[20];
- const int MINSZ = offsetof (struct encrypted_message, message);
- const int UNENCSZ = offsetof (struct encrypted_message, server_salt);
- int enc_len = (MINSZ - UNENCSZ) + enc->msg_len;
- assert (enc->msg_len >= 0 && enc->msg_len <= MAX_MESSAGE_INTS * 4 - 16 && !(enc->msg_len & 3));
- sha1 ((unsigned char *) &enc->server_salt, enc_len, sha1_buffer);
- //printf ("enc_len is %d\n", enc_len);
- vlogprintf (E_DEBUG, "sending message with sha1 %08x\n", *(int *)sha1_buffer);
- memcpy (enc->msg_key, sha1_buffer + 4, 16);
- tgl_init_aes_auth (key, enc->msg_key, AES_ENCRYPT);
- //hexdump ((char *)enc, (char *)enc + enc_len + 24);
- return tgl_pad_aes_encrypt ((char *) &enc->server_salt, enc_len, (char *) &enc->server_salt, MAX_MESSAGE_INTS * 4 + (MINSZ - UNENCSZ));
-}
-
-long long tglmp_encrypt_send_message (struct tgl_state *TLS, struct connection *c, int *msg, int msg_ints, int flags) {
- struct tgl_dc *DC = TLS->net_methods->get_dc (c);
- if (!(DC->flags & 4) && !(flags & 2)) {
- return generate_next_msg_id (TLS, DC);
- }
- struct tgl_session *S = TLS->net_methods->get_session (c);
- assert (S);
-
- const int UNENCSZ = offsetof (struct encrypted_message, server_salt);
- if (msg_ints <= 0 || msg_ints > MAX_MESSAGE_INTS - 4) {
- return -1;
- }
- if (msg) {
- memcpy (enc_msg.message, msg, msg_ints * 4);
- enc_msg.msg_len = msg_ints * 4;
- } else {
- if ((enc_msg.msg_len & 0x80000003) || enc_msg.msg_len > MAX_MESSAGE_INTS * 4 - 16) {
- return -1;
- }
- }
- init_enc_msg (TLS, S, flags & 1);
-
- //hexdump ((char *)msg, (char *)msg + (msg_ints * 4));
- int l = aes_encrypt_message (TLS, DC->temp_auth_key, &enc_msg);
- //hexdump ((char *)&enc_msg, (char *)&enc_msg + l + 24);
- assert (l > 0);
- vlogprintf (E_DEBUG, "Sending message to DC%d: %s:%d with key_id=%lld\n", DC->id, DC->ip, DC->port, enc_msg.auth_key_id);
- rpc_send_message (TLS, c, &enc_msg, l + UNENCSZ);
-
-
- return client_last_msg_id;
-}
-
-int tglmp_encrypt_inner_temp (struct tgl_state *TLS, struct connection *c, int *msg, int msg_ints, int useful, void *data, long long msg_id) {
- struct tgl_dc *DC = TLS->net_methods->get_dc (c);
- struct tgl_session *S = TLS->net_methods->get_session (c);
- assert (S);
-
- const int UNENCSZ = offsetof (struct encrypted_message, server_salt);
- if (msg_ints <= 0 || msg_ints > MAX_MESSAGE_INTS - 4) {
- return -1;
- }
- memcpy (enc_msg.message, msg, msg_ints * 4);
- enc_msg.msg_len = msg_ints * 4;
-
- init_enc_msg_inner_temp (DC, msg_id);
-
- int l = aes_encrypt_message (TLS, DC->auth_key, &enc_msg);
- assert (l > 0);
- //rpc_send_message (c, &enc_msg, l + UNENCSZ);
- memcpy (data, &enc_msg, l + UNENCSZ);
-
- return l + UNENCSZ;
-}
-
-static int good_messages;
-
-static void rpc_execute_answer (struct tgl_state *TLS, struct connection *c, long long msg_id UU);
-
-//int unread_messages;
-//int pts;
-//int qts;
-//int last_date;
-//int seq;
-
-static void work_container (struct tgl_state *TLS, struct connection *c, long long msg_id UU) {
- vlogprintf (E_DEBUG, "work_container: msg_id = %lld\n", msg_id);
- assert (fetch_int () == CODE_msg_container);
- int n = fetch_int ();
- int i;
- for (i = 0; i < n; i++) {
- long long id = fetch_long ();
- //int seqno = fetch_int ();
- fetch_int (); // seq_no
- if (id & 1) {
- tgln_insert_msg_id (TLS, TLS->net_methods->get_session (c), id);
- }
- int bytes = fetch_int ();
- int *t = in_end;
- in_end = in_ptr + (bytes / 4);
- rpc_execute_answer (TLS, c, id);
- assert (in_ptr == in_end);
- in_end = t;
- }
-}
-
-static void work_new_session_created (struct tgl_state *TLS, struct connection *c, long long msg_id UU) {
- vlogprintf (E_DEBUG, "work_new_session_created: msg_id = %lld\n", msg_id);
- assert (fetch_int () == (int)CODE_new_session_created);
- fetch_long (); // first message id
- //DC->session_id = fetch_long ();
- fetch_long (); // unique_id
- TLS->net_methods->get_dc (c)->server_salt = fetch_long ();
- if (TLS->started && !(TLS->locks & TGL_LOCK_DIFF)) {
- tgl_do_get_difference (TLS, 0, 0, 0);
- }
-}
-
-static void work_msgs_ack (struct tgl_state *TLS, struct connection *c UU, long long msg_id UU) {
- vlogprintf (E_DEBUG, "work_msgs_ack: msg_id = %lld\n", msg_id);
- assert (fetch_int () == CODE_msgs_ack);
- assert (fetch_int () == CODE_vector);
- int n = fetch_int ();
- int i;
- for (i = 0; i < n; i++) {
- long long id = fetch_long ();
- vlogprintf (E_DEBUG + 1, "ack for %lld\n", id);
- tglq_query_ack (TLS, id);
- }
-}
-
-static void work_rpc_result (struct tgl_state *TLS, struct connection *c UU, long long msg_id UU) {
- vlogprintf (E_DEBUG, "work_rpc_result: msg_id = %lld\n", msg_id);
- assert (fetch_int () == (int)CODE_rpc_result);
- long long id = fetch_long ();
- int op = prefetch_int ();
- if (op == CODE_rpc_error) {
- tglq_query_error (TLS, id);
- } else {
- tglq_query_result (TLS, id);
- }
-}
-
-#define MAX_PACKED_SIZE (1 << 24)
-static void work_packed (struct tgl_state *TLS, struct connection *c, long long msg_id) {
- assert (fetch_int () == CODE_gzip_packed);
- static int in_gzip;
- static int buf[MAX_PACKED_SIZE >> 2];
- assert (!in_gzip);
- in_gzip = 1;
-
- int l = prefetch_strlen ();
- char *s = fetch_str (l);
-
- int total_out = tgl_inflate (s, l, buf, MAX_PACKED_SIZE);
- int *end = in_ptr;
- int *eend = in_end;
- //assert (total_out % 4 == 0);
- in_ptr = buf;
- in_end = in_ptr + total_out / 4;
- rpc_execute_answer (TLS, c, msg_id);
- in_ptr = end;
- in_end = eend;
- in_gzip = 0;
-}
-
-static void work_bad_server_salt (struct tgl_state *TLS, struct connection *c UU, long long msg_id UU) {
- assert (fetch_int () == (int)CODE_bad_server_salt);
- long long id = fetch_long ();
- tglq_query_restart (TLS, id);
- fetch_int (); // seq_no
- fetch_int (); // error_code
- long long new_server_salt = fetch_long ();
- TLS->net_methods->get_dc (c)->server_salt = new_server_salt;
-}
-
-static void work_pong (struct tgl_state *TLS, struct connection *c UU, long long msg_id UU) {
- assert (fetch_int () == CODE_pong);
- fetch_long (); // msg_id
- fetch_long (); // ping_id
-}
-
-static void work_detailed_info (struct tgl_state *TLS, struct connection *c UU, long long msg_id UU) {
- assert (fetch_int () == CODE_msg_detailed_info);
- fetch_long (); // msg_id
- fetch_long (); // answer_msg_id
- fetch_int (); // bytes
- fetch_int (); // status
-}
-
-static void work_new_detailed_info (struct tgl_state *TLS, struct connection *c UU, long long msg_id UU) {
- assert (fetch_int () == (int)CODE_msg_new_detailed_info);
- fetch_long (); // answer_msg_id
- fetch_int (); // bytes
- fetch_int (); // status
-}
-
-static void work_bad_msg_notification (struct tgl_state *TLS, struct connection *c UU, long long msg_id UU) {
- assert (fetch_int () == (int)CODE_bad_msg_notification);
- long long m1 = fetch_long ();
- int s = fetch_int ();
- int e = fetch_int ();
- vlogprintf (E_NOTICE, "bad_msg_notification: msg_id = %lld, seq = %d, error = %d\n", m1, s, e);
-}
-
-static void rpc_execute_answer (struct tgl_state *TLS, struct connection *c, long long msg_id UU) {
- int op = prefetch_int ();
- switch (op) {
- case CODE_msg_container:
- work_container (TLS, c, msg_id);
- return;
- case CODE_new_session_created:
- work_new_session_created (TLS, c, msg_id);
- return;
- case CODE_msgs_ack:
- work_msgs_ack (TLS, c, msg_id);
- return;
- case CODE_rpc_result:
- work_rpc_result (TLS, c, msg_id);
- return;
- case CODE_update_short:
- tglu_work_update_short (TLS, c, msg_id);
- return;
- case CODE_updates:
- tglu_work_updates (TLS, c, msg_id);
- return;
- case CODE_update_short_message:
- tglu_work_update_short_message (TLS, c, msg_id);
- return;
- case CODE_update_short_chat_message:
- tglu_work_update_short_chat_message (TLS, c, msg_id);
- return;
- case CODE_gzip_packed:
- work_packed (TLS, c, msg_id);
- return;
- case CODE_bad_server_salt:
- work_bad_server_salt (TLS, c, msg_id);
- return;
- case CODE_pong:
- work_pong (TLS, c, msg_id);
- return;
- case CODE_msg_detailed_info:
- work_detailed_info (TLS, c, msg_id);
- return;
- case CODE_msg_new_detailed_info:
- work_new_detailed_info (TLS, c, msg_id);
- return;
- case CODE_updates_too_long:
- tglu_work_updates_to_long (TLS, c, msg_id);
- return;
- case CODE_bad_msg_notification:
- work_bad_msg_notification (TLS, c, msg_id);
- return;
- }
- vlogprintf (E_WARNING, "Unknown message: %08x\n", op);
- in_ptr = in_end; // Will not fail due to assertion in_ptr == in_end
-}
-
-static int process_rpc_message (struct tgl_state *TLS, struct connection *c UU, struct encrypted_message *enc, int len) {
- const int MINSZ = offsetof (struct encrypted_message, message);
- const int UNENCSZ = offsetof (struct encrypted_message, server_salt);
- vlogprintf (E_DEBUG, "process_rpc_message(), len=%d\n", len);
- assert (len >= MINSZ && (len & 15) == (UNENCSZ & 15));
- struct tgl_dc *DC = TLS->net_methods->get_dc (c);
- if (enc->auth_key_id != DC->temp_auth_key_id && enc->auth_key_id != DC->auth_key_id) {
- vlogprintf (E_WARNING, "received msg from dc %d with auth_key_id %lld (perm_auth_key_id %lld temp_auth_key_id %lld). Dropping\n",
- DC->id, enc->auth_key_id, DC->auth_key_id, DC->temp_auth_key_id);
- return 0;
- }
- if (enc->auth_key_id == DC->temp_auth_key_id) {
- assert (enc->auth_key_id == DC->temp_auth_key_id);
- assert (DC->temp_auth_key_id);
- tgl_init_aes_auth (DC->temp_auth_key + 8, enc->msg_key, AES_DECRYPT);
- } else {
- assert (enc->auth_key_id == DC->auth_key_id);
- assert (DC->auth_key_id);
- tgl_init_aes_auth (DC->auth_key + 8, enc->msg_key, AES_DECRYPT);
- }
- int l = tgl_pad_aes_decrypt ((char *)&enc->server_salt, len - UNENCSZ, (char *)&enc->server_salt, len - UNENCSZ);
- assert (l == len - UNENCSZ);
- //assert (enc->auth_key_id2 == enc->auth_key_id);
- assert (!(enc->msg_len & 3) && enc->msg_len > 0 && enc->msg_len <= len - MINSZ && len - MINSZ - enc->msg_len <= 12);
- static unsigned char sha1_buffer[20];
- sha1 ((void *)&enc->server_salt, enc->msg_len + (MINSZ - UNENCSZ), sha1_buffer);
- assert (!memcmp (&enc->msg_key, sha1_buffer + 4, 16));
- //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 ();
- }
-
-
- int this_server_time = enc->msg_id >> 32LL;
- if (!DC->server_time_delta) {
- DC->server_time_delta = this_server_time - get_utime (CLOCK_REALTIME);
- DC->server_time_udelta = this_server_time - get_utime (CLOCK_MONOTONIC);
- }
- double st = get_server_time (DC);
- if (this_server_time < st - 300 || this_server_time > st + 30) {
- vlogprintf (E_WARNING, "salt = %lld, session_id = %lld, msg_id = %lld, seq_no = %d, st = %lf, now = %lf\n", enc->server_salt, enc->session_id, enc->msg_id, enc->seq_no, st, get_utime (CLOCK_REALTIME));
- return 0;
- }
-
-
- assert (this_server_time >= st - 300 && this_server_time <= st + 30);
- //assert (enc->msg_id > server_last_msg_id && (enc->msg_id & 3) == 1);
- vlogprintf (E_DEBUG, "received mesage id %016llx\n", enc->msg_id);
- server_last_msg_id = enc->msg_id;
-
- //*(long long *)(longpoll_query + 3) = *(long long *)((char *)(&enc->msg_id) + 0x3c);
- //*(long long *)(longpoll_query + 5) = *(long long *)((char *)(&enc->msg_id) + 0x3c);
-
- assert (l >= (MINSZ - UNENCSZ) + 8);
- //assert (enc->message[0] == CODE_rpc_result && *(long long *)(enc->message + 1) == client_last_msg_id);
- ++good_messages;
-
- in_ptr = enc->message;
- in_end = in_ptr + (enc->msg_len / 4);
-
- /*{
- assert (len <= 10000);
- static char s[1 << 20];
- int p = 0;
- int i;
- //static int buf[10000];
- //assert (TLS->net_methods->read_in_lookup (c, buf, len) == len);
-
- for (i = 0; i < in_end - in_ptr; i++) {
- p += sprintf (s + p, "%08x ", *(int *)(in_ptr + i));
- }
- vlogprintf (E_DEBUG, "%s\n", s);
- }*/
-
- struct tgl_session *S = TLS->net_methods->get_session (c);
- if (enc->msg_id & 1) {
- tgln_insert_msg_id (TLS, S, enc->msg_id);
- }
- assert (S->session_id == enc->session_id);
- rpc_execute_answer (TLS, c, enc->msg_id);
- assert (in_ptr == in_end);
- return 0;
-}
-
-
-static int rpc_execute (struct tgl_state *TLS, struct connection *c, int op, int len) {
- struct tgl_dc *D = TLS->net_methods->get_dc (c);
- vlogprintf (E_DEBUG, "outbound rpc connection from dc #%d (%s:%d) : received rpc answer %d with %d content bytes\n", D->id, D->ip, D->port, op, len);
-
- /*{
- assert (len <= 10000);
- static char s[1 << 20];
- int p = 0;
- int i;
- static int buf[10000];
- assert (TLS->net_methods->read_in_lookup (c, buf, len) == len);
-
- for (i = 0; i < len / 4; i++) {
- p += sprintf (s + p, "%08x ", *(int *)(buf + i));
- }
- vlogprintf (E_DEBUG, "%s\n", s);
- }*/
- /* if (op < 0) {
- assert (TLS->net_methods->read_in (c, Response, Response_len) == Response_len);
- return 0;
- }*/
-
- if (len >= MAX_RESPONSE_SIZE/* - 12*/ || len < 0/*12*/) {
- vlogprintf (E_WARNING, "answer too long (%d bytes), skipping\n", len);
- return 0;
- }
-
- int Response_len = len;
-
- static char Response[MAX_RESPONSE_SIZE];
- vlogprintf (E_DEBUG, "Response_len = %d\n", Response_len);
- assert (TLS->net_methods->read_in (c, Response, Response_len) == Response_len);
- Response[Response_len] = 0;
-
-#if !defined(__MACH__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined (__CYGWIN__)
-// setsockopt (c->fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){0}, 4);
-#endif
- int o = D->state;
- //if (D->flags & 1) { o = st_authorized;}
- switch (o) {
- case st_reqpq_sent:
- process_respq_answer (TLS, c, Response/* + 8*/, Response_len/* - 12*/, 0);
- return 0;
- case st_reqdh_sent:
- process_dh_answer (TLS, c, Response/* + 8*/, Response_len/* - 12*/, 0);
- return 0;
- case st_client_dh_sent:
- process_auth_complete (TLS, c, Response/* + 8*/, Response_len/* - 12*/, 0);
- return 0;
- case st_reqpq_sent_temp:
- process_respq_answer (TLS, c, Response/* + 8*/, Response_len/* - 12*/, 1);
- return 0;
- case st_reqdh_sent_temp:
- process_dh_answer (TLS, c, Response/* + 8*/, Response_len/* - 12*/, 1);
- return 0;
- case st_client_dh_sent_temp:
- process_auth_complete (TLS, c, Response/* + 8*/, Response_len/* - 12*/, 1);
- return 0;
- case st_authorized:
- if (op < 0 && op >= -999) {
- vlogprintf (E_WARNING, "Server error %d\n", op);
- } else {
- process_rpc_message (TLS, c, (void *)(Response/* + 8*/), Response_len/* - 12*/);
- }
- return 0;
- default:
- vlogprintf (E_ERROR, "fatal: cannot receive answer in state %d\n", D->state);
- exit (2);
- }
-
- return 0;
-}
-
-
-static int tc_close (struct tgl_state *TLS, struct connection *c, int who) {
- vlogprintf (E_DEBUG, "outbound rpc connection from dc #%d : closing by %d\n", TLS->net_methods->get_dc(c)->id, who);
- return 0;
-}
-
-static void mpc_on_get_config (struct tgl_state *TLS, void *extra, int success) {
- assert (success);
- struct tgl_dc *D = extra;
- D->flags |= 4;
-}
-
-static int tc_becomes_ready (struct tgl_state *TLS, struct connection *c) {
- vlogprintf (E_DEBUG, "outbound rpc connection from dc #%d becomed ready\n", TLS->net_methods->get_dc(c)->id);
- //char byte = 0xef;
- //assert (TLS->net_methods->write_out (c, &byte, 1) == 1);
- //TLS->net_methods->flush_out (c);
-
- struct tgl_dc *D = TLS->net_methods->get_dc (c);
- if (D->flags & 1) { D->state = st_authorized; }
- int o = D->state;
- if (o == st_authorized && !TLS->enable_pfs) {
- D->temp_auth_key_id = D->auth_key_id;
- memcpy (D->temp_auth_key, D->auth_key, 256);
- D->flags |= 2;
- }
- switch (o) {
- case st_init:
- send_req_pq_packet (TLS, c);
- break;
- case st_authorized:
- if (!(D->flags & 2)) {
- assert (!D->temp_auth_key_id);
- create_temp_auth_key (TLS, c);
- } else if (!(D->flags & 4)) {
- tgl_do_help_get_config_dc (TLS, D, mpc_on_get_config, D);
- }
- break;
- default:
- vlogprintf (E_DEBUG, "c_state = %d\n", D->state);
- assert (0);
- }
- return 0;
-}
-
-static int rpc_becomes_ready (struct tgl_state *TLS, struct connection *c) {
- return tc_becomes_ready (TLS, c);
-}
-
-static int rpc_close (struct tgl_state *TLS, struct connection *c) {
- return tc_close (TLS, c, 0);
-}
-
-
-#define RANDSEED_PASSWORD_FILENAME NULL
-#define RANDSEED_PASSWORD_LENGTH 0
-void tglmp_on_start (struct tgl_state *TLS) {
- tgl_prng_seed (TLS, RANDSEED_PASSWORD_FILENAME, RANDSEED_PASSWORD_LENGTH);
-
- int i;
- int ok = 0;
- for (i = 0; i < TLS->rsa_key_num; i++) {
- char *key = TLS->rsa_key_list[i];
- if (rsa_load_public_key (TLS, key) < 0) {
- vlogprintf (E_WARNING, "Can not load key %s\n", key);
- } else {
- ok = 1;
- break;
- }
- }
-
- if (!ok) {
- vlogprintf (E_ERROR, "No public keys found\n");
- exit (1);
- }
-
- pk_fingerprint = tgl_do_compute_rsa_key_fingerprint (TLS->pubKey);
-}
-
-void tgl_dc_authorize (struct tgl_state *TLS, struct tgl_dc *DC) {
- //c_state = 0;
- if (!DC->sessions[0]) {
- tglmp_dc_create_session (TLS, DC);
- }
- vlogprintf (E_DEBUG, "Starting authorization for DC #%d: %s:%d\n", DC->id, DC->ip, DC->port);
- //net_loop (0, auth_ok);
-}
-
-#define long_cmp(a,b) ((a) > (b) ? 1 : (a) == (b) ? 0 : -1)
-DEFINE_TREE(long,long long,long_cmp,0)
-
-static int send_all_acks (struct tgl_state *TLS, struct tgl_session *S) {
- clear_packet ();
- out_int (CODE_msgs_ack);
- out_int (CODE_vector);
- out_int (tree_count_long (S->ack_tree));
- while (S->ack_tree) {
- long long x = tree_get_min_long (S->ack_tree);
- out_long (x);
- S->ack_tree = tree_delete_long (S->ack_tree, x);
- }
- tglmp_encrypt_send_message (TLS, S->c, packet_buffer, packet_ptr - packet_buffer, 0);
- return 0;
-}
-
-static void send_all_acks_gateway (struct tgl_state *TLS, void *arg) {
- send_all_acks (TLS, arg);
-}
-
-
-void tgln_insert_msg_id (struct tgl_state *TLS, struct tgl_session *S, long long id) {
- if (!S->ack_tree) {
- TLS->timer_methods->insert (S->ev, ACK_TIMEOUT);
- }
- if (!tree_lookup_long (S->ack_tree, id)) {
- S->ack_tree = tree_insert_long (S->ack_tree, id, lrand48 ());
- }
-}
-
-//extern struct tgl_dc *DC_list[];
-
-
-static void regen_temp_key_gw (struct tgl_state *TLS, void *arg) {
- tglmp_regenerate_temp_auth_key (TLS, arg);
-}
-
-struct tgl_dc *tglmp_alloc_dc (struct tgl_state *TLS, int id, char *ip, int port UU) {
- //assert (!TLS->DC_list[id]);
- if (!TLS->DC_list[id]) {
- struct tgl_dc *DC = talloc0 (sizeof (*DC));
- DC->id = id;
- DC->ip = ip;
- DC->port = port;
- TLS->DC_list[id] = DC;
- if (id > TLS->max_dc_num) {
- TLS->max_dc_num = id;
- }
- DC->ev = TLS->timer_methods->alloc (TLS, regen_temp_key_gw, DC);
- TLS->timer_methods->insert (DC->ev, 0);
- return DC;
- } else {
- struct tgl_dc *DC = TLS->DC_list[id];
- tfree_str (DC->ip);
- DC->ip = tstrdup (ip);
- return DC;
- }
-}
-
-static struct mtproto_methods mtproto_methods = {
- .execute = rpc_execute,
- .ready = rpc_becomes_ready,
- .close = rpc_close
-};
-
-void tglmp_dc_create_session (struct tgl_state *TLS, struct tgl_dc *DC) {
- struct tgl_session *S = talloc0 (sizeof (*S));
- assert (RAND_pseudo_bytes ((unsigned char *) &S->session_id, 8) >= 0);
- S->dc = DC;
- S->c = TLS->net_methods->create_connection (TLS, DC->ip, DC->port, S, DC, &mtproto_methods);
- if (!S->c) {
- vlogprintf (E_DEBUG, "Can not create connection to DC. Is network down?\n");
- exit (1);
- }
- S->ev = TLS->timer_methods->alloc (TLS, send_all_acks_gateway, S);
- assert (!DC->sessions[0]);
- DC->sessions[0] = S;
-}
-
-void tgl_do_send_ping (struct tgl_state *TLS, struct connection *c) {
- int x[3];
- x[0] = CODE_ping;
- *(long long *)(x + 1) = lrand48 () * (1ll << 32) + lrand48 ();
- tglmp_encrypt_send_message (TLS, c, x, 3, 0);
-}
-
-void tgl_dc_iterator (struct tgl_state *TLS, void (*iterator)(struct tgl_dc *DC)) {
- int i;
- for (i = 0; i <= TLS->max_dc_num; i++) {
- iterator (TLS->DC_list[i]);
- }
-}
-
-void tgl_dc_iterator_ex (struct tgl_state *TLS, void (*iterator)(struct tgl_dc *DC, void *extra), void *extra) {
- int i;
- for (i = 0; i <= TLS->max_dc_num; i++) {
- iterator (TLS->DC_list[i], extra);
- }
-}
-
-
-void tglmp_regenerate_temp_auth_key (struct tgl_state *TLS, struct tgl_dc *D) {
- D->flags &= ~6;
- D->temp_auth_key_id = 0;
- memset (D->temp_auth_key, 0, 256);
-
- if (!D->sessions[0]) {
- tgl_dc_authorize (TLS, D);
- return;
- }
-
-
- struct tgl_session *S = D->sessions[0];
- tglt_secure_random (&S->session_id, 8);
- S->seq_no = 0;
-
- TLS->timer_methods->delete (S->ev);
- S->ack_tree = tree_clear_long (S->ack_tree);
-
- if (D->state != st_authorized) {
- return;
- }
-
- if (S->c) {
- create_temp_auth_key (TLS, S->c);
- }
-}
-
-void tgls_free_session (struct tgl_state *TLS, struct tgl_session *S) {
- S->ack_tree = tree_clear_long (S->ack_tree);
- if (S->ev) { TLS->timer_methods->free (S->ev); }
- if (S->c) {
- TLS->net_methods->free (S->c);
- }
- tfree (S, sizeof (*S));
-}
-
-void tgls_free_dc (struct tgl_state *TLS, struct tgl_dc *DC) {
- if (DC->ip) { tfree_str (DC->ip); }
-
- struct tgl_session *S = DC->sessions[0];
- if (S) { tgls_free_session (TLS, S); }
-
- if (DC->ev) { TLS->timer_methods->free (DC->ev); }
- tfree (DC, sizeof (*DC));
-}
-
-void tgls_free_pubkey (struct tgl_state *TLS) {
- RSA_free (TLS->pubKey);
-}
diff --git a/mtproto-client.h b/mtproto-client.h
deleted file mode 100644
index 692a4b8..0000000
--- a/mtproto-client.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- This file is part of tgl-library
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library 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
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
- Copyright Nikolay Durov, Andrey Lopatin 2012-2013
- Vitaly Valtman 2013-2014
-*/
-#ifndef __MTPROTO_CLIENT_H__
-#define __MTPROTO_CLIENT_H__
-//#include "net.h"
-#include
-//void on_start (void);
-//..long long encrypt_send_message (struct connection *c, int *msg, int msg_ints, int useful);
-//void dc_authorize (struct tgl_dc *DC);
-//void work_update (struct connection *c, long long msg_id);
-//void work_update_binlog (void);
-//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);
-
-#include "tgl.h"
-
-struct connection;
-struct tgl_dc;
-//#include "queries.h"
-#define TG_APP_HASH "36722c72256a24c1225de00eb6a1ca74"
-#define TG_APP_ID 2899
-
-#define ACK_TIMEOUT 1
-#define MAX_DC_ID 10
-
-struct connection;
-
-long long tglmp_encrypt_send_message (struct tgl_state *TLS, struct connection *c, int *msg, int msg_ints, int flags);
-void tglmp_dc_create_session (struct tgl_state *TLS, struct tgl_dc *DC);
-int tglmp_check_g (struct tgl_state *TLS, unsigned char p[256], BIGNUM *g);
-int tglmp_check_DH_params (struct tgl_state *TLS, BIGNUM *p, int g);
-struct tgl_dc *tglmp_alloc_dc (struct tgl_state *TLS, int id, char *ip, int port);
-void tglmp_regenerate_temp_auth_key (struct tgl_state *TLS, struct tgl_dc *D);
-
-void tgln_insert_msg_id (struct tgl_state *TLS, struct tgl_session *S, long long id);
-void tglmp_on_start (struct tgl_state *TLS);
-void tgl_dc_authorize (struct tgl_state *TLS, struct tgl_dc *DC);
-void tgls_free_dc (struct tgl_state *TLS, struct tgl_dc *DC);
-void tgls_free_pubkey (struct tgl_state *TLS);
-#endif
diff --git a/mtproto-common.c b/mtproto-common.c
deleted file mode 100644
index dd8caaf..0000000
--- a/mtproto-common.c
+++ /dev/null
@@ -1,394 +0,0 @@
-/*
- This file is part of tgl-library
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library 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
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
- Copyright Nikolay Durov, Andrey Lopatin 2012-2013
- Vitaly Valtman 2013-2014
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#define _FILE_OFFSET_BITS 64
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "mtproto-common.h"
-#include "include.h"
-#include "tools.h"
-
-#ifdef __MACH__
-#include
-#include
-#endif
-
-
-static int __packet_buffer[PACKET_BUFFER_SIZE + 16];
-int *tgl_packet_ptr;
-int *tgl_packet_buffer = __packet_buffer + 16;
-
-static long long rsa_encrypted_chunks, rsa_decrypted_chunks;
-
-//int verbosity;
-
-static int get_random_bytes (struct tgl_state *TLS, unsigned char *buf, int n) {
- int r = 0, h = open ("/dev/random", O_RDONLY | O_NONBLOCK);
- if (h >= 0) {
- r = read (h, buf, n);
- if (r > 0) {
- vlogprintf (E_DEBUG, "added %d bytes of real entropy to secure random numbers seed\n", r);
- } else {
- r = 0;
- }
- close (h);
- }
-
- if (r < n) {
- h = open ("/dev/urandom", O_RDONLY);
- if (h < 0) {
- return r;
- }
- int s = read (h, buf + r, n - r);
- close (h);
- if (s > 0) {
- r += s;
- }
- }
-
- if (r >= (int) sizeof (long)) {
- *(long *)buf ^= lrand48 ();
- srand48 (*(long *)buf);
- }
-
- return r;
-}
-
-
-/* RDTSC */
-#if defined(__i386__)
-#define HAVE_RDTSC
-static __inline__ unsigned long long rdtsc (void) {
- unsigned long long int x;
- __asm__ volatile ("rdtsc" : "=A" (x));
- return x;
-}
-#elif defined(__x86_64__)
-#define HAVE_RDTSC
-static __inline__ unsigned long long rdtsc (void) {
- unsigned hi, lo;
- __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
- return ((unsigned long long) lo) | (((unsigned long long) hi) << 32);
-}
-#endif
-
-void tgl_prng_seed (struct tgl_state *TLS, const char *password_filename, int password_length) {
- struct timespec T;
- tgl_my_clock_gettime (CLOCK_REALTIME, &T);
- RAND_add (&T, sizeof (T), 4.0);
-#ifdef HAVE_RDTSC
- unsigned long long r = rdtsc ();
- RAND_add (&r, 8, 4.0);
-#endif
- unsigned short p = getpid ();
- RAND_add (&p, sizeof (p), 0.0);
- p = getppid ();
- RAND_add (&p, sizeof (p), 0.0);
- unsigned char rb[32];
- int s = get_random_bytes (TLS, rb, 32);
- if (s > 0) {
- RAND_add (rb, s, s);
- }
- memset (rb, 0, sizeof (rb));
- if (password_filename && password_length > 0) {
- int fd = open (password_filename, O_RDONLY);
- if (fd < 0) {
- vlogprintf (E_WARNING, "Warning: fail to open password file - \"%s\", %m.\n", password_filename);
- } else {
- unsigned char *a = talloc0 (password_length);
- int l = read (fd, a, password_length);
- if (l < 0) {
- vlogprintf (E_WARNING, "Warning: fail to read password file - \"%s\", %m.\n", password_filename);
- } else {
- vlogprintf (E_DEBUG, "read %d bytes from password file.\n", l);
- RAND_add (a, l, l);
- }
- close (fd);
- tfree_secure (a, password_length);
- }
- }
- TLS->BN_ctx = BN_CTX_new ();
- ensure_ptr (TLS->BN_ctx);
-}
-
-int tgl_serialize_bignum (BIGNUM *b, char *buffer, int maxlen) {
- int itslen = BN_num_bytes (b);
- int reqlen;
- if (itslen < 254) {
- reqlen = itslen + 1;
- } else {
- reqlen = itslen + 4;
- }
- int newlen = (reqlen + 3) & -4;
- int pad = newlen - reqlen;
- reqlen = newlen;
- if (reqlen > maxlen) {
- return -reqlen;
- }
- if (itslen < 254) {
- *buffer++ = itslen;
- } else {
- *(int *)buffer = (itslen << 8) + 0xfe;
- buffer += 4;
- }
- int l = BN_bn2bin (b, (unsigned char *)buffer);
- assert (l == itslen);
- buffer += l;
- while (pad --> 0) {
- *buffer++ = 0;
- }
- return reqlen;
-}
-
-
-long long tgl_do_compute_rsa_key_fingerprint (RSA *key) {
- static char tempbuff[4096];
- static unsigned char sha[20];
- assert (key->n && key->e);
- int l1 = tgl_serialize_bignum (key->n, tempbuff, 4096);
- assert (l1 > 0);
- int l2 = tgl_serialize_bignum (key->e, tempbuff + l1, 4096 - l1);
- assert (l2 > 0 && l1 + l2 <= 4096);
- SHA1 ((unsigned char *)tempbuff, l1 + l2, sha);
- return *(long long *)(sha + 12);
-}
-
-void tgl_out_cstring (const char *str, long len) {
- assert (len >= 0 && len < (1 << 24));
- assert ((char *) packet_ptr + len + 8 < (char *) (packet_buffer + PACKET_BUFFER_SIZE));
- char *dest = (char *) packet_ptr;
- if (len < 254) {
- *dest++ = len;
- } else {
- *packet_ptr = (len << 8) + 0xfe;
- dest += 4;
- }
- memcpy (dest, str, len);
- dest += len;
- while ((long) dest & 3) {
- *dest++ = 0;
- }
- packet_ptr = (int *) dest;
-}
-
-void tgl_out_cstring_careful (const char *str, long len) {
- assert (len >= 0 && len < (1 << 24));
- assert ((char *) packet_ptr + len + 8 < (char *) (packet_buffer + PACKET_BUFFER_SIZE));
- char *dest = (char *) packet_ptr;
- if (len < 254) {
- dest++;
- if (dest != str) {
- memmove (dest, str, len);
- }
- dest[-1] = len;
- } else {
- dest += 4;
- if (dest != str) {
- memmove (dest, str, len);
- }
- *packet_ptr = (len << 8) + 0xfe;
- }
- dest += len;
- while ((long) dest & 3) {
- *dest++ = 0;
- }
- packet_ptr = (int *) dest;
-}
-
-
-void tgl_out_data (const void *data, long len) {
- assert (len >= 0 && len < (1 << 24) && !(len & 3));
- assert ((char *) packet_ptr + len + 8 < (char *) (packet_buffer + PACKET_BUFFER_SIZE));
- memcpy (packet_ptr, data, len);
- packet_ptr += len >> 2;
-}
-
-int *tgl_in_ptr, *tgl_in_end;
-
-int tgl_fetch_bignum (BIGNUM *x) {
- int l = prefetch_strlen ();
- if (l < 0) {
- return l;
- }
- char *str = fetch_str (l);
- assert (BN_bin2bn ((unsigned char *) str, l, x) == x);
- return l;
-}
-
-int tgl_pad_rsa_encrypt (struct tgl_state *TLS, char *from, int from_len, char *to, int size, BIGNUM *N, BIGNUM *E) {
- int pad = (255000 - from_len - 32) % 255 + 32;
- int chunks = (from_len + pad) / 255;
- int bits = BN_num_bits (N);
- assert (bits >= 2041 && bits <= 2048);
- assert (from_len > 0 && from_len <= 2550);
- assert (size >= chunks * 256);
- assert (RAND_pseudo_bytes ((unsigned char *) from + from_len, pad) >= 0);
- int i;
- BIGNUM x, y;
- BN_init (&x);
- BN_init (&y);
- rsa_encrypted_chunks += chunks;
- for (i = 0; i < chunks; i++) {
- BN_bin2bn ((unsigned char *) from, 255, &x);
- assert (BN_mod_exp (&y, &x, E, N, TLS->BN_ctx) == 1);
- unsigned l = 256 - BN_num_bytes (&y);
- assert (l <= 256);
- memset (to, 0, l);
- BN_bn2bin (&y, (unsigned char *) to + l);
- to += 256;
- }
- BN_free (&x);
- BN_free (&y);
- return chunks * 256;
-}
-
-int tgl_pad_rsa_decrypt (struct tgl_state *TLS, char *from, int from_len, char *to, int size, BIGNUM *N, BIGNUM *D) {
- if (from_len < 0 || from_len > 0x1000 || (from_len & 0xff)) {
- return -1;
- }
- int chunks = (from_len >> 8);
- int bits = BN_num_bits (N);
- assert (bits >= 2041 && bits <= 2048);
- assert (size >= chunks * 255);
- int i;
- BIGNUM x, y;
- BN_init (&x);
- BN_init (&y);
- for (i = 0; i < chunks; i++) {
- ++rsa_decrypted_chunks;
- BN_bin2bn ((unsigned char *) from, 256, &x);
- assert (BN_mod_exp (&y, &x, D, N, TLS->BN_ctx) == 1);
- int l = BN_num_bytes (&y);
- if (l > 255) {
- BN_free (&x);
- BN_free (&y);
- return -1;
- }
- assert (l >= 0 && l <= 255);
- memset (to, 0, 255 - l);
- BN_bn2bin (&y, (unsigned char *) to + 255 - l);
- to += 255;
- }
- BN_free (&x);
- BN_free (&y);
- return chunks * 255;
-}
-
-static unsigned char aes_key_raw[32], aes_iv[32];
-static AES_KEY aes_key;
-
-void tgl_init_aes_unauth (const char server_nonce[16], const char hidden_client_nonce[32], int encrypt) {
- static unsigned char buffer[64], hash[20];
- memcpy (buffer, hidden_client_nonce, 32);
- memcpy (buffer + 32, server_nonce, 16);
- SHA1 (buffer, 48, aes_key_raw);
- memcpy (buffer + 32, hidden_client_nonce, 32);
- SHA1 (buffer, 64, aes_iv + 8);
- memcpy (buffer, server_nonce, 16);
- memcpy (buffer + 16, hidden_client_nonce, 32);
- SHA1 (buffer, 48, hash);
- memcpy (aes_key_raw + 20, hash, 12);
- memcpy (aes_iv, hash + 12, 8);
- memcpy (aes_iv + 28, hidden_client_nonce, 4);
- if (encrypt == AES_ENCRYPT) {
- AES_set_encrypt_key (aes_key_raw, 32*8, &aes_key);
- } else {
- AES_set_decrypt_key (aes_key_raw, 32*8, &aes_key);
- }
- memset (aes_key_raw, 0, sizeof (aes_key_raw));
-}
-
-void tgl_init_aes_auth (char auth_key[192], char msg_key[16], int encrypt) {
- static unsigned char buffer[48], hash[20];
- // sha1_a = SHA1 (msg_key + substr (auth_key, 0, 32));
- // sha1_b = SHA1 (substr (auth_key, 32, 16) + msg_key + substr (auth_key, 48, 16));
- // sha1_с = SHA1 (substr (auth_key, 64, 32) + msg_key);
- // sha1_d = SHA1 (msg_key + substr (auth_key, 96, 32));
- // aes_key = substr (sha1_a, 0, 8) + substr (sha1_b, 8, 12) + substr (sha1_c, 4, 12);
- // aes_iv = substr (sha1_a, 8, 12) + substr (sha1_b, 0, 8) + substr (sha1_c, 16, 4) + substr (sha1_d, 0, 8);
- memcpy (buffer, msg_key, 16);
- memcpy (buffer + 16, auth_key, 32);
- SHA1 (buffer, 48, hash);
- memcpy (aes_key_raw, hash, 8);
- memcpy (aes_iv, hash + 8, 12);
-
- memcpy (buffer, auth_key + 32, 16);
- memcpy (buffer + 16, msg_key, 16);
- memcpy (buffer + 32, auth_key + 48, 16);
- SHA1 (buffer, 48, hash);
- memcpy (aes_key_raw + 8, hash + 8, 12);
- memcpy (aes_iv + 12, hash, 8);
-
- memcpy (buffer, auth_key + 64, 32);
- memcpy (buffer + 32, msg_key, 16);
- SHA1 (buffer, 48, hash);
- memcpy (aes_key_raw + 20, hash + 4, 12);
- memcpy (aes_iv + 20, hash + 16, 4);
-
- memcpy (buffer, msg_key, 16);
- memcpy (buffer + 16, auth_key + 96, 32);
- SHA1 (buffer, 48, hash);
- memcpy (aes_iv + 24, hash, 8);
-
- if (encrypt == AES_ENCRYPT) {
- AES_set_encrypt_key (aes_key_raw, 32*8, &aes_key);
- } else {
- AES_set_decrypt_key (aes_key_raw, 32*8, &aes_key);
- }
- memset (aes_key_raw, 0, sizeof (aes_key_raw));
-}
-
-int tgl_pad_aes_encrypt (char *from, int from_len, char *to, int size) {
- int padded_size = (from_len + 15) & -16;
- assert (from_len > 0 && padded_size <= size);
- if (from_len < padded_size) {
- assert (RAND_pseudo_bytes ((unsigned char *) from + from_len, padded_size - from_len) >= 0);
- }
- AES_ige_encrypt ((unsigned char *) from, (unsigned char *) to, padded_size, &aes_key, aes_iv, AES_ENCRYPT);
- return padded_size;
-}
-
-int tgl_pad_aes_decrypt (char *from, int from_len, char *to, int size) {
- if (from_len <= 0 || from_len > size || (from_len & 15)) {
- return -1;
- }
- AES_ige_encrypt ((unsigned char *) from, (unsigned char *) to, from_len, &aes_key, aes_iv, AES_DECRYPT);
- return from_len;
-}
-
-
diff --git a/mtproto-common.h b/mtproto-common.h
deleted file mode 100644
index a1d1ce5..0000000
--- a/mtproto-common.h
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- This file is part of tgl-library
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library 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
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
- Copyright Nikolay Durov, Andrey Lopatin 2012-2013
- Vitaly Valtman 2013-2014
-*/
-#ifndef __MTPROTO_COMMON_H__
-#define __MTPROTO_COMMON_H__
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-//#include "interface.h"
-#include "tools.h"
-#include "auto/constants.h"
-
-#include "tgl.h"
-#include "tgl-inner.h"
-/* DH key exchange protocol data structures */
-#define CODE_req_pq 0x60469778
-#define CODE_resPQ 0x05162463
-#define CODE_req_DH_params 0xd712e4be
-#define CODE_p_q_inner_data 0x83c95aec
-#define CODE_p_q_inner_data_temp 0x3c6a84d4
-#define CODE_server_DH_inner_data 0xb5890dba
-#define CODE_server_DH_params_fail 0x79cb045d
-#define CODE_server_DH_params_ok 0xd0e8075c
-#define CODE_set_client_DH_params 0xf5045f1f
-#define CODE_client_DH_inner_data 0x6643b654
-#define CODE_dh_gen_ok 0x3bcbf734
-#define CODE_dh_gen_retry 0x46dc1fb9
-#define CODE_dh_gen_fail 0xa69dae02
-
-#define CODE_bind_auth_key_inner 0x75a3f765
-
-/* service messages */
-#define CODE_rpc_result 0xf35c6d01
-#define CODE_rpc_error 0x2144ca19
-#define CODE_msg_container 0x73f1f8dc
-#define CODE_msg_copy 0xe06046b2
-#define CODE_msgs_ack 0x62d6b459
-#define CODE_bad_msg_notification 0xa7eff811
-#define CODE_bad_server_salt 0xedab447b
-#define CODE_msgs_state_req 0xda69fb52
-#define CODE_msgs_state_info 0x04deb57d
-#define CODE_msgs_all_info 0x8cc0d131
-#define CODE_new_session_created 0x9ec20908
-#define CODE_msg_resend_req 0x7d861a08
-#define CODE_ping 0x7abe77ec
-#define CODE_pong 0x347773c5
-#define CODE_destroy_session 0xe7512126
-#define CODE_destroy_session_ok 0xe22045fc
-#define CODE_destroy_session_none 0x62d350c9
-#define CODE_destroy_sessions 0x9a6face8
-#define CODE_destroy_sessions_res 0xa8164668
-#define CODE_get_future_salts 0xb921bd04
-#define CODE_future_salt 0x0949d9dc
-#define CODE_future_salts 0xae500895
-#define CODE_rpc_drop_answer 0x58e4a740
-#define CODE_rpc_answer_unknown 0x5e2ad36e
-#define CODE_rpc_answer_dropped_running 0xcd78e586
-#define CODE_rpc_answer_dropped 0xa43ad8b7
-#define CODE_msg_detailed_info 0x276d3ec6
-#define CODE_msg_new_detailed_info 0x809db6df
-#define CODE_ping_delay_disconnect 0xf3427b8c
-#define CODE_gzip_packed 0x3072cfa1
-
-#define CODE_input_peer_notify_settings_old 0x3cf4b1be
-#define CODE_peer_notify_settings_old 0xddbcd4a5
-#define CODE_user_profile_photo_old 0x990d1493
-#define CODE_config_old 0x232d5905
-
-#define CODE_msg_new_detailed_info 0x809db6df
-
-#define CODE_msg_detailed_info 0x276d3ec6
-/* not really a limit, for struct encrypted_message only */
-// #define MAX_MESSAGE_INTS 16384
-#define MAX_MESSAGE_INTS 1048576
-#define MAX_PROTO_MESSAGE_INTS 1048576
-
-#define PACKET_BUFFER_SIZE (16384 * 100 + 16) // temp fix
-#pragma pack(push,4)
-struct encrypted_message {
- // unencrypted header
- long long auth_key_id;
- char msg_key[16];
- // encrypted part, starts with encrypted header
- long long server_salt;
- long long session_id;
- // long long auth_key_id2; // removed
- // first message follows
- long long msg_id;
- int seq_no;
- int msg_len; // divisible by 4
- int message[MAX_MESSAGE_INTS];
-};
-
-#pragma pack(pop)
-
-//BN_CTX *BN_ctx;
-
-void tgl_prng_seed (struct tgl_state *TLS, const char *password_filename, int password_length);
-int tgl_serialize_bignum (BIGNUM *b, char *buffer, int maxlen);
-long long tgl_do_compute_rsa_key_fingerprint (RSA *key);
-
-#define packet_buffer tgl_packet_buffer
-#define packet_ptr tgl_packet_ptr
-
-extern int *tgl_packet_buffer;
-extern int *tgl_packet_ptr;
-
-static inline void out_ints (const int *what, int len) {
- assert (packet_ptr + len <= packet_buffer + PACKET_BUFFER_SIZE);
- memcpy (packet_ptr, what, len * 4);
- packet_ptr += len;
-}
-
-
-static inline void out_int (int x) {
- assert (packet_ptr + 1 <= packet_buffer + PACKET_BUFFER_SIZE);
- *packet_ptr++ = x;
-}
-
-
-static inline void out_long (long long x) {
- assert (packet_ptr + 2 <= packet_buffer + PACKET_BUFFER_SIZE);
- *(long long *)packet_ptr = x;
- packet_ptr += 2;
-}
-
-static inline void out_double (double x) {
- assert (packet_ptr + 2 <= packet_buffer + PACKET_BUFFER_SIZE);
- *(double *)packet_ptr = x;
- packet_ptr += 2;
-}
-
-static inline void clear_packet (void) {
- packet_ptr = packet_buffer;
-}
-
-void tgl_out_cstring (const char *str, long len);
-void tgl_out_cstring_careful (const char *str, long len);
-void tgl_out_data (const void *data, long len);
-
-#define out_cstring tgl_out_cstring
-#define out_cstring_careful tgl_out_cstring_careful
-#define out_data tgl_out_data
-
-static inline void out_string (const char *str) {
- out_cstring (str, strlen (str));
-}
-
-static inline void out_bignum (BIGNUM *n) {
- int l = tgl_serialize_bignum (n, (char *)packet_ptr, (PACKET_BUFFER_SIZE - (packet_ptr - packet_buffer)) * 4);
- assert (l > 0);
- packet_ptr += l >> 2;
-}
-
-#define in_ptr tgl_in_ptr
-#define in_end tgl_in_end
-extern int *tgl_in_ptr, *tgl_in_end;
-
-
-//void fetch_pts (void);
-//void fetch_qts (void);
-//void fetch_date (void);
-//void fetch_seq (void);
-static inline int prefetch_strlen (void) {
- if (in_ptr >= in_end) {
- return -1;
- }
- unsigned l = *in_ptr;
- if ((l & 0xff) < 0xfe) {
- l &= 0xff;
- return (in_end >= in_ptr + (l >> 2) + 1) ? (int)l : -1;
- } else if ((l & 0xff) == 0xfe) {
- l >>= 8;
- return (l >= 254 && in_end >= in_ptr + ((l + 7) >> 2)) ? (int)l : -1;
- } else {
- return -1;
- }
-}
-
-static inline char *fetch_str (int len) {
- assert (len >= 0);
- if (len < 254) {
- char *str = (char *) in_ptr + 1;
- in_ptr += 1 + (len >> 2);
- return str;
- } else {
- char *str = (char *) in_ptr + 4;
- in_ptr += (len + 7) >> 2;
- return str;
- }
-}
-
-static inline char *fetch_str_dup (void) {
- int l = prefetch_strlen ();
- assert (l >= 0);
- int i;
- char *s = fetch_str (l);
- for (i = 0; i < l; i++) {
- if (!s[i]) { break; }
- }
- char *r = talloc (i + 1);
- memcpy (r, s, i);
- r[i] = 0;
- return r;
-}
-
-static inline int fetch_update_str (char **s) {
- if (!*s) {
- *s = fetch_str_dup ();
- return 1;
- }
- int l = prefetch_strlen ();
- char *r = fetch_str (l);
- if (memcmp (*s, r, l) || (*s)[l]) {
- tfree_str (*s);
- *s = talloc (l + 1);
- memcpy (*s, r, l);
- (*s)[l] = 0;
- return 1;
- }
- return 0;
-}
-
-static inline int fetch_update_int (int *value) {
- if (*value == *in_ptr) {
- in_ptr ++;
- return 0;
- } else {
- *value = *(in_ptr ++);
- return 1;
- }
-}
-
-static inline int fetch_update_long (long long *value) {
- if (*value == *(long long *)in_ptr) {
- in_ptr += 2;
- return 0;
- } else {
- *value = *(long long *)(in_ptr);
- in_ptr += 2;
- return 1;
- }
-}
-
-static inline int set_update_int (int *value, int new_value) {
- if (*value == new_value) {
- return 0;
- } else {
- *value = new_value;
- return 1;
- }
-}
-
-static inline void fetch_skip (int n) {
- in_ptr += n;
- assert (in_ptr <= in_end);
-}
-
-static inline void fetch_skip_str (void) {
- int l = prefetch_strlen ();
- assert (l >= 0);
- fetch_str (l);
-}
-
-static inline long have_prefetch_ints (void) {
- return in_end - in_ptr;
-}
-
-int tgl_fetch_bignum (BIGNUM *x);
-#define fetch_bignum tgl_fetch_bignum
-
-static inline int fetch_int (void) {
- assert (in_ptr + 1 <= in_end);
- return *(in_ptr ++);
-}
-
-static inline int fetch_bool (void) {
- assert (in_ptr + 1 <= in_end);
- assert (*(in_ptr) == (int)CODE_bool_true || *(in_ptr) == (int)CODE_bool_false);
- return *(in_ptr ++) == (int)CODE_bool_true;
-}
-
-static inline int prefetch_int (void) {
- assert (in_ptr < in_end);
- return *(in_ptr);
-}
-
-static inline void prefetch_data (void *data, int size) {
- assert (in_ptr + (size >> 2) <= in_end);
- memcpy (data, in_ptr, size);
-}
-
-static inline void fetch_data (void *data, int size) {
- assert (in_ptr + (size >> 2) <= in_end);
- memcpy (data, in_ptr, size);
- assert (!(size & 3));
- in_ptr += (size >> 2);
-}
-
-static inline long long fetch_long (void) {
- assert (in_ptr + 2 <= in_end);
- long long r = *(long long *)in_ptr;
- in_ptr += 2;
- return r;
-}
-
-static inline double fetch_double (void) {
- assert (in_ptr + 2 <= in_end);
- double r = *(double *)in_ptr;
- in_ptr += 2;
- return r;
-}
-
-static inline void fetch_ints (void *data, int count) {
- assert (in_ptr + count <= in_end);
- memcpy (data, in_ptr, 4 * count);
- in_ptr += count;
-}
-
-static inline void fetch256 (void *buf) {
- int l = prefetch_strlen ();
- assert (l >= 0);
- char *s = fetch_str (l);
- if (l < 256) {
- memcpy (buf + 256 - l, s, l);
- } else {
- memcpy (buf, s + (l - 256), 256);
- }
-}
-
-static inline int in_remaining (void) {
- return 4 * (in_end - in_ptr);
-}
-
-//int get_random_bytes (unsigned char *buf, int n);
-
-int tgl_pad_rsa_encrypt (struct tgl_state *TLS, char *from, int from_len, char *to, int size, BIGNUM *N, BIGNUM *E);
-int tgl_pad_rsa_decrypt (struct tgl_state *TLS, char *from, int from_len, char *to, int size, BIGNUM *N, BIGNUM *D);
-
-//extern long long rsa_encrypted_chunks, rsa_decrypted_chunks;
-
-//extern unsigned char aes_key_raw[32], aes_iv[32];
-//extern AES_KEY aes_key;
-
-void tgl_init_aes_unauth (const char server_nonce[16], const char hidden_client_nonce[32], int encrypt);
-void tgl_init_aes_auth (char auth_key[192], char msg_key[16], int encrypt);
-int tgl_pad_aes_encrypt (char *from, int from_len, char *to, int size);
-int tgl_pad_aes_decrypt (char *from, int from_len, char *to, int size);
-/*
-static inline void hexdump_in (void) {
- hexdump (in_ptr, in_end);
-}
-
-static inline void hexdump_out (void) {
- hexdump (packet_buffer, packet_ptr);
-}*/
-
-#ifdef __MACH__
-#define CLOCK_REALTIME 0
-#define CLOCK_MONOTONIC 1
-#endif
-#endif
diff --git a/net.c b/net.c
deleted file mode 100644
index 8f48e80..0000000
--- a/net.c
+++ /dev/null
@@ -1,623 +0,0 @@
-/*
- This file is part of tgl-library
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library 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
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
- Copyright Vitaly Valtman 2013-2014
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#define _GNU_SOURCE
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#ifdef EVENT_V2
-#include
-#else
-#include
-#include "event-old.h"
-#endif
-#include
-#include
-
-#include "net.h"
-#include "include.h"
-#include "tgl.h"
-#include "tgl-inner.h"
-//#include "mtproto-client.h"
-//#include "mtproto-common.h"
-#include "tree.h"
-#include "tools.h"
-
-#ifndef POLLRDHUP
-#define POLLRDHUP 0
-#endif
-
-//double get_utime (int clock_id);
-
-//extern struct mtproto_methods auth_methods;
-
-static void fail_connection (struct connection *c);
-
-#define PING_TIMEOUT 10
-
-static void start_ping_timer (struct connection *c);
-static void ping_alarm (evutil_socket_t fd, short what, void *arg) {
- struct connection *c = arg;
- struct tgl_state *TLS = c->TLS;
- vlogprintf (E_DEBUG + 2,"ping alarm\n");
- assert (c->state == conn_ready || c->state == conn_connecting);
- if (tglt_get_double_time () - c->last_receive_time > 6 * PING_TIMEOUT) {
- vlogprintf (E_WARNING, "fail connection: reason: ping timeout\n");
- c->state = conn_failed;
- fail_connection (c);
- } else if (tglt_get_double_time () - c->last_receive_time > 3 * PING_TIMEOUT && c->state == conn_ready) {
- tgl_do_send_ping (c->TLS, c);
- start_ping_timer (c);
- } else {
- start_ping_timer (c);
- }
-}
-
-static void stop_ping_timer (struct connection *c) {
- event_del (c->ping_ev);
-}
-
-static void start_ping_timer (struct connection *c) {
- static struct timeval ptimeout = { PING_TIMEOUT, 0};
- event_add (c->ping_ev, &ptimeout);
-}
-
-static void restart_connection (struct connection *c);
-
-static void fail_alarm (evutil_socket_t fd, short what, void *arg) {
- struct connection *c = arg;
- c->in_fail_timer = 0;
- restart_connection (c);
-}
-
-static void start_fail_timer (struct connection *c) {
- if (c->in_fail_timer) { return; }
- c->in_fail_timer = 1;
-
- static struct timeval ptimeout = { 10, 0};
- event_add (c->fail_ev, &ptimeout);
-}
-
-static struct connection_buffer *new_connection_buffer (int size) {
- struct connection_buffer *b = talloc0 (sizeof (*b));
- b->start = talloc (size);
- b->end = b->start + size;
- b->rptr = b->wptr = b->start;
- return b;
-}
-
-static void delete_connection_buffer (struct connection_buffer *b) {
- tfree (b->start, b->end - b->start);
- tfree (b, sizeof (*b));
-}
-
-int tgln_write_out (struct connection *c, const void *_data, int len) {
- struct tgl_state *TLS = c->TLS;
- vlogprintf (E_DEBUG, "write_out: %d bytes\n", len);
- const unsigned char *data = _data;
- if (!len) { return 0; }
- assert (len > 0);
- int x = 0;
- if (!c->out_bytes) {
- event_add (c->write_ev, 0);
- }
- if (!c->out_head) {
- struct connection_buffer *b = new_connection_buffer (1 << 20);
- c->out_head = c->out_tail = b;
- }
- while (len) {
- if (c->out_tail->end - c->out_tail->wptr >= len) {
- memcpy (c->out_tail->wptr, data, len);
- c->out_tail->wptr += len;
- c->out_bytes += len;
- return x + len;
- } else {
- int y = c->out_tail->end - c->out_tail->wptr;
- assert (y < len);
- memcpy (c->out_tail->wptr, data, y);
- x += y;
- len -= y;
- data += y;
- struct connection_buffer *b = new_connection_buffer (1 << 20);
- c->out_tail->next = b;
- b->next = 0;
- c->out_tail = b;
- c->out_bytes += y;
- }
- }
- return x;
-}
-
-int tgln_read_in (struct connection *c, void *_data, int len) {
- unsigned char *data = _data;
- if (!len) { return 0; }
- assert (len > 0);
- if (len > c->in_bytes) {
- len = c->in_bytes;
- }
- int x = 0;
- while (len) {
- int y = c->in_head->wptr - c->in_head->rptr;
- if (y > len) {
- memcpy (data, c->in_head->rptr, len);
- c->in_head->rptr += len;
- c->in_bytes -= len;
- return x + len;
- } else {
- memcpy (data, c->in_head->rptr, y);
- c->in_bytes -= y;
- x += y;
- data += y;
- len -= y;
- void *old = c->in_head;
- c->in_head = c->in_head->next;
- if (!c->in_head) {
- c->in_tail = 0;
- }
- delete_connection_buffer (old);
- }
- }
- return x;
-}
-
-int tgln_read_in_lookup (struct connection *c, void *_data, int len) {
- unsigned char *data = _data;
- if (!len || !c->in_bytes) { return 0; }
- assert (len > 0);
- if (len > c->in_bytes) {
- len = c->in_bytes;
- }
- int x = 0;
- struct connection_buffer *b = c->in_head;
- while (len) {
- int y = b->wptr - b->rptr;
- if (y >= len) {
- memcpy (data, b->rptr, len);
- return x + len;
- } else {
- memcpy (data, b->rptr, y);
- x += y;
- data += y;
- len -= y;
- b = b->next;
- }
- }
- return x;
-}
-
-void tgln_flush_out (struct connection *c UU) {
-}
-
-#define MAX_CONNECTIONS 100
-static struct connection *Connections[MAX_CONNECTIONS];
-static int max_connection_fd;
-
-static void rotate_port (struct connection *c) {
- switch (c->port) {
- case 443:
- c->port = 80;
- break;
- case 80:
- c->port = 25;
- break;
- case 25:
- c->port = 443;
- break;
- }
-}
-
-static void try_read (struct connection *c);
-static void try_write (struct connection *c);
-
-static void conn_try_read (evutil_socket_t fd, short what, void *arg) {
- struct connection *c = arg;
- struct tgl_state *TLS = c->TLS;
- vlogprintf (E_DEBUG + 1, "Try read. Fd = %d\n", c->fd);
- try_read (c);
-}
-static void conn_try_write (evutil_socket_t fd, short what, void *arg) {
- struct connection *c = arg;
- struct tgl_state *TLS = c->TLS;
- if (c->state == conn_connecting) {
- c->state = conn_ready;
- c->methods->ready (TLS, c);
- }
- try_write (c);
- if (c->out_bytes) {
- event_add (c->write_ev, 0);
- }
-}
-
-struct connection *tgln_create_connection (struct tgl_state *TLS, const char *host, int port, struct tgl_session *session, struct tgl_dc *dc, struct mtproto_methods *methods) {
- struct connection *c = talloc0 (sizeof (*c));
- c->TLS = TLS;
- int fd = socket (AF_INET, SOCK_STREAM, 0);
- if (fd == -1) {
- vlogprintf (E_ERROR, "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) {
- //vlogprintf (E_ERROR, "Can not connect to %s:%d %m\n", host, port);
- if (errno != EINPROGRESS) {
- vlogprintf (E_ERROR, "Can not connect to %s:%d %m\n", host, port);
- close (fd);
- tfree (c, sizeof (*c));
- return 0;
- }
- }
-
- c->fd = fd;
- c->state = conn_connecting;
- c->last_receive_time = tglt_get_double_time ();
- c->ip = tstrdup (host);
- c->flags = 0;
- c->port = port;
- assert (!Connections[fd]);
- Connections[fd] = c;
-
- c->ping_ev = evtimer_new (TLS->ev_base, ping_alarm, c);
- c->fail_ev = evtimer_new (TLS->ev_base, fail_alarm, c);
- c->write_ev = event_new (TLS->ev_base, c->fd, EV_WRITE, conn_try_write, c);
-
- struct timeval tv = {5, 0};
- c->read_ev = event_new (TLS->ev_base, c->fd, EV_READ | EV_PERSIST, conn_try_read, c);
- event_add (c->read_ev, &tv);
-
- start_ping_timer (c);
-
- c->dc = dc;
- c->session = session;
- c->methods = methods;
-
- char byte = 0xef;
- assert (tgln_write_out (c, &byte, 1) == 1);
- tgln_flush_out (c);
-
- return c;
-}
-
-static void restart_connection (struct connection *c) {
- struct tgl_state *TLS = c->TLS;
- if (c->last_connect_time == time (0)) {
- start_fail_timer (c);
- return;
- }
-
- c->last_connect_time = time (0);
- int fd = socket (AF_INET, SOCK_STREAM, 0);
- if (fd == -1) {
- vlogprintf (E_ERROR, "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 (c->port);
- if (strcmp (c->ip, c->dc->ip)) {
- tfree_str (c->ip);
- c->ip = tstrdup (c->dc->ip);
- }
- addr.sin_addr.s_addr = inet_addr (c->ip);
-
-
- fcntl (fd, F_SETFL, O_NONBLOCK);
-
- if (connect (fd, (struct sockaddr *) &addr, sizeof (addr)) == -1) {
- if (errno != EINPROGRESS) {
- vlogprintf (E_WARNING, "Can not connect to %s:%d %m\n", c->ip, c->port);
- start_fail_timer (c);
- close (fd);
- return;
- }
- }
-
- c->fd = fd;
- c->state = conn_connecting;
- c->last_receive_time = tglt_get_double_time ();
- start_ping_timer (c);
- Connections[fd] = c;
-
- c->write_ev = event_new (TLS->ev_base, c->fd, EV_WRITE, conn_try_write, c);
-
- struct timeval tv = {5, 0};
- c->read_ev = event_new (TLS->ev_base, c->fd, EV_READ | EV_PERSIST, conn_try_read, c);
- event_add (c->read_ev, &tv);
-
- char byte = 0xef;
- assert (tgln_write_out (c, &byte, 1) == 1);
- tgln_flush_out (c);
-}
-
-static void fail_connection (struct connection *c) {
- struct tgl_state *TLS = c->TLS;
- if (c->state == conn_ready || c->state == conn_connecting) {
- stop_ping_timer (c);
- }
- event_free (c->write_ev);
- event_free (c->read_ev);
-
- rotate_port (c);
- struct connection_buffer *b = c->out_head;
- while (b) {
- struct connection_buffer *d = b;
- b = b->next;
- delete_connection_buffer (d);
- }
- b = c->in_head;
- while (b) {
- struct connection_buffer *d = b;
- b = b->next;
- delete_connection_buffer (d);
- }
- c->out_head = c->out_tail = c->in_head = c->in_tail = 0;
- c->state = conn_failed;
- c->out_bytes = c->in_bytes = 0;
- close (c->fd);
- Connections[c->fd] = 0;
- vlogprintf (E_NOTICE, "Lost connection to server... %s:%d\n", c->ip, c->port);
- restart_connection (c);
-}
-
-//extern FILE *log_net_f;
-static void try_write (struct connection *c) {
- struct tgl_state *TLS = c->TLS;
- vlogprintf (E_DEBUG, "try write: fd = %d\n", c->fd);
- int x = 0;
- while (c->out_head) {
- int r = write (c->fd, c->out_head->rptr, c->out_head->wptr - c->out_head->rptr);
- if (r >= 0) {
- x += r;
- c->out_head->rptr += r;
- if (c->out_head->rptr != c->out_head->wptr) {
- break;
- }
- struct connection_buffer *b = c->out_head;
- c->out_head = b->next;
- if (!c->out_head) {
- c->out_tail = 0;
- }
- delete_connection_buffer (b);
- } else {
- if (errno != EAGAIN && errno != EWOULDBLOCK) {
- vlogprintf (E_NOTICE, "fail_connection: write_error %m\n");
- fail_connection (c);
- return;
- } else {
- break;
- }
- }
- }
- vlogprintf (E_DEBUG, "Sent %d bytes to %d\n", x, c->fd);
- c->out_bytes -= x;
-}
-
-static void try_rpc_read (struct connection *c) {
- assert (c->in_head);
- struct tgl_state *TLS = c->TLS;
-
- while (1) {
- if (c->in_bytes < 1) { return; }
- unsigned len = 0;
- unsigned t = 0;
- assert (tgln_read_in_lookup (c, &len, 1) == 1);
- if (len >= 1 && len <= 0x7e) {
- if (c->in_bytes < (int)(1 + 4 * len)) { return; }
- } else {
- if (c->in_bytes < 4) { return; }
- assert (tgln_read_in_lookup (c, &len, 4) == 4);
- len = (len >> 8);
- if (c->in_bytes < (int)(4 + 4 * len)) { return; }
- len = 0x7f;
- }
-
- if (len >= 1 && len <= 0x7e) {
- assert (tgln_read_in (c, &t, 1) == 1);
- assert (t == len);
- assert (len >= 1);
- } else {
- assert (len == 0x7f);
- assert (tgln_read_in (c, &len, 4) == 4);
- len = (len >> 8);
- assert (len >= 1);
- }
- len *= 4;
- int op;
- assert (tgln_read_in_lookup (c, &op, 4) == 4);
- c->methods->execute (TLS, c, op, len);
- }
-}
-
-static void try_read (struct connection *c) {
- struct tgl_state *TLS = c->TLS;
- vlogprintf (E_DEBUG, "try read: fd = %d\n", c->fd);
- if (!c->in_tail) {
- c->in_head = c->in_tail = new_connection_buffer (1 << 20);
- }
- #ifdef EVENT_V1
- struct timeval tv = {5, 0};
- event_add (c->read_ev, &tv);
- #endif
- int x = 0;
- while (1) {
- int r = read (c->fd, c->in_tail->wptr, c->in_tail->end - c->in_tail->wptr);
- if (r > 0) {
- c->last_receive_time = tglt_get_double_time ();
- stop_ping_timer (c);
- start_ping_timer (c);
- }
- if (r >= 0) {
- c->in_tail->wptr += r;
- x += r;
- if (c->in_tail->wptr != c->in_tail->end) {
- break;
- }
- struct connection_buffer *b = new_connection_buffer (1 << 20);
- c->in_tail->next = b;
- c->in_tail = b;
- } else {
- if (errno != EAGAIN && errno != EWOULDBLOCK) {
- vlogprintf (E_NOTICE, "fail_connection: read_error %m\n");
- fail_connection (c);
- return;
- } else {
- break;
- }
- }
- }
- vlogprintf (E_DEBUG, "Received %d bytes from %d\n", x, c->fd);
- c->in_bytes += x;
- if (x) {
- try_rpc_read (c);
- }
-}
-/*
-int tgl_connections_make_poll_array (struct pollfd *fds, int max) {
- int _max = max;
- int i;
- for (i = 0; i <= max_connection_fd; i++) {
- if (Connections[i] && Connections[i]->state == conn_failed) {
- restart_connection (Connections[i]);
- }
- if (Connections[i] && Connections[i]->state != conn_failed) {
- assert (max > 0);
- struct connection *c = Connections[i];
- fds[0].fd = c->fd;
- fds[0].events = POLLERR | POLLHUP | POLLRDHUP | POLLIN;
- if (c->out_bytes || c->state == conn_connecting) {
- fds[0].events |= POLLOUT;
- }
- fds ++;
- max --;
- }
- }
- return _max - max;
-}
-
-void tgl_connections_poll_result (struct pollfd *fds, int max) {
- int i;
- for (i = 0; i < max; i++) {
- struct connection *c = Connections[fds[i].fd];
- if (fds[i].revents & POLLIN) {
- try_read (c);
- }
- if (fds[i].revents & (POLLHUP | POLLERR | POLLRDHUP)) {
- vlogprintf (E_NOTICE, "fail_connection: events_mask=0x%08x\n", fds[i].revents);
- fail_connection (c);
- } else if (fds[i].revents & POLLOUT) {
- if (c->state == conn_connecting) {
- vlogprintf (E_DEBUG, "connection ready\n");
- c->state = conn_ready;
- c->last_receive_time = tglt_get_double_time ();
- }
- if (c->out_bytes) {
- try_write (c);
- }
- }
- }
-}*/
-
-static void incr_out_packet_num (struct connection *c) {
- c->out_packet_num ++;
-}
-
-static struct tgl_dc *get_dc (struct connection *c) {
- return c->dc;
-}
-
-static struct tgl_session *get_session (struct connection *c) {
- return c->session;
-}
-
-static void tgln_free (struct connection *c) {
- if (c->ip) { tfree_str (c->ip); }
- struct connection_buffer *b = c->out_head;
- while (b) {
- struct connection_buffer *d = b;
- b = b->next;
- delete_connection_buffer (d);
- }
- b = c->in_head;
- while (b) {
- struct connection_buffer *d = b;
- b = b->next;
- delete_connection_buffer (d);
- }
-
- if (c->ping_ev) { event_free (c->ping_ev); }
- if (c->fail_ev) { event_free (c->fail_ev); }
- if (c->read_ev) { event_free (c->read_ev); }
- if (c->write_ev) { event_free (c->write_ev); }
-
- if (c->fd >= 0) { close (c->fd); }
- tfree (c, sizeof (*c));
-}
-
-struct tgl_net_methods tgl_conn_methods = {
- .write_out = tgln_write_out,
- .read_in = tgln_read_in,
- .read_in_lookup = tgln_read_in_lookup,
- .flush_out = tgln_flush_out,
- .incr_out_packet_num = incr_out_packet_num,
- .get_dc = get_dc,
- .get_session = get_session,
- .create_connection = tgln_create_connection,
- .free = tgln_free
-};
diff --git a/net.h b/net.h
deleted file mode 100644
index 00d7da2..0000000
--- a/net.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- This file is part of tgl-library
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library 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
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
- Copyright Vitaly Valtman 2013-2014
-*/
-#ifndef __NET_H__
-#define __NET_H__
-
-struct connection_buffer {
- unsigned char *start;
- unsigned char *end;
- unsigned char *rptr;
- unsigned char *wptr;
- struct connection_buffer *next;
-};
-
-enum conn_state {
- conn_none,
- conn_connecting,
- conn_ready,
- conn_failed,
- conn_stopped
-};
-
-struct connection {
- int fd;
- char *ip;
- int port;
- int flags;
- enum conn_state state;
- int ipv6[4];
- struct connection_buffer *in_head;
- struct connection_buffer *in_tail;
- struct connection_buffer *out_head;
- struct connection_buffer *out_tail;
- int in_bytes;
- int out_bytes;
- int packet_num;
- int out_packet_num;
- int last_connect_time;
- int in_fail_timer;
- struct mtproto_methods *methods;
- struct tgl_state *TLS;
- struct tgl_session *session;
- struct tgl_dc *dc;
- void *extra;
- struct event *ping_ev;
- struct event *fail_ev;
- struct event *read_ev;
- struct event *write_ev;
- double last_receive_time;
-};
-
-//extern struct connection *Connections[];
-
-int tgln_write_out (struct connection *c, const void *data, int len);
-void tgln_flush_out (struct connection *c);
-int tgln_read_in (struct connection *c, void *data, int len);
-int tgln_read_in_lookup (struct connection *c, void *data, int len);
-
-//void tgln_insert_msg_id (struct tgl_session *S, long long id);
-
-extern struct tgl_net_methods tgl_conn_methods;
-
-//void create_all_outbound_connections (void);
-
-//struct connection *create_connection (const char *host, int port, struct tgl_session *session, struct connection_methods *methods);
-//struct tgl_dc *tgln_alloc_dc (int id, char *ip, int port);
-//void tgln_dc_create_session (struct tgl_dc *DC, struct mtproto_methods *methods);
-struct connection *tgln_create_connection (struct tgl_state *TLS, const char *host, int port, struct tgl_session *session, struct tgl_dc *dc, struct mtproto_methods *methods);
-
-#define GET_DC(c) (c->session->dc)
-#endif
diff --git a/no-preview.h b/no-preview.h
deleted file mode 100644
index 50d1274..0000000
--- a/no-preview.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- This file is part of tgl-library
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library 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
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
- Copyright Vitaly Valtman 2013-2014
-*/
-
-// Just sample jpg file 90x90
-
-int thumb_file_size = (82 * 6 - 2) * 4;
-int thumb_file [] = {
-0xe0ffd8ff, 0x464a1000, 0x01004649, 0x64000101, 0x00006400, 0xa002e2ff,
-0x5f434349, 0x464f5250, 0x00454c49, 0x00000101, 0x636c9002, 0x3004736d,
-0x6e6d0000, 0x47527274, 0x59582042, 0xdd07205a, 0x04000b00, 0x1b001600,
-0x63612400, 0x50417073, 0x00004c50, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x0100d6f6, 0x00000000, 0x636c2dd3,
-0x0000736d, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
-0x65640b00, 0x00006373, 0x00000801, 0x70633800, 0x00007472, 0x00004001,
-0x74774e00, 0x00007470, 0x00009001, 0x68631400, 0x00006461, 0x0000a401,
-0x58722c00, 0x00005a59, 0x0000d001, 0x58621400, 0x00005a59, 0x0000e401,
-0x58671400, 0x00005a59, 0x0000f801, 0x54721400, 0x00004352, 0x00000c02,
-0x54672000, 0x00004352, 0x00002c02, 0x54622000, 0x00004352, 0x00004c02,
-0x68632000, 0x00006d72, 0x00006c02, 0x6c6d2400, 0x00006375, 0x00000000,
-0x00000100, 0x6e650c00, 0x00005355, 0x00001c00, 0x73001c00, 0x47005200,
-0x20004200, 0x75006200, 0x6c006900, 0x2d007400, 0x6e006900, 0x6c6d0000,
-0x00006375, 0x00000000, 0x00000100, 0x6e650c00, 0x00005355, 0x00003200,
-0x4e001c00, 0x20006f00, 0x6f006300, 0x79007000, 0x69007200, 0x68006700,
-0x2c007400, 0x75002000, 0x65007300, 0x66002000, 0x65007200, 0x6c006500,
-0x00007900, 0x59580000, 0x0000205a, 0x00000000, 0x0100d6f6, 0x00000000,
-0x66732dd3, 0x00003233, 0x01000000, 0x00004a0c, 0xffffe305, 0x00002af3,
-0x00009b07, 0xffff87fd, 0xffffa2fb, 0x0000a3fd, 0x0000d803, 0x595894c0,
-0x0000205a, 0x00000000, 0x0000946f, 0x0000ee38, 0x59589003, 0x0000205a,
-0x00000000, 0x00009d24, 0x0000830f, 0x5958beb6, 0x0000205a, 0x00000000,
-0x0000a562, 0x000090b7, 0x6170de18, 0x00006172, 0x03000000, 0x02000000,
-0x00006666, 0x0000a7f2, 0x0000590d, 0x0000d013, 0x61705b0a, 0x00006172,
-0x03000000, 0x02000000, 0x00006666, 0x0000a7f2, 0x0000590d, 0x0000d013,
-0x61705b0a, 0x00006172, 0x03000000, 0x02000000, 0x00006666, 0x0000a7f2,
-0x0000590d, 0x0000d013, 0x68635b0a, 0x00006d72, 0x03000000, 0x00000000,
-0x0000d7a3, 0x00007b54, 0x0000cd4c, 0x00009a99, 0x00006626, 0xdbff5c0f,
-0x14004300, 0x0f120f0e, 0x1112140d, 0x14161712, 0x21331f18, 0x1f1c1c1f,
-0x252f2d3f, 0x4e414a33, 0x4841494d, 0x765c5246, 0x6f575264, 0x66484658,
-0x7a6f688c, 0x8485847d, 0x9b91634f, 0x769a808f, 0xff7f8481, 0x014300db,
-0x1f171716, 0x213c1f1b, 0x547f3c21, 0x7f7f5448, 0x7f7f7f7f, 0x7f7f7f7f,
-0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f,
-0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x1100c0ff, 0x005a0008,
-0x2201035a, 0x01110200, 0xff011103, 0x001900c4, 0x01010101, 0x00000101,
-0x00000000, 0x00000000, 0x02030400, 0xc4ff0605, 0x00103600, 0x02010401,
-0x06050304, 0x00000306, 0x01000000, 0x11030200, 0x05211204, 0x13514131,
-0x32146122, 0x23918171, 0x72423424, 0x432515a1, 0xa2827444, 0xc4fff0b3,
-0x01011400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x1400c4ff,
-0x00000111, 0x00000000, 0x00000000, 0x00000000, 0xdaff0000, 0x01030c00,
-0x03110200, 0x003f0011, 0x404434fb, 0xbcb4875c, 0x006b38b0, 0x03dcdb12,
-0xf4637f74, 0xe519f153, 0x09d7c5c7, 0x47d29160, 0x20692f18, 0xd06d786a,
-0x53f7f922, 0x17b3e260, 0x2fe8668c, 0x1786a473, 0x9775efbd, 0xe917e43a,
-0x1d0a1bb0, 0x114d0f82, 0x14651110, 0x35f299ed, 0xe9b09680, 0xf5a4fc2f,
-0xe975bd03, 0xb506737b, 0x04444440, 0x5c444044, 0x8e8dedbd, 0xc61adc7b,
-0x689c738b, 0x92a0dc01, 0x58e2b77f, 0x7bfb37d1, 0xb5b5e79d, 0xdbf968cc,
-0xead3f48d, 0x38ed1313, 0xdea77c86, 0xae089963, 0xc743435a, 0x403fe4ce,
-0x392ee1b9, 0xed39e718, 0xd6517e2d, 0x7fc4aa03, 0xb7ad7590, 0x77e7e6ab,
-0x34bf705d, 0x7c77ca53, 0x3dea1299, 0x7fb0bcf4, 0x241fadc5, 0x95a7a816,
-0x13fbe6f3, 0x3182b135, 0xd1b4b224, 0x1b0d48a2, 0xbf9d26d8, 0x82dc3640,
-0x63569a2a, 0xbbd224c3, 0xb9b4714c, 0x1680aec6, 0x3d311856, 0x9b59be91,
-0x09876ca6, 0x61d86564, 0x5a9f06d2, 0x36f51b0d, 0x8682e476, 0xacb1b131,
-0xd1584363, 0x00456b4d, 0x22d2053b, 0x22202202, 0xf3f30222, 0xe3e513e5,
-0xf1e6e1f0, 0x2380496e, 0x5fdcdb68, 0x549b3a27, 0x825e6a6c, 0x6522028b,
-0xaf91ccc8, 0x341cf26b, 0x58dbc4b5, 0xf2289add, 0x0854ddbd, 0x0b9247d5,
-0xf02b5c54, 0x3f917f92, 0xaf56affd, 0xe3760637, 0x05cebde0, 0xed4c76ce,
-0x3cef1b63, 0x7fd8aff8, 0xa0c902ea, 0x7e730d0a, 0x435834f3, 0x26edbb76,
-0xd3ec00fd, 0x76d48efa, 0xa8560f2d, 0x0e766331, 0xd319993c, 0x20243209,
-0x61b7e6c8, 0x998331d0, 0x640ee802, 0x47a3d493, 0xfab99413, 0x4fd871f1,
-0xe9443792, 0x627e051c, 0xd8f3051c, 0x2f28f558, 0x64b51745, 0x1b2bfee3,
-0xb8783953, 0x9900fff6, 0xd8176a65, 0x5a3bf56a, 0x1b331fdb, 0x64b3572f,
-0xd59a3643, 0xaf3abce1, 0x11dd20bd, 0x01111110, 0x5c141011, 0xb3e3083f,
-0xd9b19cc4, 0x17edb20e, 0xa78e9aa1, 0x4ef4de06, 0x00c0bfe7, 0x7e1e442d,
-0x9221fe38, 0xedb5c7dc, 0x6338078a, 0x62495b8d, 0xc11d9b8c, 0x49e81b16,
-0x51d02bea, 0x3eb86d70, 0xc8bc4f13, 0xa10ec758, 0xd40751c0, 0x5ac94710,
-0xc4c8b080, 0x95492b83, 0x975ee696, 0xb7bd96b4, 0x17379cce, 0x82e856e8,
-0xe4c2c82a, 0x398e935f, 0x632437ea, 0x7c9c87d2, 0xdc1ddb7c, 0x65a80a48,
-0x2309f164, 0x51fab475, 0x081dc11d, 0xda45573b, 0x6622f3f3, 0x48f1b214,
-0x676c4edb, 0x243468c7, 0x00ffde60, 0xf1630350, 0xa0076c1d, 0x8f2c0c8b,
-0x2383c26b, 0x361a8f4e, 0xaceea6c9, 0x01dd5a5d, 0x11111011, 0xc3780c04,
-0xbf093ee2, 0xc7972c0b, 0x00d99040, 0xc0c20eb7, 0x659d3bd4, 0x269ab85e,
-0x468e114f, 0x11ad4fdb, 0x83d083d8, 0x8c52f4bd, 0x3c9664bf, 0xa4f9c77c,
-0x22a68876, 0xadb18784, 0xf480be83, 0x885a00ea, 0x220e0a88, 0xc303e4f6,
-0xc866e058, 0xdddbd661, 0xdf395db1, 0xbad64343, 0xe6e65b03, 0x668e81c3,
-0xad619e98, 0xeeb94563, 0xd4d19a3c, 0x3316ce95, 0x9d65f1e1, 0x3bf324fe,
-0x0e468f53, 0xc386068c, 0xa89e24f7, 0xf0c7c73b, 0xb60e391f, 0x1b8827cb,
-0x58601954, 0xc54f90f9, 0x80886ec5, 0x88088888, 0x1b7bb980, 0xb4c71c23,
-0xe6148e39, 0xb12358b8, 0xbd08225d, 0x0ffef085, 0x72b4f025, 0x635ce389,
-0xb90277e4, 0x0d05e000, 0x9bf9dbb9, 0x8e749fbc, 0x7ee6abbf, 0x4ddbf4af,
-0x728df7f3, 0x10b59adf, 0xe3c38f49, 0xb23c638a, 0xdb3d9349, 0x66899a64,
-0x00004dd5, 0xf51b5adf, 0x2220a255, 0xd9ff0f22};
diff --git a/queries.c b/queries.c
deleted file mode 100644
index a80c104..0000000
--- a/queries.c
+++ /dev/null
@@ -1,3879 +0,0 @@
-/*
- This file is part of tgl-library
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library 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
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
- Copyright Vitaly Valtman 2013-2014
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#define _FILE_OFFSET_BITS 64
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-
-#include "include.h"
-#include "mtproto-client.h"
-#include "queries.h"
-#include "tree.h"
-#include "mtproto-common.h"
-//#include "telegram.h"
-#include "structures.h"
-//#include "interface.h"
-//#include "net.h"
-#include
-#include
-#include
-#include
-#include
-
-#include "no-preview.h"
-#include "binlog.h"
-#include "updates.h"
-#include "auto.h"
-#include "tgl.h"
-
-#define sha1 SHA1
-
-#ifndef PATH_MAX
-#define PATH_MAX 4096
-#endif
-
-//int want_dc_num;
-//char *get_downloads_directory (void);
-//extern int offline_mode;
-
-//long long cur_uploading_bytes;
-//long long cur_uploaded_bytes;
-//long long cur_downloading_bytes;
-//long long cur_downloaded_bytes;
-
-//extern int binlog_enabled;
-//extern int sync_from_start;
-
-//static int queries_num;
-
-static void out_peer_id (struct tgl_state *TLS, tgl_peer_id_t id);
-#define QUERY_TIMEOUT 6.0
-
-#define memcmp8(a,b) memcmp ((a), (b), 8)
-DEFINE_TREE (query, struct query *, memcmp8, 0) ;
-
-struct query *tglq_query_get (struct tgl_state *TLS, long long id) {
- return tree_lookup_query (TLS->queries_tree, (void *)&id);
-}
-
-static int alarm_query (struct tgl_state *TLS, struct query *q) {
- assert (q);
- vlogprintf (E_DEBUG - 1, "Alarm query %lld\n", q->msg_id);
-
- TLS->timer_methods->insert (q->ev, QUERY_TIMEOUT);
-
- if (q->session->session_id == q->session_id) {
- clear_packet ();
- out_int (CODE_msg_container);
- out_int (1);
- out_long (q->msg_id);
- out_int (q->seq_no);
- out_int (4 * q->data_len);
- out_ints (q->data, q->data_len);
-
- tglmp_encrypt_send_message (TLS, q->session->c, packet_buffer, packet_ptr - packet_buffer, q->flags & QUERY_FORCE_SEND);
- } else {
- q->flags &= ~QUERY_ACK_RECEIVED;
- if (tree_lookup_query (TLS->queries_tree, q)) {
- TLS->queries_tree = tree_delete_query (TLS->queries_tree, q);
- }
- q->msg_id = tglmp_encrypt_send_message (TLS, q->session->c, q->data, q->data_len, (q->flags & QUERY_FORCE_SEND) | 1);
- TLS->queries_tree = tree_insert_query (TLS->queries_tree, q, lrand48 ());
- q->session_id = q->session->session_id;
- if (!(q->session->dc->flags & 4) && !(q->flags & QUERY_FORCE_SEND)) {
- q->session_id = 0;
- }
- }
- return 0;
-}
-
-void tglq_query_restart (struct tgl_state *TLS, long long id) {
- struct query *q = tglq_query_get (TLS, id);
- if (q) {
- TLS->timer_methods->delete (q->ev);
- alarm_query (TLS, q);
- }
-}
-
-static void alarm_query_gateway (struct tgl_state *TLS, void *arg) {
- alarm_query (TLS, arg);
-}
-
-
-struct query *tglq_send_query_ex (struct tgl_state *TLS, struct tgl_dc *DC, int ints, void *data, struct query_methods *methods, void *extra, void *callback, void *callback_extra, int flags) {
- assert (DC);
- assert (DC->auth_key_id);
- if (!DC->sessions[0]) {
- tglmp_dc_create_session (TLS, DC);
- }
- vlogprintf (E_DEBUG, "Sending query of size %d to DC (%s:%d)\n", 4 * ints, DC->ip, DC->port);
- struct query *q = talloc0 (sizeof (*q));
- q->data_len = ints;
- q->data = talloc (4 * ints);
- memcpy (q->data, data, 4 * ints);
- q->msg_id = tglmp_encrypt_send_message (TLS, DC->sessions[0]->c, data, ints, 1 | (flags & QUERY_FORCE_SEND));
- q->session = DC->sessions[0];
- q->seq_no = q->session->seq_no - 1;
- q->session_id = q->session->session_id;
- if (!(DC->flags & 4) && !(flags & QUERY_FORCE_SEND)) {
- q->session_id = 0;
- }
- vlogprintf (E_DEBUG, "Msg_id is %lld %p\n", q->msg_id, q);
- q->methods = methods;
- q->type = methods->type;
- q->DC = DC;
- q->flags = flags & QUERY_FORCE_SEND;
- if (TLS->queries_tree) {
- vlogprintf (E_DEBUG + 2, "%lld %lld\n", q->msg_id, TLS->queries_tree->x->msg_id);
- }
- TLS->queries_tree = tree_insert_query (TLS->queries_tree, q, lrand48 ());
-
- q->ev = TLS->timer_methods->alloc (TLS, alarm_query_gateway, q);
- TLS->timer_methods->insert (q->ev, QUERY_TIMEOUT);
-
- q->extra = extra;
- q->callback = callback;
- q->callback_extra = callback_extra;
- TLS->active_queries ++;
- return q;
-}
-
-struct query *tglq_send_query (struct tgl_state *TLS, struct tgl_dc *DC, int ints, void *data, struct query_methods *methods, void *extra, void *callback, void *callback_extra) {
- return tglq_send_query_ex (TLS, DC, ints, data, methods, extra, callback, callback_extra, 0);
-}
-
-static int fail_on_error (struct tgl_state *TLS, struct query *q UU, int error_code UU, int l UU, char *error UU) {
- fprintf (stderr, "error #%d: %.*s\n", error_code, l, error);
- assert (0);
- return 0;
-}
-
-void tglq_query_ack (struct tgl_state *TLS, long long id) {
- struct query *q = tglq_query_get (TLS, id);
- if (q && !(q->flags & QUERY_ACK_RECEIVED)) {
- assert (q->msg_id == id);
- q->flags |= QUERY_ACK_RECEIVED;
- TLS->timer_methods->delete (q->ev);
- }
-}
-
-void tglq_query_error (struct tgl_state *TLS, long long id) {
- assert (fetch_int () == CODE_rpc_error);
- int error_code = fetch_int ();
- int error_len = prefetch_strlen ();
- char *error = fetch_str (error_len);
- vlogprintf (E_WARNING, "error for query #%lld: #%d :%.*s\n", id, error_code, error_len, error);
- struct query *q = tglq_query_get (TLS, id);
- if (!q) {
- vlogprintf (E_WARNING, "No such query\n");
- } else {
- if (!(q->flags & QUERY_ACK_RECEIVED)) {
- TLS->timer_methods->delete (q->ev);
- }
- TLS->queries_tree = tree_delete_query (TLS->queries_tree, q);
- int res = 0;
- if (q->methods && q->methods->on_error && error_code != 500) {
- res = q->methods->on_error (TLS, q, error_code, error_len, error);
- } else {
- if (error_code == 420 || error_code == 500) {
- int wait;
- if (error_code == 420) {
- if (strncmp (error, "FLOOD_WAIT_", 11)) {
- vlogprintf (E_ERROR, "error = '%s'\n", error);
- wait = 10;
- } else {
- wait = atoll (error + 11);
- }
- } else {
- wait = 10;
- }
- q->flags &= ~QUERY_ACK_RECEIVED;
- TLS->timer_methods->insert (q->ev, wait);
- q->session_id = 0;
- res = 1;
- }
- }
- if (res <= 0) {
- tfree (q->data, q->data_len * 4);
- TLS->timer_methods->free (q->ev);
- }
- }
- TLS->active_queries --;
-}
-
-#define MAX_PACKED_SIZE (1 << 24)
-static int packed_buffer[MAX_PACKED_SIZE / 4];
-
-void tglq_query_result (struct tgl_state *TLS, long long id UU) {
- vlogprintf (E_DEBUG, "result for query #%lld. Size %ld bytes\n", id, (long)4 * (in_end - in_ptr));
- /*if (verbosity >= 4) {
- logprintf ( "result: ");
- hexdump_in ();
- }*/
- int op = prefetch_int ();
- int *end = 0;
- int *eend = 0;
- if (op == CODE_gzip_packed) {
- fetch_int ();
- int l = prefetch_strlen ();
- char *s = fetch_str (l);
- int total_out = tgl_inflate (s, l, packed_buffer, MAX_PACKED_SIZE);
- vlogprintf (E_DEBUG, "inflated %d bytes\n", total_out);
- end = in_ptr;
- eend = in_end;
- //assert (total_out % 4 == 0);
- in_ptr = packed_buffer;
- in_end = in_ptr + total_out / 4;
- /*if (verbosity >= 4) {
- logprintf ( "Unzipped data: ");
- hexdump_in ();
- }*/
- }
- struct query *q = tglq_query_get (TLS, id);
- if (!q) {
- //if (verbosity) {
- // logprintf ( "No such query\n");
- //}
- vlogprintf (E_WARNING, "No such query\n");
- in_ptr = in_end;
- } else {
- if (!(q->flags & QUERY_ACK_RECEIVED)) {
- TLS->timer_methods->delete (q->ev);
- }
- TLS->queries_tree = tree_delete_query (TLS->queries_tree, q);
- if (q->methods && q->methods->on_answer) {
- if (q->type) {
- int *save = in_ptr;
- vlogprintf (E_DEBUG, "in_ptr = %p, end_ptr = %p\n", in_ptr, in_end);
- if (skip_type_any (q->type) < 0) {
- vlogprintf (E_ERROR, "Skipped %ld int out of %ld (type %s)\n", (long)(in_ptr - save), (long)(in_end - save), q->type->type->id);
- assert (0);
- }
-
- assert (in_ptr == in_end);
- in_ptr = save;
- }
- q->methods->on_answer (TLS, q);
- assert (in_ptr == in_end);
- }
- tfree (q->data, 4 * q->data_len);
- TLS->timer_methods->free (q->ev);
- tfree (q, sizeof (*q));
-
- }
- if (end) {
- in_ptr = end;
- in_end = eend;
- }
- TLS->active_queries --;
-}
-
-
-//int max_chat_size;
-//int max_bcast_size;
-//int want_dc_num;
-//int new_dc_num;
-//extern struct tgl_dc *DC_list[];
-//extern struct tgl_dc *TLS->DC_working;
-
-static void out_random (int n) {
- assert (n <= 32);
- static char buf[32];
- tglt_secure_random (buf, n);
- out_cstring (buf, n);
-}
-
-int allow_send_linux_version;
-void tgl_do_insert_header (void) {
- out_int (CODE_invoke_with_layer18);
- //out_int (0x50858a19);
- out_int (CODE_init_connection);
- out_int (TG_APP_ID);
- if (allow_send_linux_version) {
- struct utsname st;
- uname (&st);
- out_string (st.machine);
- static char buf[4096];
- tsnprintf (buf, sizeof (buf), "%.999s %.999s %.999s\n", st.sysname, st.release, st.version);
- out_string (buf);
- out_string (TGL_VERSION " (build " TGL_BUILD ")");
- out_string ("En");
- } else {
- out_string ("x86");
- out_string ("Linux");
- out_string (TGL_VERSION);
- out_string ("en");
- }
-}
-
-/* {{{ Get config */
-
-static void fetch_dc_option (struct tgl_state *TLS) {
- assert (fetch_int () == CODE_dc_option);
- int id = fetch_int ();
- int l1 = prefetch_strlen ();
- char *name = fetch_str (l1);
- int l2 = prefetch_strlen ();
- char *ip = fetch_str (l2);
- int port = fetch_int ();
-
- bl_do_dc_option (TLS, id, l1, name, l2, ip, port);
-}
-
-static int help_get_config_on_answer (struct tgl_state *TLS, struct query *q UU) {
- unsigned op = fetch_int ();
- assert (op == CODE_config || op == CODE_config_old);
- fetch_int ();
-
- unsigned test_mode = fetch_int ();
- assert (test_mode == CODE_bool_true || test_mode == CODE_bool_false);
- assert (test_mode == CODE_bool_false || test_mode == CODE_bool_true);
- int this_dc = fetch_int ();
- vlogprintf (E_DEBUG, "this_dc = %d\n", this_dc);
- assert (fetch_int () == CODE_vector);
- int n = fetch_int ();
- assert (n <= 10);
- int i;
- for (i = 0; i < n; i++) {
- fetch_dc_option (TLS);
- }
- int max_chat_size = fetch_int ();
- int max_bcast_size = 0;
- if (op == CODE_config) {
- max_bcast_size = fetch_int ();
- }
- vlogprintf (E_DEBUG, "chat_size = %d, bcast_size = %d\n", max_chat_size, max_bcast_size);
-
- if (q->callback) {
- ((void (*)(struct tgl_state *,void *, int))(q->callback))(TLS, q->callback_extra, 1);
- }
- return 0;
-}
-
-static struct query_methods help_get_config_methods = {
- .on_answer = help_get_config_on_answer,
- .type = TYPE_TO_PARAM(config)
-};
-
-void tgl_do_help_get_config (struct tgl_state *TLS, void (*callback)(struct tgl_state *,void *, int), void *callback_extra) {
- clear_packet ();
- tgl_do_insert_header ();
- out_int (CODE_help_get_config);
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &help_get_config_methods, 0, callback, callback_extra);
-}
-
-void tgl_do_help_get_config_dc (struct tgl_state *TLS, struct tgl_dc *D, void (*callback)(struct tgl_state *, void *, int), void *callback_extra) {
- clear_packet ();
- tgl_do_insert_header ();
- out_int (CODE_help_get_config);
- tglq_send_query_ex (TLS, D, packet_ptr - packet_buffer, packet_buffer, &help_get_config_methods, 0, callback, callback_extra, 2);
-}
-/* }}} */
-
-/* {{{ Send code */
-static int send_code_on_answer (struct tgl_state *TLS, struct query *q UU) {
- static char *phone_code_hash;
- assert (fetch_int () == (int)CODE_auth_sent_code);
- int registered = fetch_bool ();
- int l = prefetch_strlen ();
- char *s = fetch_str (l);
- if (phone_code_hash) {
- tfree_str (phone_code_hash);
- }
- phone_code_hash = tstrndup (s, l);
- fetch_int ();
- fetch_bool ();
- tfree_str (q->extra);
-
- if (q->callback) {
- ((void (*)(struct tgl_state *, void *, int, int, const char *))(q->callback)) (TLS, q->callback_extra, 1, registered, phone_code_hash);
- }
- return 0;
-}
-
-static int send_code_on_error (struct tgl_state *TLS, struct query *q UU, int error_code, int l, char *error) {
- int s = strlen ("PHONE_MIGRATE_");
- int s2 = strlen ("NETWORK_MIGRATE_");
- int want_dc_num = 0;
- if (l >= s && !memcmp (error, "PHONE_MIGRATE_", s)) {
- int i = error[s] - '0';
- want_dc_num = i;
- } else if (l >= s2 && !memcmp (error, "NETWORK_MIGRATE_", s2)) {
- int i = error[s2] - '0';
- want_dc_num = i;
- } else {
- vlogprintf (E_ERROR, "error_code = %d, error = %.*s\n", error_code, l, error);
- if (q->callback) {
- ((void (*)(struct tgl_state *, void *, int, int, const char *))(q->callback)) (TLS, q->callback_extra, 0, 0, 0);
- }
- return 0;
- }
- bl_do_set_working_dc (TLS, want_dc_num);
- //if (q->callback) {
- // ((void (*)(void *, int, int, const char *))(q->callback)) (q->callback_extra, 0, 0, 0);
- //}
- assert (TLS->DC_working->id == want_dc_num);
- tgl_do_send_code (TLS, q->extra, q->callback, q->callback_extra);
- tfree_str (q->extra);
- return 0;
-}
-
-static struct query_methods send_code_methods = {
- .on_answer = send_code_on_answer,
- .on_error = send_code_on_error,
- .type = TYPE_TO_PARAM(auth_sent_code)
-};
-
-//char *suser;
-//extern int dc_working_num;
-void tgl_do_send_code (struct tgl_state *TLS, const char *user, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, int registered, const char *hash), void *callback_extra) {
- vlogprintf (E_DEBUG, "sending code to dc %d\n", TLS->dc_working_num);
- //suser = tstrdup (user);
- clear_packet ();
- tgl_do_insert_header ();
- out_int (CODE_auth_send_code);
- out_string (user);
- out_int (0);
- out_int (TG_APP_ID);
- out_string (TG_APP_HASH);
- out_string ("en");
-
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_code_methods, tstrdup (user), callback, callback_extra);
-}
-
-
-static int phone_call_on_answer (struct tgl_state *TLS, struct query *q UU) {
- fetch_bool ();
- if (q->callback) {
- ((void (*)(struct tgl_state *TLS, void *, int))(q->callback))(TLS, q->callback_extra, 1);
- }
- return 0;
-}
-
-static struct query_methods phone_call_methods = {
- .on_answer = phone_call_on_answer,
- .type = TYPE_TO_PARAM(bool)
-};
-
-void tgl_do_phone_call (struct tgl_state *TLS, const char *user, const char *hash,void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) {
- vlogprintf (E_DEBUG, "calling user\n");
- //suser = tstrdup (user);
- //want_dc_num = 0;
- clear_packet ();
- tgl_do_insert_header ();
- out_int (CODE_auth_send_call);
- out_string (user);
- out_string (hash);
-
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &phone_call_methods, 0, callback, callback_extra);
-}
-/* }}} */
-
-/* {{{ Sign in / Sign up */
-static int sign_in_on_answer (struct tgl_state *TLS, struct query *q UU) {
- assert (fetch_int () == (int)CODE_auth_authorization);
- int expires = fetch_int ();
- vlogprintf (E_DEBUG, "Expires in %d\n", expires);
-
- struct tgl_user *U = tglf_fetch_alloc_user (TLS);
-
- TLS->DC_working->has_auth = 1;
-
- bl_do_dc_signed (TLS, TLS->DC_working->id);
-
- if (q->callback) {
- ((void (*)(struct tgl_state *TLS, void *, int, struct tgl_user *))q->callback) (TLS, q->callback_extra, 1, U);
- }
-
- return 0;
-}
-
-static struct query_methods sign_in_methods = {
- .on_answer = sign_in_on_answer,
- .type = TYPE_TO_PARAM(auth_authorization)
-};
-
-int tgl_do_send_code_result (struct tgl_state *TLS, const char *user, const char *hash, const char *code, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_user *Self), void *callback_extra) {
- clear_packet ();
- out_int (CODE_auth_sign_in);
- out_string (user);
- out_string (hash);
- out_string (code);
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &sign_in_methods, 0, callback, callback_extra);
- return 0;
-}
-
-int tgl_do_send_code_result_auth (struct tgl_state *TLS, const char *user, const char *hash, const char *code, const char *first_name, const char *last_name, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_user *Self), void *callback_extra) {
- clear_packet ();
- out_int (CODE_auth_sign_up);
- out_string (user);
- out_string (hash);
- out_string (code);
- out_string (first_name);
- out_string (last_name);
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &sign_in_methods, 0, callback, callback_extra);
- return 0;
-}
-/* }}} */
-
-/* {{{ Get contacts */
-static int get_contacts_on_answer (struct tgl_state *TLS, struct query *q UU) {
- int i;
-
- assert (fetch_int () == (int)CODE_contacts_contacts);
- assert (fetch_int () == CODE_vector);
- int n = fetch_int ();
- for (i = 0; i < n; i++) {
- assert (fetch_int () == (int)CODE_contact);
- fetch_int (); // id
- fetch_int (); // mutual
- }
- assert (fetch_int () == CODE_vector);
- n = fetch_int ();
- struct tgl_user **list = talloc (sizeof (void *) * n);
- for (i = 0; i < n; i++) {
- list[i] = tglf_fetch_alloc_user (TLS);
- }
- if (q->callback) {
- ((void (*)(struct tgl_state *TLS, void *, int, int, struct tgl_user **))q->callback) (TLS, q->callback_extra, 1, n, list);
- }
- tfree (list, sizeof (void *) * n);
-/* for (i = 0; i < n; i++) {
- struct tgl_user *U = tglf_fetch_alloc_user (TLS);
- print_start ();
- push_color (COLOR_YELLOW);
- printf ("User #%d: ", tgl_get_peer_id (U->id));
- print_user_name (U->id, (tgl_peer_t *)U);
- push_color (COLOR_GREEN);
- printf (" (");
- printf ("%s", U->print_name);
- if (U->phone) {
- printf (" ");
- printf ("%s", U->phone);
- }
- printf (") ");
- pop_color ();
- if (U->status.online > 0) {
- printf ("online\n");
- } else {
- if (U->status.online < 0) {
- printf ("offline. Was online ");
- print_date_full (U->status.when);
- } else {
- printf ("offline permanent");
- }
- printf ("\n");
- }
- pop_color ();
- print_end ();
- }*/
- return 0;
-}
-
-static struct query_methods get_contacts_methods = {
- .on_answer = get_contacts_on_answer,
- .type = TYPE_TO_PARAM(contacts_contacts)
-};
-
-
-void tgl_do_update_contact_list (struct tgl_state *TLS, void (*callback) (struct tgl_state *TLS, void *callback_extra, int success, int size, struct tgl_user *contacts[]), void *callback_extra) {
- clear_packet ();
- out_int (CODE_contacts_get_contacts);
- out_string ("");
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &get_contacts_methods, 0, callback, callback_extra);
-}
-/* }}} */
-
-/* {{{ Encrypt decrypted */
-static int *encr_extra;
-static int *encr_ptr;
-static int *encr_end;
-
-static char *encrypt_decrypted_message (struct tgl_secret_chat *E) {
- static int msg_key[4];
- static unsigned char sha1a_buffer[20];
- static unsigned char sha1b_buffer[20];
- static unsigned char sha1c_buffer[20];
- static unsigned char sha1d_buffer[20];
- int x = *(encr_ptr);
- assert (x >= 0 && !(x & 3));
- sha1 ((void *)encr_ptr, 4 + x, sha1a_buffer);
- memcpy (msg_key, sha1a_buffer + 4, 16);
-
- static unsigned char buf[64];
- memcpy (buf, msg_key, 16);
- memcpy (buf + 16, E->key, 32);
- sha1 (buf, 48, sha1a_buffer);
-
- memcpy (buf, E->key + 8, 16);
- memcpy (buf + 16, msg_key, 16);
- memcpy (buf + 32, E->key + 12, 16);
- sha1 (buf, 48, sha1b_buffer);
-
- memcpy (buf, E->key + 16, 32);
- memcpy (buf + 32, msg_key, 16);
- sha1 (buf, 48, sha1c_buffer);
-
- memcpy (buf, msg_key, 16);
- memcpy (buf + 16, E->key + 24, 32);
- sha1 (buf, 48, sha1d_buffer);
-
- static unsigned char key[32];
- memcpy (key, sha1a_buffer + 0, 8);
- memcpy (key + 8, sha1b_buffer + 8, 12);
- memcpy (key + 20, sha1c_buffer + 4, 12);
-
- static unsigned char iv[32];
- memcpy (iv, sha1a_buffer + 8, 12);
- memcpy (iv + 12, sha1b_buffer + 0, 8);
- memcpy (iv + 20, sha1c_buffer + 16, 4);
- memcpy (iv + 24, sha1d_buffer + 0, 8);
-
- AES_KEY aes_key;
- AES_set_encrypt_key (key, 256, &aes_key);
- AES_ige_encrypt ((void *)encr_ptr, (void *)encr_ptr, 4 * (encr_end - encr_ptr), &aes_key, iv, 1);
- memset (&aes_key, 0, sizeof (aes_key));
-
- return (void *)msg_key;
-}
-
-static void encr_start (void) {
- encr_extra = packet_ptr;
- packet_ptr += 1; // str len
- packet_ptr += 2; // fingerprint
- packet_ptr += 4; // msg_key
- packet_ptr += 1; // len
-}
-
-
-static void encr_finish (struct tgl_secret_chat *E) {
- int l = packet_ptr - (encr_extra + 8);
- while (((packet_ptr - encr_extra) - 3) & 3) {
- int t;
- tglt_secure_random (&t, 4);
- out_int (t);
- }
-
- *encr_extra = ((packet_ptr - encr_extra) - 1) * 4 * 256 + 0xfe;
- encr_extra ++;
- *(long long *)encr_extra = E->key_fingerprint;
- encr_extra += 2;
- encr_extra[4] = l * 4;
- encr_ptr = encr_extra + 4;
- encr_end = packet_ptr;
- memcpy (encr_extra, encrypt_decrypted_message (E), 16);
-}
-/* }}} */
-
-void tgl_do_send_encr_chat_layer (struct tgl_state *TLS, struct tgl_secret_chat *E) {
- long long t;
- tglt_secure_random (&t, 8);
- int action[2];
- action[0] = CODE_decrypted_message_action_notify_layer;
- action[1] = TGL_ENCRYPTED_LAYER;
- bl_do_send_message_action_encr (TLS, t, TLS->our_id, tgl_get_peer_type (E->id), tgl_get_peer_id (E->id), time (0), 2, action);
-
- struct tgl_message *M = tgl_message_get (TLS, t);
- assert (M);
- assert (M->action.type == tgl_message_action_notify_layer);
- tgl_do_send_msg (TLS, M, 0, 0);
- //print_message (M);
-}
-
-void tgl_do_set_encr_chat_ttl (struct tgl_state *TLS, struct tgl_secret_chat *E, int ttl, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) {
- long long t;
- tglt_secure_random (&t, 8);
- int action[2];
- action[0] = CODE_decrypted_message_action_set_message_t_t_l;
- action[1] = ttl;
- bl_do_send_message_action_encr (TLS, t, TLS->our_id, tgl_get_peer_type (E->id), tgl_get_peer_id (E->id), time (0), 2, action);
-
- struct tgl_message *M = tgl_message_get (TLS, t);
- assert (M);
- assert (M->action.type == tgl_message_action_set_message_ttl);
- tgl_do_send_msg (TLS, M, callback, callback_extra);
- //print_message (M);
-}
-
-/* {{{ Seng msg (plain text) */
-static int msg_send_encr_on_answer (struct tgl_state *TLS, struct query *q UU) {
- assert (fetch_int () == CODE_messages_sent_encrypted_message);
- struct tgl_message *M = q->extra;
- //M->date = fetch_int ();
- fetch_int ();
- if (M->flags & FLAG_PENDING) {
- bl_do_set_message_sent (TLS, M);
- bl_do_msg_update (TLS, M->id);
- }
-
- if (q->callback) {
- ((void (*)(struct tgl_state *TLS, void *, int, struct tgl_message *))q->callback) (TLS, q->callback_extra, 1, M);
- }
- return 0;
-}
-
-static int msg_send_on_answer (struct tgl_state *TLS, struct query *q UU) {
- unsigned x = fetch_int ();
- assert (x == CODE_messages_sent_message || x == CODE_messages_sent_message_link);
- int id = fetch_int (); // id
- long long y = *(long long *)q->extra;
- tfree (q->extra, 8);
- struct tgl_message *M = tgl_message_get (TLS, y);
- if (M && M->id != id) {
- bl_do_set_msg_id (TLS, M, id);
- }
- int date = fetch_int ();
- int pts = fetch_int ();
- //tglu_fetch_seq ();
- //bl_do_
- int seq = fetch_int ();
- if (seq == TLS->seq + 1 && !(TLS->locks & TGL_LOCK_DIFF)) {
- bl_do_set_date (TLS, date);
- bl_do_set_pts (TLS, pts);
- bl_do_msg_seq_update (TLS, id);
- } else {
- if (seq > TLS->seq + 1) {
- vlogprintf (E_NOTICE, "Hole in seq\n");
- tgl_do_get_difference (TLS, 0, 0, 0);
- }
- }
- if (x == CODE_messages_sent_message_link) {
- assert (skip_type_any (TYPE_TO_PARAM_1 (vector, TYPE_TO_PARAM (contacts_link))) >= 0);
- }
- /*if (x == CODE_messages_sent_message_link) {
- assert (fetch_int () == CODE_vector);
- int n = fetch_int ();
- int i;
- unsigned a, b;
- for (i = 0; i < n; i++) {
- assert (fetch_int () == (int)CODE_contacts_link);
- a = fetch_int ();
- assert (a == CODE_contacts_my_link_empty || a == CODE_contacts_my_link_requested || a == CODE_contacts_my_link_contact);
- if (a == CODE_contacts_my_link_requested) {
- fetch_bool ();
- }
- b = fetch_int ();
- assert (b == CODE_contacts_foreign_link_unknown || b == CODE_contacts_foreign_link_requested || b == CODE_contacts_foreign_link_mutual);
- if (b == CODE_contacts_foreign_link_requested) {
- fetch_bool ();
- }
- struct tgl_user *U = tglf_fetch_alloc_user (TLS);
-
- U->flags &= ~(FLAG_USER_IN_CONTACT | FLAG_USER_OUT_CONTACT);
- if (a == CODE_contacts_my_link_contact) {
- U->flags |= FLAG_USER_IN_CONTACT;
- }
- U->flags &= ~(FLAG_USER_IN_CONTACT | FLAG_USER_OUT_CONTACT);
- if (b == CODE_contacts_foreign_link_mutual) {
- U->flags |= FLAG_USER_IN_CONTACT | FLAG_USER_OUT_CONTACT;
- }
- if (b == CODE_contacts_foreign_link_requested) {
- U->flags |= FLAG_USER_OUT_CONTACT;
- }
- print_start ();
- push_color (COLOR_YELLOW);
- printf ("Link with user ");
- print_user_name (U->id, (void *)U);
- printf (" changed\n");
- pop_color ();
- print_end ();
- }
- }*/
- if (M->flags & FLAG_PENDING) {
- bl_do_set_message_sent (TLS, M);
- }
- if (q->callback) {
- ((void (*)(struct tgl_state *,void *, int, struct tgl_message *))q->callback) (TLS, q->callback_extra, 1, M);
- }
- return 0;
-}
-
-static int msg_send_on_error (struct tgl_state *TLS, struct query *q, int error_code, int error_len, char *error) {
- //vlogprintf (E_WARNING, "error for query #%lld: #%d :%.*s\n", q->msg_id, error_code, error_len, error);
- if (error_code == 420) {
- assert (!strncmp (error, "FLOOD_WAIT_", 11));
- int wait = atoll (error + 11);
- q->flags &= ~QUERY_ACK_RECEIVED;
-
- TLS->timer_methods->insert (q->ev, wait);
- q->session_id = 0;
- return 1;
- }
- long long x = *(long long *)q->extra;
- tfree (q->extra, 8);
- struct tgl_message *M = tgl_message_get (TLS, x);
- if (q->callback) {
- ((void (*)(struct tgl_state *,void *, int, struct tgl_message *))q->callback) (TLS, q->callback_extra, 0, M);
- }
- if (M) {
- bl_do_delete_msg (TLS, M);
- }
- return 0;
-}
-
-static struct query_methods msg_send_methods = {
- .on_answer = msg_send_on_answer,
- .on_error = msg_send_on_error,
- .type = TYPE_TO_PARAM(messages_sent_message)
-};
-
-static struct query_methods msg_send_encr_methods = {
- .on_answer = msg_send_encr_on_answer,
- .type = TYPE_TO_PARAM(messages_sent_encrypted_message)
-};
-
-//int out_message_num;
-
-void tgl_do_send_encr_msg_action (struct tgl_state *TLS, struct tgl_message *M, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) {
- tgl_peer_t *P = tgl_peer_get (TLS, M->to_id);
- if (!P || P->encr_chat.state != sc_ok) {
- vlogprintf (E_WARNING, "Unknown encrypted chat\n");
- if (callback) {
- callback (TLS, callback_extra, 0, 0);
- }
- return;
- }
-
- clear_packet ();
- out_int (CODE_messages_send_encrypted_service);
- out_int (CODE_input_encrypted_chat);
- out_int (tgl_get_peer_id (M->to_id));
- out_long (P->encr_chat.access_hash);
- out_long (M->id);
- encr_start ();
- if (P->encr_chat.layer <= 16) {
- out_int (CODE_decrypted_message_service_l16);
- } else {
- out_int (CODE_decrypted_message_layer);
- out_random (15 + 4 * (lrand48 () % 3));
- out_int (TGL_ENCRYPTED_LAYER);
- out_int (2 * P->encr_chat.in_seq_no + (P->encr_chat.admin_id != TLS->our_id));
- out_int (2 * P->encr_chat.out_seq_no + (P->encr_chat.admin_id == TLS->our_id) - 2);
- out_int (CODE_decrypted_message_service);
- }
- out_long (M->id);
- if (P->encr_chat.layer < 17) {
- out_random (15 + 4 * (lrand48 () % 3));
- }
-
- switch (M->action.type) {
- case tgl_message_action_notify_layer:
- out_int (CODE_decrypted_message_action_notify_layer);
- out_int (M->action.layer);
- break;
- case tgl_message_action_set_message_ttl:
- out_int (CODE_decrypted_message_action_set_message_t_t_l);
- out_int (M->action.ttl);
- break;
- default:
- assert (0);
- }
- encr_finish (&P->encr_chat);
-
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_send_encr_methods, M, callback, callback_extra);
-}
-
-void tgl_do_send_encr_msg (struct tgl_state *TLS, struct tgl_message *M, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) {
- if (M->service) {
- tgl_do_send_encr_msg_action (TLS, M, callback, callback_extra);
- return;
- }
- tgl_peer_t *P = tgl_peer_get (TLS, M->to_id);
- if (!P || P->encr_chat.state != sc_ok) {
- vlogprintf (E_WARNING, "Unknown encrypted chat\n");
- if (callback) {
- callback (TLS, callback_extra, 0, M);
- }
- return;
- }
-
- clear_packet ();
- out_int (CODE_messages_send_encrypted);
- out_int (CODE_input_encrypted_chat);
- out_int (tgl_get_peer_id (M->to_id));
- out_long (P->encr_chat.access_hash);
- out_long (M->id);
- encr_start ();
- if (P->encr_chat.layer <= 16) {
- out_int (CODE_decrypted_message_service_l16);
- } else {
- out_int (CODE_decrypted_message_layer);
- out_random (15 + 4 * (lrand48 () % 3));
- out_int (TGL_ENCRYPTED_LAYER);
- out_int (2 * P->encr_chat.in_seq_no + (P->encr_chat.admin_id != TLS->our_id));
- out_int (2 * P->encr_chat.out_seq_no + (P->encr_chat.admin_id == TLS->our_id) - 2);
- out_int (CODE_decrypted_message);
- }
- out_long (M->id);
- if (P->encr_chat.layer < 17) {
- out_random (15 + 4 * (lrand48 () % 3));
- } else {
- out_int (0);
- }
- out_cstring ((void *)M->message, M->message_len);
- out_int (CODE_decrypted_message_media_empty);
- encr_finish (&P->encr_chat);
-
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_send_encr_methods, M, callback, callback_extra);
-}
-
-void tgl_do_send_msg (struct tgl_state *TLS, struct tgl_message *M, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) {
- if (tgl_get_peer_type (M->to_id) == TGL_PEER_ENCR_CHAT) {
- tgl_do_send_encr_msg (TLS, M, callback, callback_extra);
- return;
- }
- clear_packet ();
- out_int (CODE_messages_send_message);
- out_peer_id (TLS, M->to_id);
- out_cstring (M->message, M->message_len);
- out_long (M->id);
- long long *x = talloc (8);
- *x = M->id;
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_send_methods, x, callback, callback_extra);
-}
-
-void tgl_do_send_message (struct tgl_state *TLS, tgl_peer_id_t id, const char *msg, int len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) {
- if (tgl_get_peer_type (id) == TGL_PEER_ENCR_CHAT) {
- tgl_peer_t *P = tgl_peer_get (TLS, id);
- if (!P) {
- vlogprintf (E_WARNING, "Unknown encrypted chat\n");
- if (callback) {
- callback (TLS, callback_extra, 0, 0);
- }
- return;
- }
- if (P->encr_chat.state != sc_ok) {
- vlogprintf (E_WARNING, "Chat is not yet initialized\n");
- if (callback) {
- callback (TLS, callback_extra, 0, 0);
- }
- return;
- }
- }
- long long t;
- tglt_secure_random (&t, 8);
- vlogprintf (E_DEBUG, "t = %lld, len = %d\n", t, len);
- bl_do_send_message_text (TLS, t, TLS->our_id, tgl_get_peer_type (id), tgl_get_peer_id (id), time (0), len, msg);
- struct tgl_message *M = tgl_message_get (TLS, t);
- assert (M);
- tgl_do_send_msg (TLS, M, callback, callback_extra);
- //print_message (M);
-}
-/* }}} */
-
-/* {{{ Send text file */
-void tgl_do_send_text (struct tgl_state *TLS, tgl_peer_id_t id, char *file_name, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) {
- int fd = open (file_name, O_RDONLY);
- if (fd < 0) {
- vlogprintf (E_WARNING, "No such file '%s'\n", file_name);
- if (callback) {
- callback (TLS, callback_extra, 0, 0);
- }
- return;
- }
- static char buf[(1 << 20) + 1];
- int x = read (fd, buf, (1 << 20) + 1);
- assert (x >= 0);
- if (x == (1 << 20) + 1) {
- vlogprintf (E_WARNING, "Too big file '%s'\n", file_name);
- close (fd);
- if (callback) {
- callback (TLS, callback_extra, 0, 0);
- }
- } else {
- buf[x] = 0;
- tgl_do_send_message (TLS, id, buf, x, callback, callback_extra);
- //tfree_str (file_name);
- close (fd);
- }
-}
-/* }}} */
-
-/* {{{ Mark read */
-void tgl_do_messages_mark_read (struct tgl_state *TLS, tgl_peer_id_t id, int max_id, int offset, void (*callback)(struct tgl_state *TLS, void *callback_extra, int), void *callback_extra);
-static int mark_read_on_receive (struct tgl_state *TLS, struct query *q UU) {
- assert (fetch_int () == (int)CODE_messages_affected_history);
- //tglu_fetch_pts ();
- int pts = fetch_int ();
- //tglu_fetch_seq ();
- int seq = fetch_int (); // seq
-
- if (seq == TLS->seq + 1 && !(TLS->locks & TGL_LOCK_DIFF)) {
- bl_do_set_pts (TLS, pts);
- bl_do_set_seq (TLS, seq);
- } else {
- if (seq > TLS->seq + 1) {
- vlogprintf (E_NOTICE, "Hole in seq\n");
- tgl_do_get_difference (TLS, 0, 0, 0);
- }
- }
-
- int offset = fetch_int (); // offset
- int *t = q->extra;
- if (offset > 0) {
- tgl_do_messages_mark_read (TLS, tgl_set_peer_id (t[0], t[1]), t[2], offset, q->callback, q->callback_extra);
- } else {
- if (q->callback) {
- ((void (*)(struct tgl_state *, void *, int))q->callback)(TLS, q->callback_extra, 1);
- }
- }
- tfree (t, 12);
- return 0;
-}
-
-static int mark_read_encr_on_receive (struct tgl_state *TLS, struct query *q UU) {
- fetch_bool ();
- if (q->callback) {
- ((void (*)(struct tgl_state *, void *, int))q->callback)(TLS, q->callback_extra, 1);
- }
- return 0;
-}
-
-static struct query_methods mark_read_methods = {
- .on_answer = mark_read_on_receive,
- .type = TYPE_TO_PARAM(messages_affected_history)
-};
-
-static struct query_methods mark_read_encr_methods = {
- .on_answer = mark_read_encr_on_receive,
- .type = TYPE_TO_PARAM(bool)
-};
-
-void tgl_do_messages_mark_read (struct tgl_state *TLS, tgl_peer_id_t id, int max_id, int offset, void (*callback)(struct tgl_state *TLS, void *callback_extra, int), void *callback_extra) {
- clear_packet ();
- out_int (CODE_messages_read_history);
- out_peer_id (TLS, id);
- out_int (max_id);
- out_int (offset);
- out_int (CODE_bool_true);
- int *t = talloc (12);
- t[0] = tgl_get_peer_type (id);
- t[1] = tgl_get_peer_id (id);
- t[2] = max_id;
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &mark_read_methods, t, callback, callback_extra);
-}
-
-void tgl_do_messages_mark_read_encr (struct tgl_state *TLS, tgl_peer_id_t id, long long access_hash, int last_time, void (*callback)(struct tgl_state *TLS, void *callback_extra, int), void *callback_extra) {
- clear_packet ();
- out_int (CODE_messages_read_encrypted_history);
- out_int (CODE_input_encrypted_chat);
- out_int (tgl_get_peer_id (id));
- out_long (access_hash);
- out_int (last_time);
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &mark_read_encr_methods, 0, callback, callback_extra);
-}
-
-void tgl_do_mark_read (struct tgl_state *TLS, tgl_peer_id_t id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) {
- if (tgl_get_peer_type (id) == TGL_PEER_USER || tgl_get_peer_type (id) == TGL_PEER_CHAT) {
- tgl_do_messages_mark_read (TLS, id, 0, 0, callback, callback_extra);
- return;
- }
- tgl_peer_t *P = tgl_peer_get (TLS, id);
- if (!P) {
- vlogprintf (E_WARNING, "Unknown peer\n");
- callback (TLS, callback_extra, 0);
- return;
- }
- assert (tgl_get_peer_type (id) == TGL_PEER_ENCR_CHAT);
- if (P->last) {
- tgl_do_messages_mark_read_encr (TLS, id, P->encr_chat.access_hash, P->last->date, callback, callback_extra);
- } else {
- tgl_do_messages_mark_read_encr (TLS, id, P->encr_chat.access_hash, 0, callback, callback_extra);
- }
-}
-/* }}} */
-
-/* {{{ Get history */
-void _tgl_do_get_history (struct tgl_state *TLS, tgl_peer_id_t id, int limit, int offset, int max_id, int list_offset, int list_size, struct tgl_message *ML[], void (*callback)(struct tgl_state *TLS,void *callback_extra, int success, int size, struct tgl_message *list[]), void *callback_extra);
-static int get_history_on_answer (struct tgl_state *TLS, struct query *q UU) {
- int count = -1;
- int i;
- int x = fetch_int ();
- assert (x == (int)CODE_messages_messages_slice || x == (int)CODE_messages_messages);
- if (x == (int)CODE_messages_messages_slice) {
- count = fetch_int ();
- //fetch_int ();
- }
- assert (fetch_int () == CODE_vector);
- void **T = q->extra;
- struct tgl_message **ML = T[0];
- int list_offset = (long)T[1];
- int list_size = (long)T[2];
- tgl_peer_id_t id = tgl_set_peer_id ((long)T[4], (long)T[3]);
- int limit = (long)T[5];
- int offset = (long)T[6];
- tfree (T, sizeof (void *) * 7);
-
- int n = fetch_int ();
-
- if (list_size - list_offset < n) {
- int new_list_size = 2 * list_size;
- if (new_list_size - list_offset < n) {
- new_list_size = n + list_offset;
- }
- ML = trealloc (ML, list_size * sizeof (void *), new_list_size * sizeof (void *));
- assert (ML);
- list_size = new_list_size;
- }
- //struct tgl_message **ML = talloc (sizeof (void *) * n);
- for (i = 0; i < n; i++) {
- ML[i + list_offset] = tglf_fetch_alloc_message (TLS);
- }
- list_offset += n;
- offset += n;
- limit -= n;
- if (count >= 0 && limit + offset >= count) {
- limit = count - offset;
- if (limit < 0) { limit = 0; }
- }
- assert (limit >= 0);
-
- assert (fetch_int () == CODE_vector);
- n = fetch_int ();
- for (i = 0; i < n; i++) {
- tglf_fetch_alloc_chat (TLS);
- }
- assert (fetch_int () == CODE_vector);
- n = fetch_int ();
- for (i = 0; i < n; i++) {
- tglf_fetch_alloc_user (TLS);
- }
-
-
- if (limit <= 0 || x == (int)CODE_messages_messages) {
- if (q->callback) {
- ((void (*)(struct tgl_state *TLS, void *, int, int, struct tgl_message **))q->callback) (TLS, q->callback_extra, 1, list_offset, ML);
- }
- if (list_offset > 0) {
- tgl_do_messages_mark_read (TLS, id, ML[0]->id, 0, 0, 0);
- }
-
-
- tfree (ML, sizeof (void *) * list_size);
- } else {
- _tgl_do_get_history (TLS, id, limit, 0, ML[list_offset - 1]->id, list_offset, list_size, ML, q->callback, q->callback_extra);
- }
- return 0;
-}
-
-static struct query_methods get_history_methods = {
- .on_answer = get_history_on_answer,
- .type = TYPE_TO_PARAM(messages_messages)
-};
-
-void tgl_do_get_local_history (struct tgl_state *TLS, tgl_peer_id_t id, int limit, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, int size, struct tgl_message *list[]), void *callback_extra) {
- tgl_peer_t *P = tgl_peer_get (TLS, id);
- if (!P || !P->last) {
- if (callback) {
- callback (TLS, callback_extra, 0, 0, 0);
- }
- return;
- }
- struct tgl_message *M = P->last;
- int count = 1;
- assert (!M->prev);
- while (count < limit && M->next) {
- M = M->next;
- count ++;
- }
- struct tgl_message **ML = talloc (sizeof (void *) * count);
- M = P->last;
- ML[0] = M;
- count = 1;
- while (count < limit && M->next) {
- M = M->next;
- ML[count ++] = M;
- }
-
- if (callback) {
- callback (TLS, callback_extra, 1, count, ML);
- }
- tfree (ML, sizeof (void *) * count);
-}
-
-void tgl_do_get_local_history_ext (struct tgl_state *TLS, tgl_peer_id_t id, int offset, int limit, void (*callback)(struct tgl_state *TLS,void *callback_extra, int success, int size, struct tgl_message *list[]), void *callback_extra) {
- tgl_peer_t *P = tgl_peer_get (TLS, id);
- if (!P || !P->last) {
- if (callback) {
- callback (TLS, callback_extra, 0, 0, 0);
- }
- return;
- }
- struct tgl_message *M = P->last;
- int count = 1;
- assert (!M->prev);
- while (count < limit + offset && M->next) {
- M = M->next;
- count ++;
- }
- if (count <= offset) {
- if (callback) {
- callback (TLS, callback_extra, 1, 0, 0);
- }
- return;
- }
- struct tgl_message **ML = talloc (sizeof (void *) * (count - offset));
- M = P->last;
- ML[0] = M;
- count = 1;
- while (count < limit && M->next) {
- M = M->next;
- if (count >= offset) {
- ML[count - offset] = M;
- }
- count ++;
- }
-
- if (callback) {
- callback (TLS, callback_extra, 1, count - offset, ML);
- }
- tfree (ML, sizeof (void *) * (count) - offset);
-}
-
-
-
-void _tgl_do_get_history (struct tgl_state *TLS, tgl_peer_id_t id, int limit, int offset, int max_id, int list_offset, int list_size, struct tgl_message *ML[], void (*callback)(struct tgl_state *TLS,void *callback_extra, int success, int size, struct tgl_message *list[]), void *callback_extra) {
- void **T = talloc (sizeof (void *) * 7);
- T[0] = ML;
- T[1] = (void *)(long)list_offset;
- T[2] = (void *)(long)list_size;
- T[3] = (void *)(long)tgl_get_peer_id (id);
- T[4] = (void *)(long)tgl_get_peer_type (id);
- T[5] = (void *)(long)limit;
- T[6] = (void *)(long)offset;
-
- clear_packet ();
- out_int (CODE_messages_get_history);
- out_peer_id (TLS, id);
- out_int (offset);
- out_int (max_id);
- out_int (limit);
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &get_history_methods, T, callback, callback_extra);
-}
-
-void tgl_do_get_history (struct tgl_state *TLS, tgl_peer_id_t id, int limit, int offline_mode, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, int size, struct tgl_message *list[]), void *callback_extra) {
- if (tgl_get_peer_type (id) == TGL_PEER_ENCR_CHAT || offline_mode) {
- tgl_do_get_local_history (TLS, id, limit, callback, callback_extra);
- tgl_do_mark_read (TLS, id, 0, 0);
- return;
- }
- _tgl_do_get_history (TLS, id, limit, 0, 0, 0, 0, 0, callback, callback_extra);
-}
-
-void tgl_do_get_history_ext (struct tgl_state *TLS, tgl_peer_id_t id, int offset, int limit, int offline_mode, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, int size, struct tgl_message *list[]), void *callback_extra) {
- if (tgl_get_peer_type (id) == TGL_PEER_ENCR_CHAT || offline_mode) {
- tgl_do_get_local_history (TLS, id, limit, callback, callback_extra);
- tgl_do_mark_read (TLS, id, 0, 0);
- return;
- }
- _tgl_do_get_history (TLS, id, limit, offset, 0, 0, 0, 0, callback, callback_extra);
-}
-/* }}} */
-
-/* {{{ Get dialogs */
-static int get_dialogs_on_answer (struct tgl_state *TLS, struct query *q UU) {
- unsigned x = fetch_int ();
- assert (x == CODE_messages_dialogs || x == CODE_messages_dialogs_slice);
- if (x == CODE_messages_dialogs_slice) {
- fetch_int (); // total_count
- }
- assert (fetch_int () == CODE_vector);
- int n, i;
- n = fetch_int ();
- int dl_size = n;
-
- tgl_peer_id_t *PL = talloc0 (sizeof (tgl_peer_id_t) * n);
- int *UC = talloc0 (4 * n);
- int *LM = talloc0 (4 * n);
- for (i = 0; i < n; i++) {
- assert (fetch_int () == (int)CODE_dialog);
- PL[i] = tglf_fetch_peer_id (TLS);
- LM[i] = fetch_int ();
- UC[i] = fetch_int ();
- assert (skip_type_any (TYPE_TO_PARAM (peer_notify_settings)) >= 0);
- }
- assert (fetch_int () == CODE_vector);
- n = fetch_int ();
- for (i = 0; i < n; i++) {
- tglf_fetch_alloc_message (TLS);
- }
- assert (fetch_int () == CODE_vector);
- n = fetch_int ();
- for (i = 0; i < n; i++) {
- tglf_fetch_alloc_chat (TLS);
- }
- assert (fetch_int () == CODE_vector);
- n = fetch_int ();
- for (i = 0; i < n; i++) {
- tglf_fetch_alloc_user (TLS);
- }
- /*print_start ();
- push_color (COLOR_YELLOW);
- for (i = dl_size - 1; i >= 0; i--) {
- tgl_peer_t *UC;
- switch (tgl_get_peer_type (plist[i])) {
- case TGL_PEER_USER:
- UC = tgl_peer_get (TLS, plist[i]);
- printf ("User ");
- print_user_name (plist[i], UC);
- printf (": %d unread\n", dlist[2 * i + 1]);
- break;
- case TGL_PEER_CHAT:
- UC = tgl_peer_get (TLS, plist[i]);
- printf ("Chat ");
- print_chat_name (plist[i], UC);
- printf (": %d unread\n", dlist[2 * i + 1]);
- break;
- }
- }
- pop_color ();
- print_end ();
-
- dialog_list_got = 1;*/
-
- if (q->callback) {
- ((void (*)(struct tgl_state *TLS, void *, int, int, tgl_peer_id_t *, int *, int *))q->callback) (TLS, q->callback_extra, 1, dl_size, PL, LM, UC);
- }
- tfree (PL, sizeof (tgl_peer_id_t) * dl_size);
- tfree (UC, 4 * dl_size);
- tfree (LM, 4 * dl_size);
-
- return 0;
-}
-
-static struct query_methods get_dialogs_methods = {
- .on_answer = get_dialogs_on_answer,
- .type = TYPE_TO_PARAM(messages_dialogs)
-};
-
-
-void tgl_do_get_dialog_list (struct tgl_state *TLS, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, int size, tgl_peer_id_t peers[], int last_msg_id[], int unread_count[]), void *callback_extra) {
- clear_packet ();
- out_int (CODE_messages_get_dialogs);
- out_int (0);
- out_int (0);
- out_int (1000);
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &get_dialogs_methods, 0, callback, callback_extra);
-}
-/* }}} */
-
-int allow_send_linux_version = 1;
-
-/* {{{ Send photo/video file */
-struct send_file {
- int fd;
- long long size;
- long long offset;
- int part_num;
- int part_size;
- long long id;
- long long thumb_id;
- tgl_peer_id_t to_id;
- unsigned media_type;
- char *file_name;
- int encr;
- int avatar;
- unsigned char *iv;
- unsigned char *init_iv;
- unsigned char *key;
-};
-
-static void out_peer_id (struct tgl_state *TLS, tgl_peer_id_t id) {
- tgl_peer_t *U;
- switch (tgl_get_peer_type (id)) {
- case TGL_PEER_CHAT:
- out_int (CODE_input_peer_chat);
- out_int (tgl_get_peer_id (id));
- break;
- case TGL_PEER_USER:
- U = tgl_peer_get (TLS, id);
- if (U && U->user.access_hash) {
- out_int (CODE_input_peer_foreign);
- out_int (tgl_get_peer_id (id));
- out_long (U->user.access_hash);
- } else {
- out_int (CODE_input_peer_contact);
- out_int (tgl_get_peer_id (id));
- }
- break;
- default:
- assert (0);
- }
-}
-
-static void send_part (struct tgl_state *TLS, struct send_file *f, void *callback, void *callback_extra);
-static int send_file_part_on_answer (struct tgl_state *TLS, struct query *q) {
- assert (fetch_int () == (int)CODE_bool_true);
- send_part (TLS, q->extra, q->callback, q->callback_extra);
- return 0;
-}
-
-static int send_file_on_answer (struct tgl_state *TLS, struct query *q UU) {
- assert (fetch_int () == (int)CODE_messages_stated_message);
- struct tgl_message *M = tglf_fetch_alloc_message (TLS);
- assert (fetch_int () == CODE_vector);
- int n, i;
- n = fetch_int ();
- for (i = 0; i < n; i++) {
- tglf_fetch_alloc_chat (TLS);
- }
- assert (fetch_int () == CODE_vector);
- n = fetch_int ();
- for (i = 0; i < n; i++) {
- tglf_fetch_alloc_user (TLS);
- }
- //tglu_fetch_pts ();
- int pts = fetch_int ();
- //tglu_fetch_seq ();
-
- int seq = fetch_int ();
- if (seq == TLS->seq + 1 && !(TLS->locks & TGL_LOCK_DIFF)) {
- bl_do_set_pts (TLS, pts);
- bl_do_msg_seq_update (TLS, M->id);
- } else {
- if (seq > TLS->seq + 1) {
- vlogprintf (E_NOTICE, "Hole in seq\n");
- tgl_do_get_difference (TLS, 0, 0, 0);
- }
- }
-
- if (q->callback) {
- ((void (*)(struct tgl_state *, void *, int, struct tgl_message *))q->callback)(TLS, q->callback_extra, 1, M);
- }
- //print_message (M);
- return 0;
-}
-
-static int send_encr_file_on_answer (struct tgl_state *TLS, struct query *q UU) {
- assert (fetch_int () == (int)CODE_messages_sent_encrypted_file);
- struct tgl_message *M = q->extra;
- //M->date = fetch_int ();
- fetch_int ();
- int *save = in_ptr;
-
- assert (skip_type_any (TYPE_TO_PARAM (encrypted_file)) >= 0);
-
- //print_message (M);
- if (M->flags & FLAG_PENDING) {
- bl_do_create_message_media_encr_sent (TLS, M->id, save, in_ptr - save);
- //bl_do_set_message_sent (M);
- bl_do_msg_update (TLS, M->id);
- }
-
- if (q->callback) {
- ((void (*)(struct tgl_state *, void *, int, struct tgl_message *))q->callback)(TLS, q->callback_extra, 1, M);
- }
- return 0;
-}
-
-static int set_photo_on_answer (struct tgl_state *TLS, struct query *q) {
- assert (skip_type_any (TYPE_TO_PARAM(photos_photo)) >= 0);
- if (q->callback) {
- ((void (*)(struct tgl_state *, void *, int))q->callback)(TLS, q->callback_extra, 1);
- }
- return 0;
-}
-
-static struct query_methods send_file_part_methods = {
- .on_answer = send_file_part_on_answer,
- .type = TYPE_TO_PARAM(bool)
-};
-
-static struct query_methods send_file_methods = {
- .on_answer = send_file_on_answer,
- .type = TYPE_TO_PARAM(messages_stated_message)
-};
-
-static struct query_methods set_photo_methods = {
- .on_answer = set_photo_on_answer,
- .type = TYPE_TO_PARAM(photos_photo)
-};
-
-static struct query_methods send_encr_file_methods = {
- .on_answer = send_encr_file_on_answer,
- .type = TYPE_TO_PARAM(messages_sent_encrypted_message)
-};
-
-static void send_part (struct tgl_state *TLS, struct send_file *f, void *callback, void *callback_extra) {
- if (f->fd >= 0) {
- if (!f->part_num) {
- TLS->cur_uploading_bytes += f->size;
- }
- clear_packet ();
- if (f->size < (16 << 20)) {
- out_int (CODE_upload_save_file_part);
- out_long (f->id);
- out_int (f->part_num ++);
- } else {
- out_int (CODE_upload_save_big_file_part);
- out_long (f->id);
- out_int (f->part_num ++);
- out_int ((f->size + f->part_size - 1) / f->part_size);
- }
- static char buf[512 << 10];
- int x = read (f->fd, buf, f->part_size);
- assert (x > 0);
- f->offset += x;
- TLS->cur_uploaded_bytes += x;
-
- if (f->encr) {
- if (x & 15) {
- assert (f->offset == f->size);
- tglt_secure_random (buf + x, (-x) & 15);
- x = (x + 15) & ~15;
- }
-
- AES_KEY aes_key;
- AES_set_encrypt_key (f->key, 256, &aes_key);
- AES_ige_encrypt ((void *)buf, (void *)buf, x, &aes_key, f->iv, 1);
- memset (&aes_key, 0, sizeof (aes_key));
- }
- out_cstring (buf, x);
- vlogprintf (E_DEBUG, "offset=%lld size=%lld\n", f->offset, f->size);
- if (f->offset == f->size) {
- close (f->fd);
- f->fd = -1;
- } else {
- assert (f->part_size == x);
- }
- //update_prompt ();
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_file_part_methods, f, callback, callback_extra);
- } else {
- TLS->cur_uploaded_bytes -= f->size;
- TLS->cur_uploading_bytes -= f->size;
- //update_prompt ();
- clear_packet ();
- assert (f->media_type == CODE_input_media_uploaded_photo || f->media_type == CODE_input_media_uploaded_video || f->media_type == CODE_input_media_uploaded_thumb_video || f->media_type == CODE_input_media_uploaded_audio || f->media_type == CODE_input_media_uploaded_document || f->media_type == CODE_input_media_uploaded_thumb_document);
- if (f->avatar) {
- assert (!f->encr);
- if (f->avatar > 0) {
- out_int (CODE_messages_edit_chat_photo);
- out_int (f->avatar);
- out_int (CODE_input_chat_uploaded_photo);
- if (f->size < (16 << 20)) {
- out_int (CODE_input_file);
- } else {
- out_int (CODE_input_file_big);
- }
- out_long (f->id);
- out_int (f->part_num);
- /*char *s = f->file_name + strlen (f->file_name);
- while (s >= f->file_name && *s != '/') { s --;}
- out_string (s + 1);*/
- out_string ("");
- if (f->size < (16 << 20)) {
- out_string ("");
- }
- out_int (CODE_input_photo_crop_auto);
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_file_methods, 0, callback, callback_extra);
- } else {
- out_int (CODE_photos_upload_profile_photo);
- if (f->size < (16 << 20)) {
- out_int (CODE_input_file);
- } else {
- out_int (CODE_input_file_big);
- }
- out_long (f->id);
- out_int (f->part_num);
- char *s = f->file_name + strlen (f->file_name);
- while (s >= f->file_name && *s != '/') { s --;}
- out_string (s + 1);
- if (f->size < (16 << 20)) {
- out_string ("");
- }
- out_string ("profile photo");
- out_int (CODE_input_geo_point_empty);
- out_int (CODE_input_photo_crop_auto);
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &set_photo_methods, 0, callback, callback_extra);
- }
- } else if (!f->encr) {
- out_int (CODE_messages_send_media);
- out_peer_id (TLS, f->to_id);
- out_int (f->media_type);
- if (f->size < (16 << 20)) {
- out_int (CODE_input_file);
- } else {
- out_int (CODE_input_file_big);
- }
- out_long (f->id);
- out_int (f->part_num);
- char *s = f->file_name + strlen (f->file_name);
- while (s >= f->file_name && *s != '/') { s --;}
- out_string (s + 1);
- if (f->size < (16 << 20)) {
- out_string ("");
- }
- if (f->media_type == CODE_input_media_uploaded_thumb_video || f->media_type == CODE_input_media_uploaded_thumb_document) {
- out_int (CODE_input_file);
- out_long (f->thumb_id);
- out_int (1);
- out_string ("thumb.jpg");
- out_string ("");
- }
- if (f->media_type == CODE_input_media_uploaded_video || f->media_type == CODE_input_media_uploaded_thumb_video) {
- out_int (100);
- out_int (100);
- out_int (100);
- out_string ("video");
- }
- if (f->media_type == CODE_input_media_uploaded_document || f->media_type == CODE_input_media_uploaded_thumb_document) {
- out_string (s + 1);
- out_string ("text");
- }
- if (f->media_type == CODE_input_media_uploaded_audio) {
- out_int (60);
- out_string ("audio");
- }
-
- long long r;
- tglt_secure_random (&r, 8);
- out_long (r);
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_file_methods, 0, callback, callback_extra);
- } else {
- //struct tgl_message *M = talloc0 (sizeof (*M));
-
- out_int (CODE_messages_send_encrypted_file);
- out_int (CODE_input_encrypted_chat);
- out_int (tgl_get_peer_id (f->to_id));
- tgl_peer_t *P = tgl_peer_get (TLS, f->to_id);
- assert (P);
- out_long (P->encr_chat.access_hash);
- long long r;
- tglt_secure_random (&r, 8);
- out_long (r);
- encr_start ();
- if (P->encr_chat.layer <= 16) {
- out_int (CODE_decrypted_message_service_l16);
- } else {
- out_int (CODE_decrypted_message_layer);
- out_random (15 + 4 * (lrand48 () % 3));
- out_int (TGL_ENCRYPTED_LAYER);
- out_int (2 * P->encr_chat.in_seq_no + (P->encr_chat.admin_id != TLS->our_id));
- out_int (2 * P->encr_chat.out_seq_no + (P->encr_chat.admin_id == TLS->our_id));
- out_int (CODE_decrypted_message);
- }
- out_long (r);
- if (P->encr_chat.layer < 17) {
- out_random (15 + 4 * (lrand48 () % 3));
- } else {
- out_int (0);
- }
- out_string ("");
- int *save_ptr = packet_ptr;
- if (f->media_type == CODE_input_media_uploaded_photo) {
- out_int (CODE_decrypted_message_media_photo);
- //M->media.type = CODE_decrypted_message_media_photo;
- } else if (f->media_type == CODE_input_media_uploaded_video) {
- out_int (CODE_decrypted_message_media_video);
- //M->media.type = CODE_decrypted_message_media_video;
- } else if (f->media_type == CODE_input_media_uploaded_audio) {
- out_int (CODE_decrypted_message_media_audio);
- //M->media.type = CODE_decrypted_message_media_audio;
- } else if (f->media_type == CODE_input_media_uploaded_document) {
- out_int (CODE_decrypted_message_media_document);
- //M->media.type = CODE_decrypted_message_media_document;;
- } else {
- assert (0);
- }
- if (f->media_type != CODE_input_media_uploaded_audio) {
- out_cstring ((void *)thumb_file, thumb_file_size);
- out_int (90);
- out_int (90);
- }
- if (f->media_type == CODE_input_media_uploaded_video) {
- out_int (0);
- out_string ("video");
- }
- if (f->media_type == CODE_input_media_uploaded_document) {
- out_string (f->file_name);
- out_string ("text");
- }
- if (f->media_type == CODE_input_media_uploaded_audio) {
- out_int (60);
- out_string ("audio");
- }
- if (f->media_type == CODE_input_media_uploaded_video || f->media_type == CODE_input_media_uploaded_photo) {
- out_int (100);
- out_int (100);
- }
- out_int (f->size);
- out_cstring ((void *)f->key, 32);
- out_cstring ((void *)f->init_iv, 32);
-
- bl_do_create_message_media_encr_pending (TLS, r, TLS->our_id, tgl_get_peer_type (f->to_id), tgl_get_peer_id (f->to_id), time (0), 0, 0, save_ptr, packet_ptr - save_ptr);
-
- encr_finish (&P->encr_chat);
- if (f->size < (16 << 20)) {
- out_int (CODE_input_encrypted_file_uploaded);
- } else {
- out_int (CODE_input_encrypted_file_big_uploaded);
- }
- out_long (f->id);
- out_int (f->part_num);
- if (f->size < (16 << 20)) {
- out_string ("");
- }
-
- unsigned char md5[16];
- unsigned char str[64];
- memcpy (str, f->key, 32);
- memcpy (str + 32, f->init_iv, 32);
- MD5 (str, 64, md5);
- out_int ((*(int *)md5) ^ (*(int *)(md5 + 4)));
-
- tfree_secure (f->iv, 32);
- struct tgl_message *M = tgl_message_get (TLS, r);
- assert (M);
-
- //M->media.encr_photo.key = f->key;
- //M->media.encr_photo.iv = f->init_iv;
- //M->media.encr_photo.key_fingerprint = (*(int *)md5) ^ (*(int *)(md5 + 4));
- //M->media.encr_photo.size = f->size;
-
- //M->flags = FLAG_ENCRYPTED;
- //M->from_id = TGL_MK_USER (TLS->our_id);
- //M->to_id = f->to_id;
- //M->unread = 1;
- //M->message = tstrdup ("");
- //M->out = 1;
- //M->id = r;
- //M->date = time (0);
-
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_encr_file_methods, M, callback, callback_extra);
- }
- tfree_str (f->file_name);
- tfree (f, sizeof (*f));
- }
-}
-
-/*void send_file_thumb (struct send_file *f, void *callback, void *callback_extra) {
- clear_packet ();
- f->thumb_id = lrand48 () * (1ll << 32) + lrand48 ();
- out_int (CODE_upload_save_file_part);
- out_long (f->thumb_id);
- out_int (0);
- out_cstring ((void *)thumb_file, thumb_file_size);
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_file_part_methods, f, callback, callback_extra);
-}*/
-
-void _tgl_do_send_photo (struct tgl_state *TLS, enum tgl_message_media_type type, tgl_peer_id_t to_id, char *file_name, int avatar, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) {
- int fd = open (file_name, O_RDONLY);
- if (fd < 0) {
- vlogprintf (E_WARNING, "No such file '%s'\n", file_name);
- if (callback) {
- callback (TLS, callback_extra, 0, 0);
- }
- return;
- }
- struct stat buf;
- fstat (fd, &buf);
- long long size = buf.st_size;
- if (size <= 0) {
- vlogprintf (E_WARNING, "File has zero length\n");
- close (fd);
- if (callback) {
- callback (TLS, callback_extra, 0, 0);
- }
- return;
- }
- struct send_file *f = talloc0 (sizeof (*f));
- f->fd = fd;
- f->size = size;
- f->offset = 0;
- f->part_num = 0;
- f->avatar = avatar;
- int tmp = ((size + 2999) / 3000);
- f->part_size = (1 << 14);
- while (f->part_size < tmp) {
- f->part_size *= 2;
- }
-
- if (f->part_size > (512 << 10)) {
- close (fd);
- vlogprintf (E_WARNING, "Too big file. Maximal supported size is %d.\n", (512 << 10) * 1000);
- tfree (f, sizeof (*f));
- if (callback) {
- callback (TLS, callback_extra, 0, 0);
- }
- return;
- }
-
- tglt_secure_random (&f->id, 8);
- f->to_id = to_id;
- switch (type) {
- case tgl_message_media_photo:
- f->media_type = CODE_input_media_uploaded_photo;
- break;
- case tgl_message_media_video:
- f->media_type = CODE_input_media_uploaded_video;
- break;
- case tgl_message_media_audio:
- f->media_type = CODE_input_media_uploaded_audio;
- break;
- case tgl_message_media_document:
- f->media_type = CODE_input_media_uploaded_document;
- break;
- default:
- close (fd);
- vlogprintf (E_WARNING, "Unknown type %d.\n", type);
- tfree (f, sizeof (*f));
- if (callback) {
- callback (TLS, callback_extra, 0, 0);
- }
- return;
- }
- f->file_name = tstrdup (file_name);
- if (tgl_get_peer_type (f->to_id) == TGL_PEER_ENCR_CHAT) {
- f->encr = 1;
- f->iv = talloc (32);
- tglt_secure_random (f->iv, 32);
- f->init_iv = talloc (32);
- memcpy (f->init_iv, f->iv, 32);
- f->key = talloc (32);
- tglt_secure_random (f->key, 32);
- }
- /*if (f->media_type == CODE_input_media_uploaded_video && !f->encr) {
- f->media_type = CODE_input_media_uploaded_thumb_video;
- send_file_thumb (f);
- } else if (f->media_type == CODE_input_media_uploaded_document && !f->encr) {
- f->media_type = CODE_input_media_uploaded_thumb_document;
- send_file_thumb (f);
- } else {
- send_part (f);
- }*/
- send_part (TLS, f, callback, callback_extra);
-}
-
-void tgl_do_send_photo (struct tgl_state *TLS, enum tgl_message_media_type type, tgl_peer_id_t to_id, char *file_name, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) {
- _tgl_do_send_photo (TLS, type, to_id, file_name, 0, callback, callback_extra);
-}
-
-void tgl_do_set_chat_photo (struct tgl_state *TLS, tgl_peer_id_t chat_id, char *file_name, void (*callback)(struct tgl_state *TLS,void *callback_extra, int success, struct tgl_message *M), void *callback_extra) {
- assert (tgl_get_peer_type (chat_id) == TGL_PEER_CHAT);
- _tgl_do_send_photo (TLS, tgl_message_media_photo, chat_id, file_name, tgl_get_peer_id (chat_id), callback, callback_extra);
-}
-
-void tgl_do_set_profile_photo (struct tgl_state *TLS, char *file_name, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) {
- _tgl_do_send_photo (TLS, tgl_message_media_photo, TGL_MK_USER(TLS->our_id), file_name, -1, (void *)callback, callback_extra);
-}
-/* }}} */
-
-/* {{{ Profile name */
-
-int set_profile_name_on_answer (struct tgl_state *TLS, struct query *q) {
- struct tgl_user *U = tglf_fetch_alloc_user (TLS);
- if (q->callback) {
- ((void (*)(struct tgl_state *, void *, int, struct tgl_user *))q->callback) (TLS, q->callback_extra, 1, U);
- }
- return 0;
-}
-
-static struct query_methods set_profile_name_methods = {
- .on_answer = set_profile_name_on_answer,
- .type = TYPE_TO_PARAM(user)
-};
-
-void tgl_do_set_profile_name (struct tgl_state *TLS, char *first_name, char *last_name, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_user *U), void *callback_extra) {
- clear_packet ();
- out_int (CODE_account_update_profile);
- out_string (first_name);
- out_string (last_name);
-
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &set_profile_name_methods, 0, callback, callback_extra);
-}
-
-void tgl_do_set_username (struct tgl_state *TLS, char *name, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_user *U), void *callback_extra) {
- clear_packet ();
- out_int (CODE_account_update_username);
- out_string (name);
-
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &set_profile_name_methods, 0, callback, callback_extra);
-}
-/* }}} */
-
-/* {{{ Contacts search */
-
-int contact_search_on_answer (struct tgl_state *TLS, struct query *q) {
- assert (fetch_int () == CODE_contacts_found);
- assert (fetch_int () == CODE_vector);
- int n = fetch_int ();
- int i;
- for (i = 0; i < n; i++) {
- assert (fetch_int () == (int)CODE_contact_found);
- fetch_int ();
- }
- assert (fetch_int () == CODE_vector);
- n = fetch_int ();
-
- struct tgl_user **UL = talloc (sizeof (void *) * n);
- for (i = 0; i < n; i++) {
- UL[i] = tglf_fetch_alloc_user (TLS);
- }
-
- if (q->callback) {
- ((void (*)(struct tgl_state *,void *, int, int, struct tgl_user **))q->callback) (TLS, q->callback_extra, 1, n, UL);
- }
- tfree (UL, sizeof (void *) * n);
- return 0;
-}
-
-static struct query_methods contact_search_methods = {
- .on_answer = contact_search_on_answer,
- .type = TYPE_TO_PARAM(contacts_found)
-};
-
-void tgl_do_contact_search (struct tgl_state *TLS, char *name, int limit, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, int cnt, struct tgl_user *U[]), void *callback_extra) {
- clear_packet ();
- out_int (CODE_contacts_search);
- out_string (name);
- out_int (limit);
-
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &contact_search_methods, 0, callback, callback_extra);
-}
-/* }}} */
-
-/* {{{ Forward */
-static int fwd_msg_on_answer (struct tgl_state *TLS, struct query *q UU) {
- assert (fetch_int () == (int)CODE_messages_stated_message);
- struct tgl_message *M = tglf_fetch_alloc_message (TLS);
- assert (fetch_int () == CODE_vector);
- int n, i;
- n = fetch_int ();
- for (i = 0; i < n; i++) {
- tglf_fetch_alloc_chat (TLS);
- }
- assert (fetch_int () == CODE_vector);
- n = fetch_int ();
- for (i = 0; i < n; i++) {
- tglf_fetch_alloc_user (TLS);
- }
- //tglu_fetch_pts ();
- int pts = fetch_int ();
-
- int seq = fetch_int ();
- if (seq == TLS->seq + 1 && !(TLS->locks & TGL_LOCK_DIFF)) {
- bl_do_set_pts (TLS, pts);
- bl_do_msg_seq_update (TLS, M->id);
- } else {
- if (seq > TLS->seq + 1) {
- vlogprintf (E_NOTICE, "Hole in seq\n");
- tgl_do_get_difference (TLS, 0, 0, 0);
- }
- }
- //print_message (M);
- if (q->callback) {
- ((void (*)(struct tgl_state *, void *, int, struct tgl_message *))q->callback) (TLS, q->callback_extra, 1, M);
- }
- return 0;
-}
-
-static struct query_methods fwd_msg_methods = {
- .on_answer = fwd_msg_on_answer,
- .type = TYPE_TO_PARAM(messages_stated_message)
-};
-
-void tgl_do_forward_message (struct tgl_state *TLS, tgl_peer_id_t id, int n, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) {
- if (tgl_get_peer_type (id) == TGL_PEER_ENCR_CHAT) {
- vlogprintf (E_WARNING, "Can not forward messages from secret chat\n");
- if (callback) {
- callback (TLS, callback_extra, 0, 0);
- }
- return;
- }
- clear_packet ();
- out_int (CODE_messages_forward_message);
- out_peer_id (TLS, id);
- out_int (n);
- long long r;
- tglt_secure_random (&r, 8);
- out_long (r);
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &fwd_msg_methods, 0, callback, callback_extra);
-}
-
-void tgl_do_send_contact (struct tgl_state *TLS, tgl_peer_id_t id, const char *phone, int phone_len, const char *first_name, int first_name_len, const char *last_name, int last_name_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) {
- if (tgl_get_peer_type (id) == TGL_PEER_ENCR_CHAT) {
- if (callback) {
- callback (TLS, callback_extra, 0, 0);
- }
- return;
- }
- long long t;
- tglt_secure_random (&t, 8);
- vlogprintf (E_DEBUG, "t = %lld\n", t);
-
- clear_packet ();
- out_int (CODE_messages_send_media);
- out_peer_id (TLS, id);
- out_int (CODE_input_media_contact);
- out_cstring (phone, phone_len);
- out_cstring (first_name, first_name_len);
- out_cstring (last_name, last_name_len);
- out_long (t);
-
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &fwd_msg_methods, 0, callback, callback_extra);
-}
-
-void tgl_do_forward_media (struct tgl_state *TLS, tgl_peer_id_t id, int n, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) {
- if (tgl_get_peer_type (id) == TGL_PEER_ENCR_CHAT) {
- vlogprintf (E_WARNING, "Can not forward messages from secret chat\n");
- if (callback) {
- callback (TLS, callback_extra, 0, 0);
- }
- return;
- }
- struct tgl_message *M = tgl_message_get (TLS, n);
- if (!M) {
- vlogprintf (E_WARNING, "No such message\n");
- if (callback) {
- callback (TLS, callback_extra, 0, 0);
- }
- return;
- }
- if (M->flags & FLAG_ENCRYPTED) {
- vlogprintf (E_WARNING, "Can not forward media from encrypted message\n");
- if (callback) {
- callback (TLS, callback_extra, 0, 0);
- }
- return;
- }
- if (M->media.type != tgl_message_media_photo && M->media.type != tgl_message_media_video && M->media.type != tgl_message_media_audio && M->media.type != tgl_message_media_document) {
- vlogprintf (E_WARNING, "Can only forward photo/audio/video/document\n");
- if (callback) {
- callback (TLS, callback_extra, 0, 0);
- }
- return;
- }
- clear_packet ();
- out_int (CODE_messages_send_media);
- out_peer_id (TLS, id);
- switch (M->media.type) {
- case tgl_message_media_photo:
- out_int (CODE_input_media_photo);
- out_int (CODE_input_photo);
- out_long (M->media.photo.id);
- out_long (M->media.photo.access_hash);
- break;
- case tgl_message_media_video:
- out_int (CODE_input_media_video);
- out_int (CODE_input_video);
- out_long (M->media.video.id);
- out_long (M->media.video.access_hash);
- break;
- case tgl_message_media_audio:
- out_int (CODE_input_media_audio);
- out_int (CODE_input_audio);
- out_long (M->media.audio.id);
- out_long (M->media.audio.access_hash);
- break;
- case tgl_message_media_document:
- out_int (CODE_input_media_document);
- out_int (CODE_input_document);
- out_long (M->media.document.id);
- out_long (M->media.document.access_hash);
- break;
- default:
- assert (0);
- }
- long long r;
- tglt_secure_random (&r, 8);
- out_long (r);
-
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &fwd_msg_methods, 0, callback, callback_extra);
-}
-/* }}} */
-
-/* {{{ Send location */
-
-void tgl_do_send_location(struct tgl_state *TLS, tgl_peer_id_t id, double latitude, double longitude, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) {
- if (tgl_get_peer_type (id) == TGL_PEER_ENCR_CHAT) {
- clear_packet ();
- out_int (CODE_messages_send_encrypted);
- out_int (CODE_input_encrypted_chat);
- out_int (tgl_get_peer_id (id));
- tgl_peer_t *P = tgl_peer_get (TLS, id);
- assert (P);
- out_long (P->encr_chat.access_hash);
-
- long long r;
- tglt_secure_random (&r, 8);
- out_long (r);
- encr_start ();
- if (P->encr_chat.layer <= 16) {
- out_int (CODE_decrypted_message_service_l16);
- } else {
- out_int (CODE_decrypted_message_layer);
- out_random (15 + 4 * (lrand48 () % 3));
- out_int (TGL_ENCRYPTED_LAYER);
- out_int (2 * P->encr_chat.in_seq_no + (P->encr_chat.admin_id != TLS->our_id));
- out_int (2 * P->encr_chat.out_seq_no + (P->encr_chat.admin_id == TLS->our_id));
- out_int (CODE_decrypted_message);
- }
- out_long (r);
- if (P->encr_chat.layer < 17) {
- out_random (15 + 4 * (lrand48 () % 3));
- } else {
- out_int (0);
- }
- out_string ("");
- int *save_ptr = packet_ptr;
- out_int (CODE_decrypted_message_media_geo_point);
- out_double (latitude);
- out_double (longitude);
-
- bl_do_create_message_media_encr_pending (TLS, r, TLS->our_id, tgl_get_peer_type (id), tgl_get_peer_id (id), time (0), 0, 0, save_ptr, packet_ptr - save_ptr);
-
- encr_finish (&P->encr_chat);
-
- struct tgl_message *M = tgl_message_get (TLS, r);
- assert (M);
-
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_send_encr_methods, M, callback, callback_extra);
- } else {
- long long t;
- tglt_secure_random (&t, 8);
- vlogprintf (E_DEBUG, "t = %lld\n", t);
-
- clear_packet ();
- out_int (CODE_messages_send_media);
- out_peer_id (TLS, id);
- out_int (CODE_input_media_geo_point);
- out_int (CODE_input_geo_point);
- out_double (latitude);
- out_double (longitude);
- out_long (t);
-
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &fwd_msg_methods, 0, callback, callback_extra);
- }
-}
-/* }}} */
-
-/* {{{ Rename chat */
-static int rename_chat_on_answer (struct tgl_state *TLS, struct query *q UU) {
- assert (fetch_int () == (int)CODE_messages_stated_message);
- struct tgl_message *M = tglf_fetch_alloc_message (TLS);
- assert (fetch_int () == CODE_vector);
- int n, i;
- n = fetch_int ();
- for (i = 0; i < n; i++) {
- tglf_fetch_alloc_chat (TLS);
- }
- assert (fetch_int () == CODE_vector);
- n = fetch_int ();
- for (i = 0; i < n; i++) {
- tglf_fetch_alloc_user (TLS);
- }
- //tglu_fetch_pts ();
- int pts = fetch_int ();
-
- int seq = fetch_int ();
- if (seq == TLS->seq + 1 && !(TLS->locks & TGL_LOCK_DIFF)) {
- bl_do_set_pts (TLS, pts);
- bl_do_msg_seq_update (TLS, M->id);
- } else {
- if (seq > TLS->seq + 1) {
- vlogprintf (E_NOTICE, "Hole in seq\n");
- tgl_do_get_difference (TLS, 0, 0, 0);
- }
- }
- //print_message (M);
- if (q->callback) {
- ((void (*)(struct tgl_state *, void *, int, struct tgl_message *))q->callback) (TLS, q->callback_extra, 1, M);
- }
- return 0;
-}
-
-static struct query_methods rename_chat_methods = {
- .on_answer = rename_chat_on_answer,
- .type = TYPE_TO_PARAM(messages_stated_message)
-};
-
-void tgl_do_rename_chat (struct tgl_state *TLS, tgl_peer_id_t id, char *name UU, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) {
- clear_packet ();
- out_int (CODE_messages_edit_chat_title);
- assert (tgl_get_peer_type (id) == TGL_PEER_CHAT);
- out_int (tgl_get_peer_id (id));
- out_string (name);
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &rename_chat_methods, 0, callback, callback_extra);
-}
-/* }}} */
-
-/* {{{ Chat info */
-/*void print_chat_info (struct tgl_chat *C) {
- tgl_peer_t *U = (void *)C;
- print_start ();
- push_color (COLOR_YELLOW);
- printf ("Chat ");
- print_chat_name (U->id, U);
- printf (" members:\n");
- int i;
- for (i = 0; i < C->user_list_size; i++) {
- printf ("\t\t");
- print_user_name (TGL_MK_USER (C->user_list[i].user_id), tgl_peer_get (TLS, TGL_MK_USER (C->user_list[i].user_id)));
- printf (" invited by ");
- print_user_name (TGL_MK_USER (C->user_list[i].inviter_id), tgl_peer_get (TLS, TGL_MK_USER (C->user_list[i].inviter_id)));
- printf (" at ");
- print_date_full (C->user_list[i].date);
- if (C->user_list[i].user_id == C->admin_id) {
- printf (" admin");
- }
- printf ("\n");
- }
- pop_color ();
- print_end ();
-}*/
-
-static int chat_info_on_answer (struct tgl_state *TLS, struct query *q UU) {
- struct tgl_chat *C = tglf_fetch_alloc_chat_full (TLS);
- //print_chat_info (C);
- if (q->callback) {
- ((void (*)(struct tgl_state *, void *, int, struct tgl_chat *))q->callback) (TLS, q->callback_extra, 1, C);
- }
- return 0;
-}
-
-static struct query_methods chat_info_methods = {
- .on_answer = chat_info_on_answer,
- .type = TYPE_TO_PARAM(messages_chat_full)
-};
-
-void tgl_do_get_chat_info (struct tgl_state *TLS, tgl_peer_id_t id, int offline_mode, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_chat *C), void *callback_extra) {
- if (offline_mode) {
- tgl_peer_t *C = tgl_peer_get (TLS, id);
- if (!C) {
- vlogprintf (E_WARNING, "No such chat\n");
- if (callback) {
- callback (TLS, callback_extra, 0, 0);
- }
- } else {
- //print_chat_info (&C->chat);
- if (callback) {
- callback (TLS, callback_extra, 1, &C->chat);
- }
- }
- return;
- }
- clear_packet ();
- out_int (CODE_messages_get_full_chat);
- assert (tgl_get_peer_type (id) == TGL_PEER_CHAT);
- out_int (tgl_get_peer_id (id));
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &chat_info_methods, 0, callback, callback_extra);
-}
-/* }}} */
-
-/* {{{ User info */
-
-/*void print_user_info (struct tgl_user *U) {
- tgl_peer_t *C = (void *)U;
- print_start ();
- push_color (COLOR_YELLOW);
- printf ("User ");
- print_user_name (U->id, C);
- printf (":\n");
- printf ("\treal name: %s %s\n", U->real_first_name, U->real_last_name);
- printf ("\tphone: %s\n", U->phone);
- if (U->status.online > 0) {
- printf ("\tonline\n");
- } else {
- printf ("\toffline (was online ");
- print_date_full (U->status.when);
- printf (")\n");
- }
- pop_color ();
- print_end ();
-}*/
-
-static int user_info_on_answer (struct tgl_state *TLS, struct query *q UU) {
- struct tgl_user *U = tglf_fetch_alloc_user_full (TLS);
- if (q->callback) {
- ((void (*)(struct tgl_state *, void *, int, struct tgl_user *))q->callback) (TLS, q->callback_extra, 1, U);
- }
- return 0;
-}
-
-static struct query_methods user_info_methods = {
- .on_answer = user_info_on_answer,
- .type = TYPE_TO_PARAM(user_full)
-};
-
-void tgl_do_get_user_info (struct tgl_state *TLS, tgl_peer_id_t id, int offline_mode, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_user *U), void *callback_extra) {
- if (offline_mode) {
- tgl_peer_t *C = tgl_peer_get (TLS, id);
- if (!C) {
- vlogprintf (E_WARNING, "No such user\n");
- if (callback) {
- callback (TLS, callback_extra, 0, 0);
- }
- } else {
- if (callback) {
- callback (TLS, callback_extra, 1, &C->user);
- }
- }
- return;
- }
- clear_packet ();
- out_int (CODE_users_get_full_user);
- assert (tgl_get_peer_type (id) == TGL_PEER_USER);
- tgl_peer_t *U = tgl_peer_get (TLS, id);
- if (U && U->user.access_hash) {
- out_int (CODE_input_user_foreign);
- out_int (tgl_get_peer_id (id));
- out_long (U->user.access_hash);
- } else {
- out_int (CODE_input_user_contact);
- out_int (tgl_get_peer_id (id));
- }
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &user_info_methods, 0, callback, callback_extra);
-}
-/* }}} */
-
-/* {{{ Get user info silently */
-/*int user_list_info_silent_on_answer (struct query *q UU) {
- assert (fetch_int () == CODE_vector);
- int n = fetch_int ();
- int i;
- for (i = 0; i < n; i++) {
- tglf_fetch_alloc_user (TLS);
- }
- return 0;
-}
-
-struct query_methods user_list_info_silent_methods = {
- .on_answer = user_list_info_silent_on_answer,
- .type = TYPE_TO_PARAM_1(vector, TYPE_TO_PARAM(user))
-};
-
-void tgl_do_get_user_list_info_silent (int num, int *list) {
- clear_packet ();
- out_int (CODE_users_get_users);
- out_int (CODE_vector);
- out_int (num);
- int i;
- for (i = 0; i < num; i++) {
- out_int (CODE_input_user_contact);
- out_int (list[i]);
- //out_long (0);
- }
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &user_list_info_silent_methods, 0);
-}*/
-/* }}} */
-
-/* {{{ Load photo/video */
-struct download {
- int offset;
- int size;
- long long volume;
- long long secret;
- long long access_hash;
- int local_id;
- int dc;
- int next;
- int fd;
- char *name;
- long long id;
- unsigned char *iv;
- unsigned char *key;
- int type;
- int refcnt;
-};
-
-
-static void end_load (struct tgl_state *TLS, struct download *D, void *callback, void *callback_extra) {
- TLS->cur_downloading_bytes -= D->size;
- TLS->cur_downloaded_bytes -= D->size;
- //update_prompt ();
- close (D->fd);
- /*if (D->next == 1) {
- logprintf ("Done: %s\n", D->name);
- } else if (D->next == 2) {
- static char buf[PATH_MAX];
- if (tsnprintf (buf, sizeof (buf), OPEN_BIN, D->name) >= (int) sizeof (buf)) {
- logprintf ("Open image command buffer overflow\n");
- } else {
- int x = system (buf);
- if (x < 0) {
- logprintf ("Can not open image viewer: %m\n");
- logprintf ("Image is at %s\n", D->name);
- }
- }
- }*/
-
- if (callback) {
- ((void (*)(struct tgl_state *, void *, int, char *))callback) (TLS, callback_extra, 1, D->name);
- }
-
- if (D->iv) {
- tfree_secure (D->iv, 32);
- }
- tfree_str (D->name);
- tfree (D, sizeof (*D));
-}
-
-static void load_next_part (struct tgl_state *TLS, struct download *D, void *callback, void *callback_extra);
-static int download_on_answer (struct tgl_state *TLS, struct query *q) {
- assert (fetch_int () == (int)CODE_upload_file);
- unsigned x = fetch_int ();
- assert (x);
- struct download *D = q->extra;
- if (D->fd == -1) {
- D->fd = open (D->name, O_CREAT | O_WRONLY, 0640);
- if (D->fd < 0) {
- vlogprintf (E_ERROR, "Can not open for writing: %m\n");
- assert (D->fd >= 0);
- }
- }
- fetch_int (); // mtime
- int len = prefetch_strlen ();
- assert (len >= 0);
- TLS->cur_downloaded_bytes += len;
- //update_prompt ();
- if (D->iv) {
- unsigned char *ptr = (void *)fetch_str (len);
- assert (!(len & 15));
- AES_KEY aes_key;
- AES_set_decrypt_key (D->key, 256, &aes_key);
- AES_ige_encrypt (ptr, ptr, len, &aes_key, D->iv, 0);
- memset (&aes_key, 0, sizeof (aes_key));
- if (len > D->size - D->offset) {
- len = D->size - D->offset;
- }
- assert (write (D->fd, ptr, len) == len);
- } else {
- assert (write (D->fd, fetch_str (len), len) == len);
- }
- D->offset += len;
- D->refcnt --;
- if (D->offset < D->size) {
- load_next_part (TLS, D, q->callback, q->callback_extra);
- return 0;
- } else {
- if (!D->refcnt) {
- end_load (TLS, D, q->callback, q->callback_extra);
- }
- return 0;
- }
-}
-
-static struct query_methods download_methods = {
- .on_answer = download_on_answer,
- .type = TYPE_TO_PARAM(upload_file)
-};
-
-static void load_next_part (struct tgl_state *TLS, struct download *D, void *callback, void *callback_extra) {
- if (!D->offset) {
- static char buf[PATH_MAX];
- int l;
- if (!D->id) {
- l = tsnprintf (buf, sizeof (buf), "%s/download_%lld_%d.jpg", TLS->downloads_directory, D->volume, D->local_id);
- } else {
- l = tsnprintf (buf, sizeof (buf), "%s/download_%lld", TLS->downloads_directory, D->id);
- }
- if (l >= (int) sizeof (buf)) {
- vlogprintf (E_ERROR, "Download filename is too long");
- exit (1);
- }
- D->name = tstrdup (buf);
- struct stat st;
- if (stat (buf, &st) >= 0) {
- D->offset = st.st_size;
- if (D->offset >= D->size) {
- TLS->cur_downloading_bytes += D->size;
- TLS->cur_downloaded_bytes += D->offset;
- vlogprintf (E_NOTICE, "Already downloaded\n");
- end_load (TLS, D, callback, callback_extra);
- return;
- }
- }
-
- TLS->cur_downloading_bytes += D->size;
- TLS->cur_downloaded_bytes += D->offset;
- //update_prompt ();
- }
- D->refcnt ++;
- clear_packet ();
- out_int (CODE_upload_get_file);
- if (!D->id) {
- out_int (CODE_input_file_location);
- out_long (D->volume);
- out_int (D->local_id);
- out_long (D->secret);
- } else {
- if (D->iv) {
- out_int (CODE_input_encrypted_file_location);
- } else {
- out_int (D->type);
- }
- out_long (D->id);
- out_long (D->access_hash);
- }
- out_int (D->offset);
- out_int (1 << 14);
- tglq_send_query (TLS, TLS->DC_list[D->dc], packet_ptr - packet_buffer, packet_buffer, &download_methods, D, callback, callback_extra);
- //tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &download_methods, D);
-}
-
-void tgl_do_load_photo_size (struct tgl_state *TLS, struct tgl_photo_size *P, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, char *filename), void *callback_extra) {
- if (!P->loc.dc) {
- vlogprintf (E_WARNING, "Bad video thumb\n");
- if (callback) {
- callback (TLS, callback_extra, 0, 0);
- }
- return;
- }
-
- assert (P);
- struct download *D = talloc0 (sizeof (*D));
- D->id = 0;
- D->offset = 0;
- D->size = P->size;
- D->volume = P->loc.volume;
- D->dc = P->loc.dc;
- D->local_id = P->loc.local_id;
- D->secret = P->loc.secret;
- D->name = 0;
- D->fd = -1;
- load_next_part (TLS, D, callback, callback_extra);
-}
-
-void tgl_do_load_photo (struct tgl_state *TLS, struct tgl_photo *photo, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, char *filename), void *callback_extra) {
- if (!photo->sizes_num) {
- vlogprintf (E_WARNING, "No sizes\n");
- if (callback) {
- callback (TLS, callback_extra, 0, 0);
- }
- return;
- }
- int max = -1;
- int maxi = 0;
- int i;
- for (i = 0; i < photo->sizes_num; i++) {
- if (photo->sizes[i].w + photo->sizes[i].h > max) {
- max = photo->sizes[i].w + photo->sizes[i].h;
- maxi = i;
- }
- }
- tgl_do_load_photo_size (TLS, &photo->sizes[maxi], callback, callback_extra);
-}
-
-void tgl_do_load_video_thumb (struct tgl_state *TLS, struct tgl_video *video, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, char *filename), void *callback_extra) {
- tgl_do_load_photo_size (TLS, &video->thumb, callback, callback_extra);
-}
-
-void tgl_do_load_document_thumb (struct tgl_state *TLS, struct tgl_document *video, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, char *filename), void *callback_extra) {
- tgl_do_load_photo_size (TLS, &video->thumb, callback, callback_extra);
-}
-
-void tgl_do_load_video (struct tgl_state *TLS, struct tgl_video *V, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, char *filename), void *callback_extra) {
- assert (V);
- struct download *D = talloc0 (sizeof (*D));
- D->offset = 0;
- D->size = V->size;
- D->id = V->id;
- D->access_hash = V->access_hash;
- D->dc = V->dc_id;
- D->name = 0;
- D->fd = -1;
- D->type = CODE_input_video_file_location;
- load_next_part (TLS, D, callback, callback_extra);
-}
-
-void tgl_do_load_audio (struct tgl_state *TLS, struct tgl_audio *V, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, char *filename), void *callback_extra) {
- assert (V);
- struct download *D = talloc0 (sizeof (*D));
- D->offset = 0;
- D->size = V->size;
- D->id = V->id;
- D->access_hash = V->access_hash;
- D->dc = V->dc_id;
- D->name = 0;
- D->fd = -1;
- D->type = CODE_input_audio_file_location;
- load_next_part (TLS, D, callback, callback_extra);
-}
-
-void tgl_do_load_document (struct tgl_state *TLS, struct tgl_document *V, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, char *filename), void *callback_extra) {
- assert (V);
- struct download *D = talloc0 (sizeof (*D));
- D->offset = 0;
- D->size = V->size;
- D->id = V->id;
- D->access_hash = V->access_hash;
- D->dc = V->dc_id;
- D->name = 0;
- D->fd = -1;
- D->type = CODE_input_document_file_location;
- load_next_part (TLS, D, callback, callback_extra);
-}
-
-void tgl_do_load_encr_video (struct tgl_state *TLS, struct tgl_encr_video *V, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, char *filename), void *callback_extra) {
- assert (V);
- struct download *D = talloc0 (sizeof (*D));
- D->offset = 0;
- D->size = V->size;
- D->id = V->id;
- D->access_hash = V->access_hash;
- D->dc = V->dc_id;
- D->name = 0;
- D->fd = -1;
- D->key = V->key;
- D->iv = talloc (32);
- memcpy (D->iv, V->iv, 32);
- load_next_part (TLS, D, callback, callback_extra);
-
- unsigned char md5[16];
- unsigned char str[64];
- memcpy (str, V->key, 32);
- memcpy (str + 32, V->iv, 32);
- MD5 (str, 64, md5);
- assert (V->key_fingerprint == ((*(int *)md5) ^ (*(int *)(md5 + 4))));
-}
-/* }}} */
-
-/* {{{ Export auth */
-
-static int import_auth_on_answer (struct tgl_state *TLS, struct query *q UU) {
- assert (fetch_int () == (int)CODE_auth_authorization);
- fetch_int (); // expires
- tglf_fetch_alloc_user (TLS);
-
- bl_do_dc_signed (TLS, ((struct tgl_dc *)q->extra)->id);
-
- if (q->callback) {
- ((void (*)(struct tgl_state *, void *, int))q->callback) (TLS, q->callback_extra, 1);
- }
- return 0;
-}
-
-static struct query_methods import_auth_methods = {
- .on_answer = import_auth_on_answer,
- .on_error = fail_on_error,
- .type = TYPE_TO_PARAM(auth_authorization)
-};
-
-static int export_auth_on_answer (struct tgl_state *TLS, struct query *q UU) {
- assert (fetch_int () == (int)CODE_auth_exported_authorization);
- bl_do_set_our_id (TLS, fetch_int ());
- int l = prefetch_strlen ();
- char *s = talloc (l);
- memcpy (s, fetch_str (l), l);
-
- clear_packet ();
- tgl_do_insert_header ();
- out_int (CODE_auth_import_authorization);
- out_int (TLS->our_id);
- out_cstring (s, l);
- tglq_send_query (TLS, q->extra, packet_ptr - packet_buffer, packet_buffer, &import_auth_methods, q->extra, q->callback, q->callback_extra);
- tfree (s, l);
- return 0;
-}
-
-static struct query_methods export_auth_methods = {
- .on_answer = export_auth_on_answer,
- .on_error = fail_on_error,
- .type = TYPE_TO_PARAM(auth_exported_authorization)
-};
-
-void tgl_do_export_auth (struct tgl_state *TLS, int num, void (*callback) (struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) {
- clear_packet ();
- out_int (CODE_auth_export_authorization);
- out_int (num);
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &export_auth_methods, TLS->DC_list[num], callback, callback_extra);
-}
-/* }}} */
-
-/* {{{ Add contact */
-static int add_contact_on_answer (struct tgl_state *TLS, struct query *q UU) {
- assert (fetch_int () == (int)CODE_contacts_imported_contacts);
- assert (fetch_int () == CODE_vector);
- int n = fetch_int ();
- if (n > 0) {
- vlogprintf (E_DEBUG, "Added successfully");
- } else {
- vlogprintf (E_DEBUG, "Not added");
- }
- int i;
- for (i = 0; i < n ; i++) {
- assert (fetch_int () == (int)CODE_imported_contact);
- fetch_int (); // uid
- fetch_long (); // client_id
- }
- assert (fetch_int () == CODE_vector);
- n = fetch_int ();
- for (i = 0; i < n; i++) {
- long long id = fetch_long ();
- vlogprintf (E_NOTICE, "contact #%lld not added. Please retry\n", id);
- }
- assert (fetch_int () == CODE_vector);
- n = fetch_int ();
-
- struct tgl_user **UL = talloc (n * sizeof (void *));
- for (i = 0; i < n; i++) {
- UL[i] = tglf_fetch_alloc_user (TLS);
- }
-
- if (q->callback) {
- ((void (*)(struct tgl_state *, void *, int, int, struct tgl_user **))q->callback) (TLS, q->callback_extra, 1, n, UL);
- }
- tfree (UL, n * sizeof (void *));
- return 0;
-}
-
-static struct query_methods add_contact_methods = {
- .on_answer = add_contact_on_answer,
- .type = TYPE_TO_PARAM(contacts_imported_contacts)
-};
-
-void tgl_do_add_contact (struct tgl_state *TLS, 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 (*callback)(struct tgl_state *TLS,void *callback_extra, int success, int size, struct tgl_user *users[]), void *callback_extra) {
- clear_packet ();
- out_int (CODE_contacts_import_contacts);
- out_int (CODE_vector);
- out_int (1);
- out_int (CODE_input_phone_contact);
- long long r;
- tglt_secure_random (&r, 8);
- out_long (r);
- out_cstring (phone, phone_len);
- out_cstring (first_name, first_name_len);
- out_cstring (last_name, last_name_len);
- out_int (force ? CODE_bool_true : CODE_bool_false);
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &add_contact_methods, 0, callback, callback_extra);
-}
-/* }}} */
-
-/* {{{ Add contact */
-static int del_contact_on_answer (struct tgl_state *TLS, struct query *q UU) {
- assert (skip_type_contacts_link (TYPE_TO_PARAM(contacts_link)) >= 0);
-
- if (q->callback) {
- ((void (*)(struct tgl_state *, void *, int))q->callback) (TLS, q->callback_extra, 1);
- }
- return 0;
-}
-
-static struct query_methods del_contact_methods = {
- .on_answer = del_contact_on_answer,
- .type = TYPE_TO_PARAM(contacts_link)
-};
-
-void tgl_do_del_contact (struct tgl_state *TLS, tgl_peer_id_t id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) {
- if (tgl_get_peer_type (id) != TGL_PEER_USER) {
- if (callback) {
- callback (TLS, callback_extra, 0);
- }
- return;
- }
- clear_packet ();
- out_int (CODE_contacts_delete_contact);
-
- tgl_peer_t *U = tgl_peer_get (TLS, id);
- if (U && U->user.access_hash) {
- out_int (CODE_input_user_foreign);
- out_int (tgl_get_peer_id (id));
- out_long (U->user.access_hash);
- } else {
- out_int (CODE_input_user_contact);
- out_int (tgl_get_peer_id (id));
- }
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &del_contact_methods, 0, callback, callback_extra);
-}
- /* }}} */
-
-/* {{{ Msg search */
-void _tgl_do_msg_search (struct tgl_state *TLS, tgl_peer_id_t id, int from, int to, int limit, int offset, int max_id, char *s, int list_offset, int list_size, struct tgl_message **list, void (*callback)(struct tgl_state *TLS,void *callback_extra, int success, int size, struct tgl_message *list[]), void *callback_extra);
-static int msg_search_on_answer (struct tgl_state *TLS, struct query *q UU) {
- int count = -1;
- int i;
- int x = fetch_int ();
- assert (x == (int)CODE_messages_messages_slice || x == (int)CODE_messages_messages);
- if (x == (int)CODE_messages_messages_slice) {
- count = fetch_int ();
- //fetch_int ();
- }
- assert (fetch_int () == CODE_vector);
- void **T = q->extra;
- struct tgl_message **ML = T[0];
- int list_offset = (long)T[1];
- int list_size = (long)T[2];
- tgl_peer_id_t id = tgl_set_peer_id ((long)T[4], (long)T[3]);
- int limit = (long)T[5];
- int offset = (long)T[6];
- int from = (long)T[7];
- int to = (long)T[8];
- char *s = T[9];
- tfree (T, sizeof (void *) * 10);
-
- int n = fetch_int ();
-
- if (list_size - list_offset < n) {
- int new_list_size = 2 * list_size;
- if (new_list_size - list_offset < n) {
- new_list_size = n + list_offset;
- }
- ML = trealloc (ML, list_size * sizeof (void *), new_list_size * sizeof (void *));
- assert (ML);
- list_size = new_list_size;
- }
- //struct tgl_message **ML = talloc (sizeof (void *) * n);
- for (i = 0; i < n; i++) {
- ML[i + list_offset] = tglf_fetch_alloc_message (TLS);
- }
- list_offset += n;
- offset += n;
- limit -= n;
- if (count >= 0 && limit + offset >= count) {
- limit = count - offset;
- if (limit < 0) { limit = 0; }
- }
- assert (limit >= 0);
-
- assert (fetch_int () == CODE_vector);
- n = fetch_int ();
- for (i = 0; i < n; i++) {
- tglf_fetch_alloc_chat (TLS);
- }
- assert (fetch_int () == CODE_vector);
- n = fetch_int ();
- for (i = 0; i < n; i++) {
- tglf_fetch_alloc_user (TLS);
- }
-
-
- if (limit <= 0 || x == (int)CODE_messages_messages) {
- if (q->callback) {
- ((void (*)(struct tgl_state *, void *, int, int, struct tgl_message **))q->callback) (TLS, q->callback_extra, 1, list_offset, ML);
- }
-
- tfree_str (s);
- tfree (ML, sizeof (void *) * list_size);
- } else {
- _tgl_do_msg_search (TLS, id, from, to, limit, 0, ML[list_offset - 1]->id, s, list_offset, list_size, ML, q->callback, q->callback_extra);
- }
- return 0;
-}
-
-static struct query_methods msg_search_methods = {
- .on_answer = msg_search_on_answer,
- .type = TYPE_TO_PARAM(messages_messages)
-};
-
-void _tgl_do_msg_search (struct tgl_state *TLS, tgl_peer_id_t id, int from, int to, int limit, int offset, int max_id, char *s, int list_offset, int list_size, struct tgl_message **list, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, int size, struct tgl_message *list[]), void *callback_extra) {
- if (tgl_get_peer_type (id) == TGL_PEER_ENCR_CHAT) {
- vlogprintf (E_WARNING, "Can not search in secure chat\n");
- if (callback) {
- callback (TLS, callback_extra, 0, 0, 0);
- }
- return;
- }
- clear_packet ();
- out_int (CODE_messages_search);
- if (tgl_get_peer_type (id) == TGL_PEER_UNKNOWN) {
- out_int (CODE_input_peer_empty);
- } else {
- out_peer_id (TLS, id);
- }
- void **T = talloc (sizeof (void *) * 10);
- T[0] = list;
- T[1] = (void *)(long)list_offset;
- T[2] = (void *)(long)list_size;
- T[3] = (void *)(long)tgl_get_peer_id (id);
- T[4] = (void *)(long)tgl_get_peer_type (id);
- T[5] = (void *)(long)limit;
- T[6] = (void *)(long)offset;
- T[7] = (void *)(long)from;
- T[8] = (void *)(long)to;
- T[9] = s;
-
- out_string (s);
- out_int (CODE_input_messages_filter_empty);
- out_int (from);
- out_int (to);
- out_int (offset); // offset
- out_int (max_id); // max_id
- out_int (limit);
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_search_methods, T, callback, callback_extra);
-}
-
-void tgl_do_msg_search (struct tgl_state *TLS, tgl_peer_id_t id, int from, int to, int limit, int offset, const char *s, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, int size, struct tgl_message *list[]), void *callback_extra) {
- _tgl_do_msg_search (TLS, id, from, to, limit, offset, 0, tstrdup (s), 0, 0, 0, callback, callback_extra);
-}
-/* }}} */
-
-/* {{{ Contacts search */
-static int contacts_search_on_answer (struct tgl_state *TLS, struct query *q UU) {
- assert (fetch_int () == CODE_contacts_found);
- assert (fetch_int () == CODE_vector);
- int n = fetch_int ();
- int i;
- for (i = 0; i < n; i++) {
- assert (fetch_int () == (int)CODE_contact_found);
- fetch_int ();
- }
- assert (fetch_int () == CODE_vector);
- n = fetch_int ();
-
- struct tgl_user **UL = talloc (sizeof (void *) * n);
- for (i = 0; i < n; i++) {
- UL[i] = tglf_fetch_alloc_user (TLS);
- }
- /*print_start ();
- push_color (COLOR_YELLOW);
- for (i = 0; i < n; i++) {
- struct tgl_user *U = tglf_fetch_alloc_user (TLS);
- printf ("User ");
- push_color (COLOR_RED);
- printf ("%s %s", U->first_name, U->last_name);
- pop_color ();
- printf (". Phone %s\n", U->phone);
- }
- pop_color ();
- print_end ();*/
- if (q->callback) {
- ((void (*)(struct tgl_state *, void *, int, int, struct tgl_user **))q->callback) (TLS, q->callback_extra, 1, n, UL);
- }
- tfree (UL, sizeof (void *) * n);
- return 0;
-}
-
-static struct query_methods contacts_search_methods = {
- .on_answer = contacts_search_on_answer,
- .type = TYPE_TO_PARAM(contacts_found)
-};
-
-void tgl_do_contacts_search (struct tgl_state *TLS, int limit, const char *s, void (*callback) (struct tgl_state *, void *callback_extra, int success, int size, struct tgl_user *users[]), void *callback_extra) {
- clear_packet ();
- out_int (CODE_contacts_search);
- out_string (s);
- out_int (limit);
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &contacts_search_methods, 0, callback, callback_extra);
-}
-/* }}} */
-
-/* {{{ Encr accept */
-static int send_encr_accept_on_answer (struct tgl_state *TLS, struct query *q UU) {
- struct tgl_secret_chat *E = tglf_fetch_alloc_encrypted_chat (TLS);
-
- /*if (E->state == sc_ok) {
- print_start ();
- push_color (COLOR_YELLOW);
- printf ("Encrypted connection with ");
- print_encr_chat_name (E->id, (void *)E);
- printf (" established\n");
- pop_color ();
- print_end ();
- } else {
- print_start ();
- push_color (COLOR_YELLOW);
- printf ("Encrypted connection with ");
- print_encr_chat_name (E->id, (void *)E);
- printf (" failed\n");
- pop_color ();
- print_end ();
- }*/
-
- if (E->state == sc_ok) {
- tgl_do_send_encr_chat_layer (TLS, E);
- }
- if (q->callback) {
- ((void (*)(struct tgl_state *, void *, int, struct tgl_secret_chat *))q->callback) (TLS, q->callback_extra, E->state == sc_ok, E);
- }
- return 0;
-}
-
-static int send_encr_request_on_answer (struct tgl_state *TLS, struct query *q UU) {
- struct tgl_secret_chat *E = tglf_fetch_alloc_encrypted_chat (TLS);
- /*if (E->state == sc_deleted) {
- print_start ();
- push_color (COLOR_YELLOW);
- printf ("Encrypted connection with ");
- print_encr_chat_name (E->id, (void *)E);
- printf (" can not be established\n");
- pop_color ();
- print_end ();
- } else {
- print_start ();
- push_color (COLOR_YELLOW);
- printf ("Establishing connection with ");
- print_encr_chat_name (E->id, (void *)E);
- printf ("\n");
- pop_color ();
- print_end ();
-
- assert (E->state == sc_waiting);
- }*/
-
- if (q->callback) {
- ((void (*)(struct tgl_state *, void *, int, struct tgl_secret_chat *))q->callback) (TLS, q->callback_extra, E->state != sc_deleted, E);
- }
- return 0;
-}
-
-static struct query_methods send_encr_accept_methods = {
- .on_answer = send_encr_accept_on_answer,
- .type = TYPE_TO_PARAM(encrypted_chat)
-};
-
-static struct query_methods send_encr_request_methods = {
- .on_answer = send_encr_request_on_answer,
- .type = TYPE_TO_PARAM(encrypted_chat)
-};
-
-//int encr_root;
-//unsigned char *encr_prime;
-//int encr_param_version;
-//static BN_CTX *ctx;
-
-void tgl_do_send_accept_encr_chat (struct tgl_state *TLS, struct tgl_secret_chat *E, unsigned char *random, void (*callback)(struct tgl_state *TLS,void *callback_extra, int success, struct tgl_secret_chat *E), void *callback_extra) {
- int i;
- int ok = 0;
- for (i = 0; i < 64; i++) {
- if (E->key[i]) {
- ok = 1;
- break;
- }
- }
- if (ok) {
- if (callback) {
- callback (TLS, callback_extra, 1, E);
- }
- return;
- } // Already generated key for this chat
- assert (E->g_key);
- assert (TLS->BN_ctx);
- unsigned char random_here[256];
- tglt_secure_random (random_here, 256);
- for (i = 0; i < 256; i++) {
- random[i] ^= random_here[i];
- }
- BIGNUM *b = BN_bin2bn (random, 256, 0);
- ensure_ptr (b);
- BIGNUM *g_a = BN_bin2bn (E->g_key, 256, 0);
- ensure_ptr (g_a);
- assert (tglmp_check_g (TLS, TLS->encr_prime, g_a) >= 0);
- //if (!ctx) {
- // ctx = BN_CTX_new ();
- // ensure_ptr (ctx);
- //}
- BIGNUM *p = BN_bin2bn (TLS->encr_prime, 256, 0);
- ensure_ptr (p);
- BIGNUM *r = BN_new ();
- ensure_ptr (r);
- ensure (BN_mod_exp (r, g_a, b, p, TLS->BN_ctx));
- static unsigned char kk[256];
- memset (kk, 0, sizeof (kk));
- BN_bn2bin (r, kk + (256 - BN_num_bytes (r)));
- for (i = 0; i < 256; i++) {
- kk[i] ^= E->nonce[i];
- }
- static unsigned char sha_buffer[20];
- sha1 (kk, 256, sha_buffer);
-
- bl_do_encr_chat_set_key (TLS, E, kk, *(long long *)(sha_buffer + 12));
-
- clear_packet ();
- out_int (CODE_messages_accept_encryption);
- out_int (CODE_input_encrypted_chat);
- out_int (tgl_get_peer_id (E->id));
- out_long (E->access_hash);
-
- ensure (BN_set_word (g_a, TLS->encr_root));
- ensure (BN_mod_exp (r, g_a, b, p, TLS->BN_ctx));
- static unsigned char buf[256];
- memset (buf, 0, sizeof (buf));
- BN_bn2bin (r, buf + (256 - BN_num_bytes (r)));
- out_cstring ((void *)buf, 256);
-
- out_long (E->key_fingerprint);
- BN_clear_free (b);
- BN_clear_free (g_a);
- BN_clear_free (p);
- BN_clear_free (r);
-
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_encr_accept_methods, E, callback, callback_extra);
-}
-
-void tgl_do_create_keys_end (struct tgl_state *TLS, struct tgl_secret_chat *U) {
- assert (TLS->encr_prime);
- BIGNUM *g_b = BN_bin2bn (U->g_key, 256, 0);
- ensure_ptr (g_b);
- assert (tglmp_check_g (TLS, TLS->encr_prime, g_b) >= 0);
- BIGNUM *p = BN_bin2bn (TLS->encr_prime, 256, 0);
- ensure_ptr (p);
- BIGNUM *r = BN_new ();
- ensure_ptr (r);
- BIGNUM *a = BN_bin2bn ((void *)U->key, 256, 0);
- ensure_ptr (a);
- ensure (BN_mod_exp (r, g_b, a, p, TLS->BN_ctx));
-
- unsigned char *t = talloc (256);
- memcpy (t, U->key, 256);
-
- memset (U->key, 0, sizeof (U->key));
- BN_bn2bin (r, (void *)(((char *)(U->key)) + (256 - BN_num_bytes (r))));
- int i;
- for (i = 0; i < 64; i++) {
- U->key[i] ^= *(((int *)U->nonce) + i);
- }
-
- static unsigned char sha_buffer[20];
- sha1 ((void *)U->key, 256, sha_buffer);
- long long k = *(long long *)(sha_buffer + 12);
- if (k != U->key_fingerprint) {
- vlogprintf (E_WARNING, "Key fingerprint mismatch (my 0x%llx 0x%llx)\n", (unsigned long long)k, (unsigned long long)U->key_fingerprint);
- U->state = sc_deleted;
- }
-
- tfree_secure (t, 256);
-
- BN_clear_free (p);
- BN_clear_free (g_b);
- BN_clear_free (r);
- BN_clear_free (a);
-}
-
-void tgl_do_send_create_encr_chat (struct tgl_state *TLS, void *x, unsigned char *random, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_secret_chat *E), void *callback_extra) {
- int user_id = (long)x;
- int i;
- unsigned char random_here[256];
- tglt_secure_random (random_here, 256);
- for (i = 0; i < 256; i++) {
- random[i] ^= random_here[i];
- }
- BIGNUM *a = BN_bin2bn (random, 256, 0);
- ensure_ptr (a);
- BIGNUM *p = BN_bin2bn (TLS->encr_prime, 256, 0);
- ensure_ptr (p);
-
- BIGNUM *g = BN_new ();
- ensure_ptr (g);
-
- ensure (BN_set_word (g, TLS->encr_root));
-
- BIGNUM *r = BN_new ();
- ensure_ptr (r);
-
- ensure (BN_mod_exp (r, g, a, p, TLS->BN_ctx));
-
- BN_clear_free (a);
-
- static char g_a[256];
- memset (g_a, 0, 256);
-
- BN_bn2bin (r, (void *)(g_a + (256 - BN_num_bytes (r))));
-
- int t = lrand48 ();
- while (tgl_peer_get (TLS, TGL_MK_ENCR_CHAT (t))) {
- t = lrand48 ();
- }
-
- bl_do_encr_chat_init (TLS, t, user_id, (void *)random, (void *)g_a);
- tgl_peer_t *_E = tgl_peer_get (TLS, TGL_MK_ENCR_CHAT (t));
- assert (_E);
- struct tgl_secret_chat *E = &_E->encr_chat;
-
- clear_packet ();
- out_int (CODE_messages_request_encryption);
- tgl_peer_t *U = tgl_peer_get (TLS, TGL_MK_USER (E->user_id));
- assert (U);
- if (U && U->user.access_hash) {
- out_int (CODE_input_user_foreign);
- out_int (E->user_id);
- out_long (U->user.access_hash);
- } else {
- out_int (CODE_input_user_contact);
- out_int (E->user_id);
- }
- out_int (tgl_get_peer_id (E->id));
- out_cstring (g_a, 256);
- //write_secret_chat_file ();
-
- BN_clear_free (g);
- BN_clear_free (p);
- BN_clear_free (r);
-
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_encr_request_methods, E, callback, callback_extra);
-}
-
-static int get_dh_config_on_answer (struct tgl_state *TLS, struct query *q UU) {
- unsigned x = fetch_int ();
- assert (x == CODE_messages_dh_config || x == CODE_messages_dh_config_not_modified);
- if (x == CODE_messages_dh_config) {
- int a = fetch_int ();
- int l = prefetch_strlen ();
- assert (l == 256);
- char *s = fetch_str (l);
- int v = fetch_int ();
- bl_do_set_dh_params (TLS, a, (void *)s, v);
-
- BIGNUM *p = BN_bin2bn ((void *)s, 256, 0);
- ensure_ptr (p);
- assert (tglmp_check_DH_params (TLS, p, a) >= 0);
- BN_free (p);
- } else {
- assert (TLS->encr_param_version);
- }
- int l = prefetch_strlen ();
- assert (l == 256);
- unsigned char *random = talloc (256);
- memcpy (random, fetch_str (256), 256);
- if (q->extra) {
- void **x = q->extra;
- ((void (*)(struct tgl_state *, void *, void *, void *, void *))(*x))(TLS, x[1], random, q->callback, q->callback_extra);
- tfree (x, 2 * sizeof (void *));
- tfree_secure (random, 256);
- } else {
- tfree_secure (random, 256);
- }
- return 0;
-}
-
-static struct query_methods get_dh_config_methods = {
- .on_answer = get_dh_config_on_answer,
- .type = TYPE_TO_PARAM(messages_dh_config)
-};
-
-void tgl_do_accept_encr_chat_request (struct tgl_state *TLS, struct tgl_secret_chat *E, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_secret_chat *E), void *callback_extra) {
- if (E->state != sc_request) {
- if (callback) {
- callback (TLS, callback_extra, 0, E);
- }
- return;
- }
- assert (E->state == sc_request);
-
- clear_packet ();
- out_int (CODE_messages_get_dh_config);
- out_int (TLS->encr_param_version);
- out_int (256);
- void **x = talloc (2 * sizeof (void *));
- x[0] = tgl_do_send_accept_encr_chat;
- x[1] = E;
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &get_dh_config_methods, x, callback, callback_extra);
-}
-
-void tgl_do_create_encr_chat_request (struct tgl_state *TLS, int user_id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_secret_chat *E), void *callback_extra) {
- clear_packet ();
- out_int (CODE_messages_get_dh_config);
- out_int (TLS->encr_param_version);
- out_int (256);
- void **x = talloc (2 * sizeof (void *));
- x[0] = tgl_do_send_create_encr_chat;
- x[1] = (void *)(long)(user_id);
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &get_dh_config_methods, x, callback, callback_extra);
-}
-/* }}} */
-
-/* {{{ Get difference */
-//int unread_messages;
-//int difference_got;
-//int seq, pts, qts, last_date;
-static int get_state_on_answer (struct tgl_state *TLS, struct query *q UU) {
- assert (TLS->locks & TGL_LOCK_DIFF);
- TLS->locks ^= TGL_LOCK_DIFF;
- assert (fetch_int () == (int)CODE_updates_state);
- bl_do_set_pts (TLS, fetch_int ());
- bl_do_set_qts (TLS, fetch_int ());
- bl_do_set_date (TLS, fetch_int ());
- bl_do_set_seq (TLS, fetch_int ());
- //unread_messages = fetch_int ();
- fetch_int ();
- //write_state_file ();
- //difference_got = 1;
-
- if (q->callback) {
- ((void (*)(struct tgl_state *, void *, int))q->callback) (TLS, q->callback_extra, 1);
- }
- return 0;
-}
-
-static int lookup_state_on_answer (struct tgl_state *TLS, struct query *q UU) {
- assert (fetch_int () == (int)CODE_updates_state);
- int pts = fetch_int ();
- int qts = fetch_int ();
- fetch_int ();
- int seq = fetch_int ();
- fetch_int ();
-
- if (pts > TLS->pts || qts > TLS->qts || seq > TLS->seq) {
- tgl_do_get_difference (TLS, 0, 0, 0);
- }
- return 0;
-}
-
-
-//int get_difference_active;
-static int get_difference_on_answer (struct tgl_state *TLS, struct query *q UU) {
- //get_difference_active = 0;
- assert (TLS->locks & TGL_LOCK_DIFF);
- TLS->locks ^= TGL_LOCK_DIFF;
-
- unsigned x = fetch_int ();
- if (x == CODE_updates_difference_empty) {
- bl_do_set_date (TLS, fetch_int ());
- bl_do_set_seq (TLS, fetch_int ());
- //difference_got = 1;
-
- vlogprintf (E_DEBUG, "Empty difference. Seq = %d\n", TLS->seq);
- if (q->callback) {
- ((void (*)(struct tgl_state *, void *, int))q->callback) (TLS, q->callback_extra, 1);
- }
- } else if (x == CODE_updates_difference || x == CODE_updates_difference_slice) {
- int n, i;
- assert (fetch_int () == CODE_vector);
- n = fetch_int ();
- struct tgl_message **ML = talloc (n * sizeof (void *));
- int ml_pos = 0;
- for (i = 0; i < n; i++) {
- ML[ml_pos ++] = tglf_fetch_alloc_message (TLS);
- }
- assert (fetch_int () == CODE_vector);
- n = fetch_int ();
- struct tgl_message **EL = talloc (n * sizeof (void *));
- int el_pos = 0;
- for (i = 0; i < n; i++) {
- EL[el_pos ++] = tglf_fetch_alloc_encrypted_message (TLS);
- }
- assert (fetch_int () == CODE_vector);
- n = fetch_int ();
- for (i = 0; i < n; i++) {
- tglu_work_update (TLS, 0, 0);
- }
- assert (fetch_int () == CODE_vector);
- n = fetch_int ();
- for (i = 0; i < n; i++) {
- tglf_fetch_alloc_chat (TLS);
- }
- assert (fetch_int () == CODE_vector);
- n = fetch_int ();
- for (i = 0; i < n; i++) {
- tglf_fetch_alloc_user (TLS);
- }
- assert (fetch_int () == (int)CODE_updates_state);
- bl_do_set_pts (TLS, fetch_int ());
- bl_do_set_qts (TLS, fetch_int ());
- bl_do_set_date (TLS, fetch_int ());
- if (x == CODE_updates_difference) {
- bl_do_set_seq (TLS, fetch_int ());
- vlogprintf (E_DEBUG, "Difference end. New seq = %d\n", TLS->seq);
- } else {
- fetch_int ();
- }
- //unread_messages = fetch_int ();
- fetch_int ();
- //write_state_file ();
- /*for (i = 0; i < ml_pos; i++) {
- print_message (ML[i]);
- }*/
- for (i = 0; i < ml_pos; i++) {
- //TLS->callback.new_msg (ML[i]);
- bl_do_msg_update (TLS, ML[i]->id);
- }
- for (i = 0; i < el_pos; i++) {
- //TLS->callback.new_msg (EL[i]);
- bl_do_msg_update (TLS, EL[i]->id);
- }
- tfree (ML, ml_pos * sizeof (void *));
- tfree (EL, el_pos * sizeof (void *));
-
- if (x == CODE_updates_difference_slice) {
- //if (q->callback) {
- // ((void (*)(void *, int))q->callback) (q->callback_extra, 1);
- //}
- tgl_do_get_difference (TLS, 0, q->callback, q->callback_extra);
- } else {
- //difference_got = 1;
- if (q->callback) {
- ((void (*)(struct tgl_state *, void *, int))q->callback) (TLS, q->callback_extra, 1);
- }
- }
- } else {
- assert (0);
- }
- return 0;
-}
-
-static struct query_methods lookup_state_methods = {
- .on_answer = lookup_state_on_answer,
- .type = TYPE_TO_PARAM(updates_state)
-};
-
-static struct query_methods get_state_methods = {
- .on_answer = get_state_on_answer,
- .type = TYPE_TO_PARAM(updates_state)
-};
-
-static struct query_methods get_difference_methods = {
- .on_answer = get_difference_on_answer,
- .type = TYPE_TO_PARAM(updates_difference)
-};
-
-void tgl_do_lookup_state (struct tgl_state *TLS) {
- if (TLS->locks & TGL_LOCK_DIFF) {
- return;
- }
- clear_packet ();
- tgl_do_insert_header ();
- out_int (CODE_updates_get_state);
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &lookup_state_methods, 0, 0, 0);
-}
-
-void tgl_do_get_difference (struct tgl_state *TLS, int sync_from_start, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) {
- //get_difference_active = 1;
- //difference_got = 0;
- if (TLS->locks & TGL_LOCK_DIFF) {
- if (callback) {
- callback (TLS, callback_extra, 0);
- }
- return;
- }
- TLS->locks |= TGL_LOCK_DIFF;
- clear_packet ();
- tgl_do_insert_header ();
- if (TLS->pts > 0 || sync_from_start) {
- if (TLS->pts == 0) { TLS->pts = 1; }
- //if (TLS->qts == 0) { TLS->qts = 1; }
- if (TLS->date == 0) { TLS->date = 1; }
- out_int (CODE_updates_get_difference);
- out_int (TLS->pts);
- out_int (TLS->date);
- out_int (TLS->qts);
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &get_difference_methods, 0, callback, callback_extra);
- } else {
- out_int (CODE_updates_get_state);
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &get_state_methods, 0, callback, callback_extra);
- }
-}
-/* }}} */
-
-/* {{{ Visualize key */
-/*char *colors[4] = {COLOR_GREY, COLOR_CYAN, COLOR_BLUE, COLOR_GREEN};
-
-void tgl_do_visualize_key (tgl_peer_id_t id) {
- assert (tgl_get_peer_type (id) == TGL_PEER_ENCR_CHAT);
- tgl_peer_t *P = tgl_peer_get (TLS, id);
- assert (P);
- if (P->encr_chat.state != sc_ok) {
- rprintf ("Chat is not initialized yet\n");
- return;
- }
- unsigned char buf[20];
- SHA1 ((void *)P->encr_chat.key, 256, buf);
- print_start ();
- int i;
- for (i = 0; i < 16; i++) {
- int x = buf[i];
- int j;
- for (j = 0; j < 4; j ++) {
- push_color (colors[x & 3]);
- push_color (COLOR_INVERSE);
- printf (" ");
- pop_color ();
- pop_color ();
- x = x >> 2;
- }
- if (i & 1) { printf ("\n"); }
- }
- print_end ();
-}*/
-
-void tgl_do_visualize_key (struct tgl_state *TLS, tgl_peer_id_t id, unsigned char buf[16]) {
- assert (tgl_get_peer_type (id) == TGL_PEER_ENCR_CHAT);
- tgl_peer_t *P = tgl_peer_get (TLS, id);
- assert (P);
- if (P->encr_chat.state != sc_ok) {
- vlogprintf (E_WARNING, "Chat is not initialized yet\n");
- return;
- }
- unsigned char res[20];
- SHA1 ((void *)P->encr_chat.key, 256, res);
- memcpy (buf, res, 16);
-}
-/* }}} */
-
-/* {{{ Get suggested */
-/*int get_suggested_on_answer (struct query *q UU) {
- assert (fetch_int () == CODE_contacts_suggested);
- assert (fetch_int () == CODE_vector);
- int n = fetch_int ();
- logprintf ("n = %d\n", n);
- assert (n <= 200);
- int l[400];
- int i;
- for (i = 0; i < n; i++) {
- assert (fetch_int () == CODE_contact_suggested);
- l[2 * i] = fetch_int ();
- l[2 * i + 1] = fetch_int ();
- }
- assert (fetch_int () == CODE_vector);
- int m = fetch_int ();
- assert (n == m);
- print_start ();
- push_color (COLOR_YELLOW);
- for (i = 0; i < m; i++) {
- tgl_peer_t *U = (void *)tglf_fetch_alloc_user (TLS);
- assert (tgl_get_peer_id (U->id) == l[2 * i]);
- print_user_name (U->id, U);
- printf (" phone %s: %d mutual friends\n", U->user.phone, l[2 * i + 1]);
- }
- pop_color ();
- print_end ();
- return 0;
-}
-
-struct query_methods get_suggested_methods = {
- .on_answer = get_suggested_on_answer,
- .type = TYPE_TO_PARAM(contacts_suggested)
-};
-
-void tgl_do_get_suggested (void) {
- clear_packet ();
- out_int (CODE_contacts_get_suggested);
- out_int (100);
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &get_suggested_methods, 0);
-}*/
-/* }}} */
-
-/* {{{ Add user to chat */
-
-static struct query_methods add_user_to_chat_methods = {
- .on_answer = fwd_msg_on_answer,
- .type = TYPE_TO_PARAM(messages_stated_message)
-};
-
-void tgl_do_add_user_to_chat (struct tgl_state *TLS, tgl_peer_id_t chat_id, tgl_peer_id_t id, int limit, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) {
- clear_packet ();
- out_int (CODE_messages_add_chat_user);
- out_int (tgl_get_peer_id (chat_id));
-
- assert (tgl_get_peer_type (id) == TGL_PEER_USER);
- tgl_peer_t *U = tgl_peer_get (TLS, id);
- if (U && U->user.access_hash) {
- out_int (CODE_input_user_foreign);
- out_int (tgl_get_peer_id (id));
- out_long (U->user.access_hash);
- } else {
- out_int (CODE_input_user_contact);
- out_int (tgl_get_peer_id (id));
- }
- out_int (limit);
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &add_user_to_chat_methods, 0, callback, callback_extra);
-}
-
-void tgl_do_del_user_from_chat (struct tgl_state *TLS, tgl_peer_id_t chat_id, tgl_peer_id_t id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) {
- clear_packet ();
- out_int (CODE_messages_delete_chat_user);
- out_int (tgl_get_peer_id (chat_id));
-
- assert (tgl_get_peer_type (id) == TGL_PEER_USER);
- tgl_peer_t *U = tgl_peer_get (TLS, id);
- if (U && U->user.access_hash) {
- out_int (CODE_input_user_foreign);
- out_int (tgl_get_peer_id (id));
- out_long (U->user.access_hash);
- } else {
- out_int (CODE_input_user_contact);
- out_int (tgl_get_peer_id (id));
- }
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &add_user_to_chat_methods, 0, callback, callback_extra);
-}
-/* }}} */
-
-/* {{{ Create secret chat */
-//char *create_print_name (tgl_peer_id_t id, const char *a1, const char *a2, const char *a3, const char *a4);
-
-void tgl_do_create_secret_chat (struct tgl_state *TLS, tgl_peer_id_t id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_secret_chat *E), void *callback_extra) {
- assert (tgl_get_peer_type (id) == TGL_PEER_USER);
- tgl_peer_t *U = tgl_peer_get (TLS, id);
- if (!U) {
- vlogprintf (E_WARNING, "Can not create chat with unknown user\n");
- return;
- }
-
- tgl_do_create_encr_chat_request (TLS, tgl_get_peer_id (id), callback, callback_extra);
-}
-/* }}} */
-
-/* {{{ Create group chat */
-static struct query_methods create_group_chat_methods = {
- .on_answer = fwd_msg_on_answer,
- .type = TYPE_TO_PARAM(messages_stated_message)
-};
-
-void tgl_do_create_group_chat (struct tgl_state *TLS, tgl_peer_id_t id, char *chat_topic, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) {
- assert (tgl_get_peer_type (id) == TGL_PEER_USER);
- tgl_peer_t *U = tgl_peer_get (TLS, id);
- if (!U) {
- vlogprintf (E_WARNING, "Can not create chat with unknown user\n");
- if (callback) {
- callback (TLS, callback_extra, 0, 0);
- }
- return;
- }
- clear_packet ();
- out_int (CODE_messages_create_chat);
- out_int (CODE_vector);
- out_int (1); // Number of users, currently we support only 1 user.
- if (U && U->user.access_hash) {
- out_int (CODE_input_user_foreign);
- out_int (tgl_get_peer_id (id));
- out_long (U->user.access_hash);
- } else {
- out_int (CODE_input_user_contact);
- out_int (tgl_get_peer_id (id));
- }
- out_string (chat_topic);
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &create_group_chat_methods, 0, callback, callback_extra);
-}
-
-void tgl_do_create_group_chat_ex (struct tgl_state *TLS, int users_num, tgl_peer_id_t ids[], char *chat_topic, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) {
- clear_packet ();
- out_int (CODE_messages_create_chat);
- out_int (CODE_vector);
- out_int (users_num); // Number of users, currently we support only 1 user.
- int i;
- for (i = 0; i < users_num; i++) {
- tgl_peer_id_t id = ids[i];
- tgl_peer_t *U = tgl_peer_get (TLS, id);
- if (!U || tgl_get_peer_type (id) != TGL_PEER_USER) {
- vlogprintf (E_WARNING, "Can not create chat with unknown user\n");
- if (callback) {
- callback (TLS, callback_extra, 0, 0);
- }
- return;
- }
- if (U && U->user.access_hash) {
- out_int (CODE_input_user_foreign);
- out_int (tgl_get_peer_id (id));
- out_long (U->user.access_hash);
- } else {
- out_int (CODE_input_user_contact);
- out_int (tgl_get_peer_id (id));
- }
- }
- out_string (chat_topic);
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &create_group_chat_methods, 0, callback, callback_extra);
-}
-/* }}} */
-
-/* {{{ Delete msg */
-
-static int delete_msg_on_answer (struct tgl_state *TLS, struct query *q UU) {
- assert (fetch_int () == CODE_vector);
- int n = fetch_int ();
- fetch_skip (n);
-
- if (q->callback) {
- ((void (*)(struct tgl_state *, void *, int))q->callback) (TLS, q->callback_extra, 1);
- }
- return 0;
-}
-
-static struct query_methods delete_msg_methods = {
- .on_answer = delete_msg_on_answer,
- .type = TYPE_TO_PARAM_1(vector, TYPE_TO_PARAM (bare_int))
-};
-
-void tgl_do_delete_msg (struct tgl_state *TLS, long long id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) {
- clear_packet ();
- out_int (CODE_messages_delete_messages);
- out_int (CODE_vector);
- out_int (1);
- out_int (id);
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &delete_msg_methods, 0, callback, callback_extra);
-}
-/* }}} */
-
-/* {{{ Restore msg */
-
-static int restore_msg_on_answer (struct tgl_state *TLS, struct query *q UU) {
- assert (fetch_int () == CODE_vector);
- int n = fetch_int ();
- fetch_skip (n);
- //logprintf ("Restored %d messages\n", n);
-
- if (q->callback) {
- ((void (*)(struct tgl_state *, void *, int))q->callback) (TLS, q->callback_extra, 1);
- }
- return 0;
-}
-
-static struct query_methods restore_msg_methods = {
- .on_answer = restore_msg_on_answer,
- .type = TYPE_TO_PARAM_1(vector, TYPE_TO_PARAM (bare_int))
-};
-
-void tgl_do_restore_msg (struct tgl_state *TLS, long long id, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) {
- clear_packet ();
- out_int (CODE_messages_restore_messages);
- out_int (CODE_vector);
- out_int (1);
- out_int (id);
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &restore_msg_methods, 0, callback, callback_extra);
-}
-/* }}} */
-
-/* {{{ Export card */
-
-static int export_card_on_answer (struct tgl_state *TLS, struct query *q UU) {
- assert (fetch_int () == CODE_vector);
- int n = fetch_int ();
- //logprintf ("Restored %d messages\n", n);
- int *r = talloc (4 * n);
- fetch_ints (r, n);
-
- if (q->callback) {
- ((void (*)(struct tgl_state *, void *, int, int, int *))q->callback) (TLS, q->callback_extra, 1, n, r);
- }
- free (r);
- return 0;
-}
-
-static struct query_methods export_card_methods = {
- .on_answer = export_card_on_answer,
- .type = TYPE_TO_PARAM_1(vector, TYPE_TO_PARAM (bare_int))
-};
-
-void tgl_do_export_card (struct tgl_state *TLS, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, int size, int *card), void *callback_extra) {
- clear_packet ();
- out_int (CODE_contacts_export_card);
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &export_card_methods, 0, callback, callback_extra);
-}
-/* }}} */
-
-/* {{{ Import card */
-
-static int import_card_on_answer (struct tgl_state *TLS, struct query *q UU) {
- struct tgl_user *U = tglf_fetch_alloc_user (TLS);
-
- if (q->callback) {
- ((void (*)(struct tgl_state *, void *, int, struct tgl_user *))q->callback) (TLS, q->callback_extra, 1, U);
- }
- return 0;
-}
-
-static struct query_methods import_card_methods = {
- .on_answer = import_card_on_answer,
- .type = TYPE_TO_PARAM (user)
-};
-
-void tgl_do_import_card (struct tgl_state *TLS, int size, int *card, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_user *U), void *callback_extra) {
- clear_packet ();
- out_int (CODE_contacts_import_card);
- out_int (CODE_vector);
- out_int (size);
- out_ints (card, size);
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &import_card_methods, 0, callback, callback_extra);
-}
-/* }}} */
-
-#ifndef DISABLE_EXTF
-static int ext_query_on_answer (struct tgl_state *TLS, struct query *q UU) {
- if (q->callback) {
- char *buf = tglf_extf_fetch (TLS, q->type);
- ((void (*)(struct tgl_state *, void *, int, char *))q->callback) (TLS, q->callback_extra, 1, buf);
- }
- tgl_paramed_type_free (q->type);
- return 0;
-}
-
-static struct query_methods ext_query_methods = {
- .on_answer = ext_query_on_answer,
-};
-
-void tgl_do_send_extf (struct tgl_state *TLS, char *data, int data_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, char *buf), void *callback_extra) {
- clear_packet ();
-
- ext_query_methods.type = tglf_extf_store (TLS, data, data_len);
-
- if (ext_query_methods.type) {
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &ext_query_methods, 0, callback, callback_extra);
- }
-}
-#else
-void tgl_do_send_extf (struct tgl_state *TLS, char *data, int data_len, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, char *buf), void *callback_extra) {
- if (callback) {
- callback (TLS, callback_extra, 0, 0);
- }
-}
-#endif
-
-static void set_flag_4 (struct tgl_state *TLS, void *_D, int success) {
- struct tgl_dc *D = _D;
- assert (success);
- D->flags |= 4;
-
- TLS->timer_methods->insert (D->ev, TLS->temp_key_expire_time * 0.9);
-}
-
-static int send_bind_temp_on_answer (struct tgl_state *TLS, struct query *q UU) {
- assert (fetch_int () == (int)CODE_bool_true);
- struct tgl_dc *D = q->extra;
- D->flags |= 2;
- tgl_do_help_get_config_dc (TLS, D, set_flag_4, D);
- vlogprintf (E_DEBUG, "Bind successful in dc %d\n", D->id);
- return 0;
-}
-
-static struct query_methods send_bind_temp_methods = {
- .on_answer = send_bind_temp_on_answer,
- .on_error = fail_on_error,
- .type = TYPE_TO_PARAM (bool)
-};
-
-void tgl_do_send_bind_temp_key (struct tgl_state *TLS, struct tgl_dc *D, long long nonce, int expires_at, void *data, int len, long long msg_id) {
- clear_packet ();
- out_int (CODE_auth_bind_temp_auth_key);
- out_long (D->auth_key_id);
- out_long (nonce);
- out_int (expires_at);
- out_cstring (data, len);
- struct query *q = tglq_send_query_ex (TLS, D, packet_ptr - packet_buffer, packet_buffer, &send_bind_temp_methods, D, 0, 0, 2);
- assert (q->msg_id == msg_id);
-}
-
-static int update_status_on_answer (struct tgl_state *TLS, struct query *q UU) {
- fetch_bool ();
-
- if (q->callback) {
- ((void (*)(struct tgl_state *, void *, int))q->callback) (TLS, q->callback_extra, 1);
- }
- return 0;
-}
-
-static struct query_methods update_status_methods = {
- .on_answer = update_status_on_answer,
- .type = TYPE_TO_PARAM(bool)
-};
-
-void tgl_do_update_status (struct tgl_state *TLS, int online UU, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success), void *callback_extra) {
- clear_packet ();
- out_int (CODE_account_update_status);
- out_int (online ? CODE_bool_false : CODE_bool_true);
- tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &update_status_methods, 0, callback, callback_extra);
-}
diff --git a/queries.h b/queries.h
deleted file mode 100644
index 51c61c2..0000000
--- a/queries.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- This file is part of tgl-library
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library 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
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
- Copyright Vitaly Valtman 2013-2014
-*/
-//#include "net.h"
-#ifndef __QUERIES_H__
-#define __QUERIES_H__
-#include "structures.h"
-#include "auto.h"
-#include "tgl-layout.h"
-
-#define QUERY_ACK_RECEIVED 1
-#define QUERY_FORCE_SEND 2
-
-struct query;
-struct query_methods {
- int (*on_answer)(struct tgl_state *TLS, struct query *q);
- int (*on_error)(struct tgl_state *TLS, struct query *q, int error_code, int len, char *error);
- int (*on_timeout)(struct tgl_state *TLS, struct query *q);
- struct paramed_type *type;
-};
-
-struct query {
- long long msg_id;
- int data_len;
- int flags;
- int seq_no;
- long long session_id;
- void *data;
- struct query_methods *methods;
- struct tgl_timer *ev;
- struct tgl_dc *DC;
- struct tgl_session *session;
- struct paramed_type *type;
- void *extra;
- void *callback;
- void *callback_extra;
-};
-
-
-struct query *tglq_send_query (struct tgl_state *TLS, struct tgl_dc *DC, int len, void *data, struct query_methods *methods, void *extra, void *callback, void *callback_extra);
-void tglq_query_ack (struct tgl_state *TLS, long long id);
-void tglq_query_error (struct tgl_state *TLS, long long id);
-void tglq_query_result (struct tgl_state *TLS, long long id);
-void tglq_query_restart (struct tgl_state *TLS, long long id);
-
-//double next_timer_in (void);
-//void work_timers (void);
-
-//extern struct query_methods help_get_config_methods;
-
-double get_double_time (void);
-
-void tgl_do_send_bind_temp_key (struct tgl_state *TLS, struct tgl_dc *D, long long nonce, int expires_at, void *data, int len, long long msg_id);
-
-// For binlog
-
-//int get_dh_config_on_answer (struct query *q);
-//void fetch_dc_option (void);
-#endif
diff --git a/scheme.tl b/scheme.tl
deleted file mode 120000
index 40329f0..0000000
--- a/scheme.tl
+++ /dev/null
@@ -1 +0,0 @@
-scheme18.tl
\ No newline at end of file
diff --git a/scheme12.tl b/scheme12.tl
deleted file mode 100644
index 7d37a6f..0000000
--- a/scheme12.tl
+++ /dev/null
@@ -1,505 +0,0 @@
-int ?= Int;
-long ?= Long;
-double ?= Double;
-string ?= String;
-
-bytes string = Bytes;
-
-boolFalse#bc799737 = Bool;
-boolTrue#997275b5 = Bool;
-
-vector#1cb5c415 {t:Type} # [ t ] = Vector t;
-
-error#c4b9f9bb code:int text:string = Error;
-
-null#56730bcc = Null;
-
-inputPeerEmpty#7f3b18ea = InputPeer;
-inputPeerSelf#7da07ec9 = InputPeer;
-inputPeerContact#1023dbe8 user_id:int = InputPeer;
-inputPeerForeign#9b447325 user_id:int access_hash:long = InputPeer;
-inputPeerChat#179be863 chat_id:int = InputPeer;
-
-inputUserEmpty#b98886cf = InputUser;
-inputUserSelf#f7c1b13f = InputUser;
-inputUserContact#86e94f65 user_id:int = InputUser;
-inputUserForeign#655e74ff user_id:int access_hash:long = InputUser;
-
-inputPhoneContact#f392b7f4 client_id:long phone:string first_name:string last_name:string = InputContact;
-
-inputFile#f52ff27f id:long parts:int name:string md5_checksum:string = InputFile;
-
-inputMediaEmpty#9664f57f = InputMedia;
-inputMediaUploadedPhoto#2dc53a7d file:InputFile = InputMedia;
-inputMediaPhoto#8f2ab2ec id:InputPhoto = InputMedia;
-inputMediaGeoPoint#f9c44144 geo_point:InputGeoPoint = InputMedia;
-inputMediaContact#a6e45987 phone_number:string first_name:string last_name:string = InputMedia;
-inputMediaUploadedVideo#4847d92a file:InputFile duration:int w:int h:int = InputMedia;
-inputMediaUploadedThumbVideo#e628a145 file:InputFile thumb:InputFile duration:int w:int h:int = InputMedia;
-inputMediaVideo#7f023ae6 id:InputVideo = InputMedia;
-
-inputChatPhotoEmpty#1ca48f57 = InputChatPhoto;
-inputChatUploadedPhoto#94254732 file:InputFile crop:InputPhotoCrop = InputChatPhoto;
-inputChatPhoto#b2e1bf08 id:InputPhoto crop:InputPhotoCrop = InputChatPhoto;
-
-inputGeoPointEmpty#e4c123d6 = InputGeoPoint;
-inputGeoPoint#f3b7acc9 lat:double long:double = InputGeoPoint;
-
-inputPhotoEmpty#1cd7bf0d = InputPhoto;
-inputPhoto#fb95c6c4 id:long access_hash:long = InputPhoto;
-
-inputVideoEmpty#5508ec75 = InputVideo;
-inputVideo#ee579652 id:long access_hash:long = InputVideo;
-
-inputFileLocation#14637196 volume_id:long local_id:int secret:long = InputFileLocation;
-inputVideoFileLocation#3d0364ec id:long access_hash:long = InputFileLocation;
-
-inputPhotoCropAuto#ade6b004 = InputPhotoCrop;
-inputPhotoCrop#d9915325 crop_left:double crop_top:double crop_width:double = InputPhotoCrop;
-
-inputAppEvent#770656a8 time:double type:string peer:long data:string = InputAppEvent;
-
-peerUser#9db1bc6d user_id:int = Peer;
-peerChat#bad0e5bb chat_id:int = Peer;
-
-storage.fileUnknown#aa963b05 = storage.FileType;
-storage.fileJpeg#7efe0e = storage.FileType;
-storage.fileGif#cae1aadf = storage.FileType;
-storage.filePng#a4f63c0 = storage.FileType;
-storage.filePdf#ae1e508d = storage.FileType;
-storage.fileMp3#528a0677 = storage.FileType;
-storage.fileMov#4b09ebbc = storage.FileType;
-storage.filePartial#40bc6f52 = storage.FileType;
-storage.fileMp4#b3cea0e4 = storage.FileType;
-storage.fileWebp#1081464c = storage.FileType;
-
-fileLocationUnavailable#7c596b46 volume_id:long local_id:int secret:long = FileLocation;
-fileLocation#53d69076 dc_id:int volume_id:long local_id:int secret:long = FileLocation;
-
-userEmpty#200250ba id:int = User;
-userSelf#720535ec id:int first_name:string last_name:string phone:string photo:UserProfilePhoto status:UserStatus inactive:Bool = User;
-userContact#f2fb8319 id:int first_name:string last_name:string access_hash:long phone:string photo:UserProfilePhoto status:UserStatus = User;
-userRequest#22e8ceb0 id:int first_name:string last_name:string access_hash:long phone:string photo:UserProfilePhoto status:UserStatus = User;
-userForeign#5214c89d id:int first_name:string last_name:string access_hash:long photo:UserProfilePhoto status:UserStatus = User;
-userDeleted#b29ad7cc id:int first_name:string last_name:string = User;
-
-userProfilePhotoEmpty#4f11bae1 = UserProfilePhoto;
-userProfilePhoto#d559d8c8 photo_id:long photo_small:FileLocation photo_big:FileLocation = UserProfilePhoto;
-
-userStatusEmpty#9d05049 = UserStatus;
-userStatusOnline#edb93949 expires:int = UserStatus;
-userStatusOffline#8c703f was_online:int = UserStatus;
-
-chatEmpty#9ba2d800 id:int = Chat;
-chat#6e9c9bc7 id:int title:string photo:ChatPhoto participants_count:int date:int left:Bool version:int = Chat;
-chatForbidden#fb0ccc41 id:int title:string date:int = Chat;
-
-chatFull#630e61be id:int participants:ChatParticipants chat_photo:Photo notify_settings:PeerNotifySettings = ChatFull;
-
-chatParticipant#c8d7493e user_id:int inviter_id:int date:int = ChatParticipant;
-
-chatParticipantsForbidden#fd2bb8a chat_id:int = ChatParticipants;
-chatParticipants#7841b415 chat_id:int admin_id:int participants:Vector version:int = ChatParticipants;
-
-chatPhotoEmpty#37c1011c = ChatPhoto;
-chatPhoto#6153276a photo_small:FileLocation photo_big:FileLocation = ChatPhoto;
-
-messageEmpty#83e5de54 id:int = Message;
-message#22eb6aba id:int from_id:int to_id:Peer out:Bool unread:Bool date:int message:string media:MessageMedia = Message;
-messageForwarded#5f46804 id:int fwd_from_id:int fwd_date:int from_id:int to_id:Peer out:Bool unread:Bool date:int message:string media:MessageMedia = Message;
-messageService#9f8d60bb id:int from_id:int to_id:Peer out:Bool unread:Bool date:int action:MessageAction = Message;
-
-messageMediaEmpty#3ded6320 = MessageMedia;
-messageMediaPhoto#c8c45a2a photo:Photo = MessageMedia;
-messageMediaVideo#a2d24290 video:Video = MessageMedia;
-messageMediaGeo#56e0d474 geo:GeoPoint = MessageMedia;
-messageMediaContact#5e7d2f39 phone_number:string first_name:string last_name:string user_id:int = MessageMedia;
-messageMediaUnsupported#29632a36 bytes:bytes = MessageMedia;
-
-messageActionEmpty#b6aef7b0 = MessageAction;
-messageActionChatCreate#a6638b9a title:string users:Vector = MessageAction;
-messageActionChatEditTitle#b5a1ce5a title:string = MessageAction;
-messageActionChatEditPhoto#7fcb13a8 photo:Photo = MessageAction;
-messageActionChatDeletePhoto#95e3fbef = MessageAction;
-messageActionChatAddUser#5e3cfc4b user_id:int = MessageAction;
-messageActionChatDeleteUser#b2ae9b0c user_id:int = MessageAction;
-
-dialog#214a8cdf peer:Peer top_message:int unread_count:int = Dialog;
-
-photoEmpty#2331b22d id:long = Photo;
-photo#22b56751 id:long access_hash:long user_id:int date:int caption:string geo:GeoPoint sizes:Vector = Photo;
-
-photoSizeEmpty#e17e23c type:string = PhotoSize;
-photoSize#77bfb61b type:string location:FileLocation w:int h:int size:int = PhotoSize;
-photoCachedSize#e9a734fa type:string location:FileLocation w:int h:int bytes:bytes = PhotoSize;
-
-videoEmpty#c10658a8 id:long = Video;
-video#5a04a49f id:long access_hash:long user_id:int date:int caption:string duration:int size:int thumb:PhotoSize dc_id:int w:int h:int = Video;
-
-geoPointEmpty#1117dd5f = GeoPoint;
-geoPoint#2049d70c long:double lat:double = GeoPoint;
-
-auth.checkedPhone#e300cc3b phone_registered:Bool phone_invited:Bool = auth.CheckedPhone;
-
-auth.sentCode#efed51d9 phone_registered:Bool phone_code_hash:string send_call_timeout:int is_password:Bool = auth.SentCode;
-
-auth.authorization#f6b673a4 expires:int user:User = auth.Authorization;
-
-auth.exportedAuthorization#df969c2d id:int bytes:bytes = auth.ExportedAuthorization;
-
-inputNotifyPeer#b8bc5b0c peer:InputPeer = InputNotifyPeer;
-inputNotifyUsers#193b4417 = InputNotifyPeer;
-inputNotifyChats#4a95e84e = InputNotifyPeer;
-inputNotifyAll#a429b886 = InputNotifyPeer;
-
-inputPeerNotifyEventsEmpty#f03064d8 = InputPeerNotifyEvents;
-inputPeerNotifyEventsAll#e86a2c74 = InputPeerNotifyEvents;
-
-inputPeerNotifySettings#46a2ce98 mute_until:int sound:string show_previews:Bool events_mask:int = InputPeerNotifySettings;
-
-peerNotifyEventsEmpty#add53cb3 = PeerNotifyEvents;
-peerNotifyEventsAll#6d1ded88 = PeerNotifyEvents;
-
-peerNotifySettingsEmpty#70a68512 = PeerNotifySettings;
-peerNotifySettings#8d5e11ee mute_until:int sound:string show_previews:Bool events_mask:int = PeerNotifySettings;
-
-wallPaper#ccb03657 id:int title:string sizes:Vector color:int = WallPaper;
-
-userFull#771095da user:User link:contacts.Link profile_photo:Photo notify_settings:PeerNotifySettings blocked:Bool real_first_name:string real_last_name:string = UserFull;
-
-contact#f911c994 user_id:int mutual:Bool = Contact;
-
-importedContact#d0028438 user_id:int client_id:long = ImportedContact;
-
-contactBlocked#561bc879 user_id:int date:int = ContactBlocked;
-
-contactFound#ea879f95 user_id:int = ContactFound;
-
-contactSuggested#3de191a1 user_id:int mutual_contacts:int = ContactSuggested;
-
-contactStatus#aa77b873 user_id:int expires:int = ContactStatus;
-
-chatLocated#3631cf4c chat_id:int distance:int = ChatLocated;
-
-contacts.foreignLinkUnknown#133421f8 = contacts.ForeignLink;
-contacts.foreignLinkRequested#a7801f47 has_phone:Bool = contacts.ForeignLink;
-contacts.foreignLinkMutual#1bea8ce1 = contacts.ForeignLink;
-
-contacts.myLinkEmpty#d22a1c60 = contacts.MyLink;
-contacts.myLinkRequested#6c69efee contact:Bool = contacts.MyLink;
-contacts.myLinkContact#c240ebd9 = contacts.MyLink;
-
-contacts.link#eccea3f5 my_link:contacts.MyLink foreign_link:contacts.ForeignLink user:User = contacts.Link;
-
-contacts.contacts#6f8b8cb2 contacts:Vector users:Vector = contacts.Contacts;
-contacts.contactsNotModified#b74ba9d2 = contacts.Contacts;
-
-contacts.importedContacts#d1cd0a4c imported:Vector users:Vector = contacts.ImportedContacts;
-
-contacts.blocked#1c138d15 blocked:Vector users:Vector = contacts.Blocked;
-contacts.blockedSlice#900802a1 count:int blocked:Vector users:Vector = contacts.Blocked;
-
-contacts.found#566000e results:Vector users:Vector = contacts.Found;
-
-contacts.suggested#5649dcc5 results:Vector users:Vector = contacts.Suggested;
-
-messages.dialogs#15ba6c40 dialogs:Vector