Rewritten to use libtgl
21
.gitignore
vendored
|
@ -1,21 +0,0 @@
|
|||
telegram
|
||||
*.o
|
||||
*.so
|
||||
*.a
|
||||
telegram-adium/libcrypto.a
|
||||
config.h
|
||||
config.log
|
||||
config.status
|
||||
.idea/
|
||||
nbproject/
|
||||
tags
|
||||
.DS_Store
|
||||
.ycm_extra_conf.py
|
||||
*.pyc
|
||||
app-hash.png
|
||||
.gdbinit
|
||||
core
|
||||
core*
|
||||
telegram-adium/telegram-adium.xcodeproj/project.xcworkspace/xcuserdata/matj.xcuserdatad/UserInterfaceState.xcuserstate
|
||||
telegram-adium/telegram-adium.xcodeproj/xcuserdata/matj.xcuserdatad
|
||||
telegram-adium/telegram-adium.xcodeproj/project.xcworkspace/xcuserdata/*
|
12
.travis.yml
|
@ -1,12 +0,0 @@
|
|||
language: c
|
||||
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
|
||||
install:
|
||||
- sudo apt-get install libssl-dev libglib2.0-dev libpurple-dev
|
||||
|
||||
script:
|
||||
- ./configure
|
||||
- make
|
339
LICENSE
|
@ -1,339 +0,0 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program 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.
|
||||
|
||||
This program 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 program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
339
LICENSE.h
|
@ -1,339 +0,0 @@
|
|||
" GNU GENERAL PUBLIC LICENSE\n"
|
||||
" Version 2, June 1991\n"
|
||||
"\n"
|
||||
" Copyright (C) 1989, 1991 Free Software Foundation, Inc.,\n"
|
||||
" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n"
|
||||
" Everyone is permitted to copy and distribute verbatim copies\n"
|
||||
" of this license document, but changing it is not allowed.\n"
|
||||
"\n"
|
||||
" Preamble\n"
|
||||
"\n"
|
||||
" The licenses for most software are designed to take away your\n"
|
||||
"freedom to share and change it. By contrast, the GNU General Public\n"
|
||||
"License is intended to guarantee your freedom to share and change free\n"
|
||||
"software--to make sure the software is free for all its users. This\n"
|
||||
"General Public License applies to most of the Free Software\n"
|
||||
"Foundation's software and to any other program whose authors commit to\n"
|
||||
"using it. (Some other Free Software Foundation software is covered by\n"
|
||||
"the GNU Lesser General Public License instead.) You can apply it to\n"
|
||||
"your programs, too.\n"
|
||||
"\n"
|
||||
" When we speak of free software, we are referring to freedom, not\n"
|
||||
"price. Our General Public Licenses are designed to make sure that you\n"
|
||||
"have the freedom to distribute copies of free software (and charge for\n"
|
||||
"this service if you wish), that you receive source code or can get it\n"
|
||||
"if you want it, that you can change the software or use pieces of it\n"
|
||||
"in new free programs; and that you know you can do these things.\n"
|
||||
"\n"
|
||||
" To protect your rights, we need to make restrictions that forbid\n"
|
||||
"anyone to deny you these rights or to ask you to surrender the rights.\n"
|
||||
"These restrictions translate to certain responsibilities for you if you\n"
|
||||
"distribute copies of the software, or if you modify it.\n"
|
||||
"\n"
|
||||
" For example, if you distribute copies of such a program, whether\n"
|
||||
"gratis or for a fee, you must give the recipients all the rights that\n"
|
||||
"you have. You must make sure that they, too, receive or can get the\n"
|
||||
"source code. And you must show them these terms so they know their\n"
|
||||
"rights.\n"
|
||||
"\n"
|
||||
" We protect your rights with two steps: (1) copyright the software, and\n"
|
||||
"(2) offer you this license which gives you legal permission to copy,\n"
|
||||
"distribute and/or modify the software.\n"
|
||||
"\n"
|
||||
" Also, for each author's protection and ours, we want to make certain\n"
|
||||
"that everyone understands that there is no warranty for this free\n"
|
||||
"software. If the software is modified by someone else and passed on, we\n"
|
||||
"want its recipients to know that what they have is not the original, so\n"
|
||||
"that any problems introduced by others will not reflect on the original\n"
|
||||
"authors' reputations.\n"
|
||||
"\n"
|
||||
" Finally, any free program is threatened constantly by software\n"
|
||||
"patents. We wish to avoid the danger that redistributors of a free\n"
|
||||
"program will individually obtain patent licenses, in effect making the\n"
|
||||
"program proprietary. To prevent this, we have made it clear that any\n"
|
||||
"patent must be licensed for everyone's free use or not licensed at all.\n"
|
||||
"\n"
|
||||
" The precise terms and conditions for copying, distribution and\n"
|
||||
"modification follow.\n"
|
||||
"\n"
|
||||
" GNU GENERAL PUBLIC LICENSE\n"
|
||||
" TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n"
|
||||
"\n"
|
||||
" 0. This License applies to any program or other work which contains\n"
|
||||
"a notice placed by the copyright holder saying it may be distributed\n"
|
||||
"under the terms of this General Public License. The \"Program\", below,\n"
|
||||
"refers to any such program or work, and a \"work based on the Program\"\n"
|
||||
"means either the Program or any derivative work under copyright law:\n"
|
||||
"that is to say, a work containing the Program or a portion of it,\n"
|
||||
"either verbatim or with modifications and/or translated into another\n"
|
||||
"language. (Hereinafter, translation is included without limitation in\n"
|
||||
"the term \"modification\".) Each licensee is addressed as \"you\".\n"
|
||||
"\n"
|
||||
"Activities other than copying, distribution and modification are not\n"
|
||||
"covered by this License; they are outside its scope. The act of\n"
|
||||
"running the Program is not restricted, and the output from the Program\n"
|
||||
"is covered only if its contents constitute a work based on the\n"
|
||||
"Program (independent of having been made by running the Program).\n"
|
||||
"Whether that is true depends on what the Program does.\n"
|
||||
"\n"
|
||||
" 1. You may copy and distribute verbatim copies of the Program's\n"
|
||||
"source code as you receive it, in any medium, provided that you\n"
|
||||
"conspicuously and appropriately publish on each copy an appropriate\n"
|
||||
"copyright notice and disclaimer of warranty; keep intact all the\n"
|
||||
"notices that refer to this License and to the absence of any warranty;\n"
|
||||
"and give any other recipients of the Program a copy of this License\n"
|
||||
"along with the Program.\n"
|
||||
"\n"
|
||||
"You may charge a fee for the physical act of transferring a copy, and\n"
|
||||
"you may at your option offer warranty protection in exchange for a fee.\n"
|
||||
"\n"
|
||||
" 2. You may modify your copy or copies of the Program or any portion\n"
|
||||
"of it, thus forming a work based on the Program, and copy and\n"
|
||||
"distribute such modifications or work under the terms of Section 1\n"
|
||||
"above, provided that you also meet all of these conditions:\n"
|
||||
"\n"
|
||||
" a) You must cause the modified files to carry prominent notices\n"
|
||||
" stating that you changed the files and the date of any change.\n"
|
||||
"\n"
|
||||
" b) You must cause any work that you distribute or publish, that in\n"
|
||||
" whole or in part contains or is derived from the Program or any\n"
|
||||
" part thereof, to be licensed as a whole at no charge to all third\n"
|
||||
" parties under the terms of this License.\n"
|
||||
"\n"
|
||||
" c) If the modified program normally reads commands interactively\n"
|
||||
" when run, you must cause it, when started running for such\n"
|
||||
" interactive use in the most ordinary way, to print or display an\n"
|
||||
" announcement including an appropriate copyright notice and a\n"
|
||||
" notice that there is no warranty (or else, saying that you provide\n"
|
||||
" a warranty) and that users may redistribute the program under\n"
|
||||
" these conditions, and telling the user how to view a copy of this\n"
|
||||
" License. (Exception: if the Program itself is interactive but\n"
|
||||
" does not normally print such an announcement, your work based on\n"
|
||||
" the Program is not required to print an announcement.)\n"
|
||||
"\n"
|
||||
"These requirements apply to the modified work as a whole. If\n"
|
||||
"identifiable sections of that work are not derived from the Program,\n"
|
||||
"and can be reasonably considered independent and separate works in\n"
|
||||
"themselves, then this License, and its terms, do not apply to those\n"
|
||||
"sections when you distribute them as separate works. But when you\n"
|
||||
"distribute the same sections as part of a whole which is a work based\n"
|
||||
"on the Program, the distribution of the whole must be on the terms of\n"
|
||||
"this License, whose permissions for other licensees extend to the\n"
|
||||
"entire whole, and thus to each and every part regardless of who wrote it.\n"
|
||||
"\n"
|
||||
"Thus, it is not the intent of this section to claim rights or contest\n"
|
||||
"your rights to work written entirely by you; rather, the intent is to\n"
|
||||
"exercise the right to control the distribution of derivative or\n"
|
||||
"collective works based on the Program.\n"
|
||||
"\n"
|
||||
"In addition, mere aggregation of another work not based on the Program\n"
|
||||
"with the Program (or with a work based on the Program) on a volume of\n"
|
||||
"a storage or distribution medium does not bring the other work under\n"
|
||||
"the scope of this License.\n"
|
||||
"\n"
|
||||
" 3. You may copy and distribute the Program (or a work based on it,\n"
|
||||
"under Section 2) in object code or executable form under the terms of\n"
|
||||
"Sections 1 and 2 above provided that you also do one of the following:\n"
|
||||
"\n"
|
||||
" a) Accompany it with the complete corresponding machine-readable\n"
|
||||
" source code, which must be distributed under the terms of Sections\n"
|
||||
" 1 and 2 above on a medium customarily used for software interchange; or,\n"
|
||||
"\n"
|
||||
" b) Accompany it with a written offer, valid for at least three\n"
|
||||
" years, to give any third party, for a charge no more than your\n"
|
||||
" cost of physically performing source distribution, a complete\n"
|
||||
" machine-readable copy of the corresponding source code, to be\n"
|
||||
" distributed under the terms of Sections 1 and 2 above on a medium\n"
|
||||
" customarily used for software interchange; or,\n"
|
||||
"\n"
|
||||
" c) Accompany it with the information you received as to the offer\n"
|
||||
" to distribute corresponding source code. (This alternative is\n"
|
||||
" allowed only for noncommercial distribution and only if you\n"
|
||||
" received the program in object code or executable form with such\n"
|
||||
" an offer, in accord with Subsection b above.)\n"
|
||||
"\n"
|
||||
"The source code for a work means the preferred form of the work for\n"
|
||||
"making modifications to it. For an executable work, complete source\n"
|
||||
"code means all the source code for all modules it contains, plus any\n"
|
||||
"associated interface definition files, plus the scripts used to\n"
|
||||
"control compilation and installation of the executable. However, as a\n"
|
||||
"special exception, the source code distributed need not include\n"
|
||||
"anything that is normally distributed (in either source or binary\n"
|
||||
"form) with the major components (compiler, kernel, and so on) of the\n"
|
||||
"operating system on which the executable runs, unless that component\n"
|
||||
"itself accompanies the executable.\n"
|
||||
"\n"
|
||||
"If distribution of executable or object code is made by offering\n"
|
||||
"access to copy from a designated place, then offering equivalent\n"
|
||||
"access to copy the source code from the same place counts as\n"
|
||||
"distribution of the source code, even though third parties are not\n"
|
||||
"compelled to copy the source along with the object code.\n"
|
||||
"\n"
|
||||
" 4. You may not copy, modify, sublicense, or distribute the Program\n"
|
||||
"except as expressly provided under this License. Any attempt\n"
|
||||
"otherwise to copy, modify, sublicense or distribute the Program is\n"
|
||||
"void, and will automatically terminate your rights under this License.\n"
|
||||
"However, parties who have received copies, or rights, from you under\n"
|
||||
"this License will not have their licenses terminated so long as such\n"
|
||||
"parties remain in full compliance.\n"
|
||||
"\n"
|
||||
" 5. You are not required to accept this License, since you have not\n"
|
||||
"signed it. However, nothing else grants you permission to modify or\n"
|
||||
"distribute the Program or its derivative works. These actions are\n"
|
||||
"prohibited by law if you do not accept this License. Therefore, by\n"
|
||||
"modifying or distributing the Program (or any work based on the\n"
|
||||
"Program), you indicate your acceptance of this License to do so, and\n"
|
||||
"all its terms and conditions for copying, distributing or modifying\n"
|
||||
"the Program or works based on it.\n"
|
||||
"\n"
|
||||
" 6. Each time you redistribute the Program (or any work based on the\n"
|
||||
"Program), the recipient automatically receives a license from the\n"
|
||||
"original licensor to copy, distribute or modify the Program subject to\n"
|
||||
"these terms and conditions. You may not impose any further\n"
|
||||
"restrictions on the recipients' exercise of the rights granted herein.\n"
|
||||
"You are not responsible for enforcing compliance by third parties to\n"
|
||||
"this License.\n"
|
||||
"\n"
|
||||
" 7. If, as a consequence of a court judgment or allegation of patent\n"
|
||||
"infringement or for any other reason (not limited to patent issues),\n"
|
||||
"conditions are imposed on you (whether by court order, agreement or\n"
|
||||
"otherwise) that contradict the conditions of this License, they do not\n"
|
||||
"excuse you from the conditions of this License. If you cannot\n"
|
||||
"distribute so as to satisfy simultaneously your obligations under this\n"
|
||||
"License and any other pertinent obligations, then as a consequence you\n"
|
||||
"may not distribute the Program at all. For example, if a patent\n"
|
||||
"license would not permit royalty-free redistribution of the Program by\n"
|
||||
"all those who receive copies directly or indirectly through you, then\n"
|
||||
"the only way you could satisfy both it and this License would be to\n"
|
||||
"refrain entirely from distribution of the Program.\n"
|
||||
"\n"
|
||||
"If any portion of this section is held invalid or unenforceable under\n"
|
||||
"any particular circumstance, the balance of the section is intended to\n"
|
||||
"apply and the section as a whole is intended to apply in other\n"
|
||||
"circumstances.\n"
|
||||
"\n"
|
||||
"It is not the purpose of this section to induce you to infringe any\n"
|
||||
"patents or other property right claims or to contest validity of any\n"
|
||||
"such claims; this section has the sole purpose of protecting the\n"
|
||||
"integrity of the free software distribution system, which is\n"
|
||||
"implemented by public license practices. Many people have made\n"
|
||||
"generous contributions to the wide range of software distributed\n"
|
||||
"through that system in reliance on consistent application of that\n"
|
||||
"system; it is up to the author/donor to decide if he or she is willing\n"
|
||||
"to distribute software through any other system and a licensee cannot\n"
|
||||
"impose that choice.\n"
|
||||
"\n"
|
||||
"This section is intended to make thoroughly clear what is believed to\n"
|
||||
"be a consequence of the rest of this License.\n"
|
||||
"\n"
|
||||
" 8. If the distribution and/or use of the Program is restricted in\n"
|
||||
"certain countries either by patents or by copyrighted interfaces, the\n"
|
||||
"original copyright holder who places the Program under this License\n"
|
||||
"may add an explicit geographical distribution limitation excluding\n"
|
||||
"those countries, so that distribution is permitted only in or among\n"
|
||||
"countries not thus excluded. In such case, this License incorporates\n"
|
||||
"the limitation as if written in the body of this License.\n"
|
||||
"\n"
|
||||
" 9. The Free Software Foundation may publish revised and/or new versions\n"
|
||||
"of the General Public License from time to time. Such new versions will\n"
|
||||
"be similar in spirit to the present version, but may differ in detail to\n"
|
||||
"address new problems or concerns.\n"
|
||||
"\n"
|
||||
"Each version is given a distinguishing version number. If the Program\n"
|
||||
"specifies a version number of this License which applies to it and \"any\n"
|
||||
"later version\", you have the option of following the terms and conditions\n"
|
||||
"either of that version or of any later version published by the Free\n"
|
||||
"Software Foundation. If the Program does not specify a version number of\n"
|
||||
"this License, you may choose any version ever published by the Free Software\n"
|
||||
"Foundation.\n"
|
||||
"\n"
|
||||
" 10. If you wish to incorporate parts of the Program into other free\n"
|
||||
"programs whose distribution conditions are different, write to the author\n"
|
||||
"to ask for permission. For software which is copyrighted by the Free\n"
|
||||
"Software Foundation, write to the Free Software Foundation; we sometimes\n"
|
||||
"make exceptions for this. Our decision will be guided by the two goals\n"
|
||||
"of preserving the free status of all derivatives of our free software and\n"
|
||||
"of promoting the sharing and reuse of software generally.\n"
|
||||
"\n"
|
||||
" NO WARRANTY\n"
|
||||
"\n"
|
||||
" 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n"
|
||||
"FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN\n"
|
||||
"OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n"
|
||||
"PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n"
|
||||
"OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n"
|
||||
"MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS\n"
|
||||
"TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE\n"
|
||||
"PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n"
|
||||
"REPAIR OR CORRECTION.\n"
|
||||
"\n"
|
||||
" 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n"
|
||||
"WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n"
|
||||
"REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n"
|
||||
"INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n"
|
||||
"OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n"
|
||||
"TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n"
|
||||
"YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n"
|
||||
"PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n"
|
||||
"POSSIBILITY OF SUCH DAMAGES.\n"
|
||||
"\n"
|
||||
" END OF TERMS AND CONDITIONS\n"
|
||||
"\n"
|
||||
" How to Apply These Terms to Your New Programs\n"
|
||||
"\n"
|
||||
" If you develop a new program, and you want it to be of the greatest\n"
|
||||
"possible use to the public, the best way to achieve this is to make it\n"
|
||||
"free software which everyone can redistribute and change under these terms.\n"
|
||||
"\n"
|
||||
" To do so, attach the following notices to the program. It is safest\n"
|
||||
"to attach them to the start of each source file to most effectively\n"
|
||||
"convey the exclusion of warranty; and each file should have at least\n"
|
||||
"the \"copyright\" line and a pointer to where the full notice is found.\n"
|
||||
"\n"
|
||||
" <one line to give the program's name and a brief idea of what it does.>\n"
|
||||
" Copyright (C) <year> <name of author>\n"
|
||||
"\n"
|
||||
" This program is free software; you can redistribute it and/or modify\n"
|
||||
" it under the terms of the GNU General Public License as published by\n"
|
||||
" the Free Software Foundation; either version 2 of the License, or\n"
|
||||
" (at your option) any later version.\n"
|
||||
"\n"
|
||||
" This program is distributed in the hope that it will be useful,\n"
|
||||
" but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
|
||||
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
|
||||
" GNU General Public License for more details.\n"
|
||||
"\n"
|
||||
" You should have received a copy of the GNU General Public License along\n"
|
||||
" with this program; if not, write to the Free Software Foundation, Inc.,\n"
|
||||
" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n"
|
||||
"\n"
|
||||
"Also add information on how to contact you by electronic and paper mail.\n"
|
||||
"\n"
|
||||
"If the program is interactive, make it output a short notice like this\n"
|
||||
"when it starts in an interactive mode:\n"
|
||||
"\n"
|
||||
" Gnomovision version 69, Copyright (C) year name of author\n"
|
||||
" Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n"
|
||||
" This is free software, and you are welcome to redistribute it\n"
|
||||
" under certain conditions; type `show c' for details.\n"
|
||||
"\n"
|
||||
"The hypothetical commands `show w' and `show c' should show the appropriate\n"
|
||||
"parts of the General Public License. Of course, the commands you use may\n"
|
||||
"be called something other than `show w' and `show c'; they could even be\n"
|
||||
"mouse-clicks or menu items--whatever suits your program.\n"
|
||||
"\n"
|
||||
"You should also get your employer (if you work as a programmer) or your\n"
|
||||
"school, if any, to sign a \"copyright disclaimer\" for the program, if\n"
|
||||
"necessary. Here is a sample; alter the names:\n"
|
||||
"\n"
|
||||
" Yoyodyne, Inc., hereby disclaims all copyright interest in the program\n"
|
||||
" `Gnomovision' (which makes passes at compilers) written by James Hacker.\n"
|
||||
"\n"
|
||||
" <signature of Ty Coon>, 1 April 1989\n"
|
||||
" Ty Coon, President of Vice\n"
|
||||
"\n"
|
||||
"This General Public License does not permit incorporating your program into\n"
|
||||
"proprietary programs. If your program is a subroutine library, you may\n"
|
||||
"consider it more useful to permit linking proprietary applications with the\n"
|
||||
"library. If this is what you want to do, use the GNU Lesser General\n"
|
||||
"Public License instead of this License.\n"
|
43
Makefile
|
@ -3,16 +3,19 @@
|
|||
#
|
||||
|
||||
srcdir=.
|
||||
CFLAGS=-g -I/usr/local/include
|
||||
LDFLAGS=-L/usr/local/lib
|
||||
COMPILE_FLAGS=${CFLAGS} -Wall -Wextra -Wno-deprecated-declarations -fno-strict-aliasing -fno-omit-frame-pointer -ggdb
|
||||
CFLAGS=-g -Wall -Wextra -Werror -Wno-unused-parameter
|
||||
LDFLAGS=-L/usr/local/lib
|
||||
CPPFLAGS=-I/usr/local/include -Itg
|
||||
DEFS=
|
||||
COMPILE_FLAGS=${CFLAGS} ${CPPFLAGS} ${DEFS} -Wall -Wextra -Wno-deprecated-declarations -fno-strict-aliasing -fno-omit-frame-pointer -ggdb
|
||||
EXTRA_LIBS=-lcrypto -lz -lm
|
||||
|
||||
HEADERS= ${srcdir}/constants.h ${srcdir}/include.h ${srcdir}/LICENSE.h ${srcdir}/loop.h ${srcdir}/mtproto-client.h ${srcdir}/net.h ${srcdir}/queries.h ${srcdir}/structures.h ${srcdir}/no-preview.h ${srcdir}/telegram.h ${srcdir}/tree.h ${srcdir}/binlog.h ${srcdir}/tools.h ${srcdir}/msglog.h
|
||||
LOCAL_LDFLAGS=-rdynamic -ggdb ${EXTRA_LIBS}
|
||||
LINK_FLAGS=${LDFLAGS} ${LOCAL_LDFLAGS}
|
||||
|
||||
INCLUDE=-I. -I${srcdir}
|
||||
CC=cc
|
||||
OBJECTS=loop.o net.o mtproto-common.o mtproto-client.o queries.o structures.o binlog.o tools.o msglog.o telegram.o
|
||||
OBJECTS=tgp-net.o tgp-timers.o msglog.o telegram-base.o
|
||||
|
||||
.SUFFIXES:
|
||||
|
||||
.SUFFIXES: .c .h .o
|
||||
|
@ -37,7 +40,7 @@ else
|
|||
endif
|
||||
|
||||
LD = $(CC)
|
||||
PRPL_C_SRCS = purple-plugin/telegram-purple.c
|
||||
PRPL_C_SRCS = telegram-purple.c
|
||||
PRPL_C_OBJS = $(PRPL_C_SRCS:.c=.o)
|
||||
PRPL_LIBNAME = telegram-purple.so
|
||||
PRPL_INCLUDE = -I. -I./purple-plugin
|
||||
|
@ -46,8 +49,8 @@ STRIP = strip
|
|||
PRPL_CFLAGS = \
|
||||
$(ARCHFLAGS) \
|
||||
-fPIC \
|
||||
-DPIC \
|
||||
-DPURPLE_PLUGINS \
|
||||
-DPIC \
|
||||
-DDEBUG \
|
||||
-g \
|
||||
$(CFLAGS_PURPLE)
|
||||
|
@ -59,30 +62,38 @@ PRPL_CFLAGS = \
|
|||
.c.o :
|
||||
${CC} -fPIC -DPIC ${CFLAGS_PURPLE} ${COMPILE_FLAGS} ${INCLUDE} -c $< -o $@
|
||||
|
||||
${OBJECTS}: ${HEADERS}
|
||||
# ${OBJECTS}: ${HEADERS}
|
||||
|
||||
#telegram: ${OBJECTS}
|
||||
# ${CC} ${OBJECTS} ${LINK_FLAGS} -o $@
|
||||
|
||||
#
|
||||
# Plugin Objects
|
||||
#
|
||||
|
||||
$(PRPL_C_OBJS): $(PRPL_C_SRCS)
|
||||
$(CC) -c $(PRPL_INCLUDE) $(PRPL_CFLAGS) $(CFLAGS) $(CPPFLAGS) -o $@ $<
|
||||
$(CC) -c $(PRPL_INCLUDE) $(PRPL_CFLAGS) $(CFLAGS) $(CPPFLAGS) -ggdb -o $@ $<
|
||||
|
||||
$(PRPL_LIBNAME): $(OBJECTS) $(PRPL_C_OBJS)
|
||||
$(LD) $(PRPL_LDFLAGS) $(LDFLAGS) $(PRPL_INCLUDE) -o $@ $(PRPL_C_OBJS) $(OBJECTS) $(LIBS_PURPLE) $(EXTRA_LIBS)
|
||||
$(PRPL_LIBNAME): $(OBJECTS) $(PRPL_C_OBJS) tg/libs/libtgl.a
|
||||
$(LD) $(PRPL_LDFLAGS) $(LDFLAGS) $(PRPL_INCLUDE) $(LIBS_PURPLE) $(EXTRA_LIBS) -o $@ $^
|
||||
|
||||
.PHONY: all
|
||||
all: ${PRPL_LIBNAME}
|
||||
|
||||
plugin: $(PRPL_LIBNAME)
|
||||
|
||||
all: $(PRPL_LIBNAME)
|
||||
|
||||
.PHONY: strip
|
||||
strip: $(PRPL_LIBNAME)
|
||||
$(STRIP) --strip-unneeded $(PRPL_LIBNAME)
|
||||
|
||||
# TODO: Find a better place for server.pub
|
||||
install: $(PRPL_LIBNAME)
|
||||
install -D $(PRPL_LIBNAME) $(DESTDIR)$(PLUGIN_DIR_PURPLE)/$(PRPL_LIBNAME)
|
||||
install -D tg-server.pub /etc/telegram-purple/server.pub
|
||||
install -D purple-plugin/telegram16.png $(DESTDIR)$(DATA_ROOT_DIR_PURPLE)/pixmaps/pidgin/protocols/16/telegram.png
|
||||
install -D purple-plugin/telegram22.png $(DESTDIR)$(DATA_ROOT_DIR_PURPLE)/pixmaps/pidgin/protocols/22/telegram.png
|
||||
install -D purple-plugin/telegram48.png $(DESTDIR)$(DATA_ROOT_DIR_PURPLE)/pixmaps/pidgin/protocols/48/telegram.png
|
||||
install -D imgs/telegram16.png $(DESTDIR)$(DATA_ROOT_DIR_PURPLE)/pixmaps/pidgin/protocols/16/telegram.png
|
||||
install -D imgs/telegram22.png $(DESTDIR)$(DATA_ROOT_DIR_PURPLE)/pixmaps/pidgin/protocols/22/telegram.png
|
||||
install -D imgs/telegram48.png $(DESTDIR)$(DATA_ROOT_DIR_PURPLE)/pixmaps/pidgin/protocols/48/telegram.png
|
||||
|
||||
.PHONY: uninstall
|
||||
uninstall:
|
||||
|
|
15
README.md
|
@ -11,6 +11,10 @@ Warning, this version is mainly for development and testing and NOT for producti
|
|||
|
||||
When encountering a crash or some other bugs, please report it to us, preferably together with a backtrace of the crashed application [https://developer.pidgin.im/wiki/GetABacktrace]
|
||||
|
||||
## Version 0.4
|
||||
|
||||
- Use latest version of libtgl
|
||||
|
||||
## Version 0.3.3
|
||||
|
||||
- multiple bugfixes
|
||||
|
@ -70,8 +74,14 @@ Unfortunately there are no packages right now, so you need to compile it yoursel
|
|||
|
||||
git clone https://github.com/majn/telegram-purple
|
||||
|
||||
## 2. Get libtgl to tg subfolder
|
||||
|
||||
cd telegram-purple
|
||||
git clone https://github.com/vysheng/tg
|
||||
|
||||
## 2. Fetch all needed dependencies
|
||||
|
||||
|
||||
## 3. Fetch all needed dependencies
|
||||
|
||||
This plugin depends on a working libpurple client (like Pidgin or Finch) and the following packages:
|
||||
|
||||
|
@ -143,8 +153,7 @@ This bundle was tested to work under OSX 10.9 and 10.8. If it doesn't work on yo
|
|||
please send your Adium crash log (which you can find in ~/Library/Logs/Adium 2/).
|
||||
|
||||
[Version 0.3.2](http://lauschgift.org/telegram-purple/telegram-adium-0.3.2.zip)
|
||||
|
||||
[Version 0.3.3](http://lauschgift.org/telegram-purple/telegram-adium-0.3.3.zip)
|
||||
[Version 0.3.2](http://lauschgift.org/telegram-purple/telegram-adium-0.3.3.zip)
|
||||
|
||||
## Build with XCode
|
||||
|
||||
|
|
150
binlog.h
|
@ -1,150 +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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright Vitaly Valtman 2013
|
||||
*/
|
||||
#ifndef __BINLOG_H__
|
||||
#define __BINLOG_H__
|
||||
|
||||
#include "structures.h"
|
||||
#include "telegram.h"
|
||||
|
||||
#define LOG_START 0x8948329a
|
||||
#define LOG_AUTH_KEY 0x984932aa
|
||||
#define LOG_DEFAULT_DC 0x95382908
|
||||
#define LOG_OUR_ID 0x8943211a
|
||||
#define LOG_DC_SIGNED 0x234f9893
|
||||
#define LOG_DC_SALT 0x92192ffa
|
||||
#define LOG_DH_CONFIG 0x8983402b
|
||||
#define LOG_ENCR_CHAT_KEY 0x894320aa
|
||||
#define LOG_ENCR_CHAT_SEND_ACCEPT 0x12ab01c4
|
||||
#define LOG_ENCR_CHAT_SEND_CREATE 0xab091e24
|
||||
#define LOG_ENCR_CHAT_DELETED 0x99481230
|
||||
#define LOG_ENCR_CHAT_WAITING 0x7102100a
|
||||
#define LOG_ENCR_CHAT_REQUESTED 0x9011011a
|
||||
#define LOG_ENCR_CHAT_OK 0x7612ce13
|
||||
|
||||
#define CODE_binlog_new_user 0xe04f30de
|
||||
#define CODE_binlog_user_delete 0xf7a27c79
|
||||
#define CODE_binlog_set_user_access_token 0x1349f615
|
||||
#define CODE_binlog_set_user_phone 0x5d3afde2
|
||||
#define CODE_binlog_set_user_friend 0x75a7ec5a
|
||||
#define CODE_binlog_dc_option 0x08c0ef19
|
||||
#define CODE_binlog_user_full_photo 0xfaa35824
|
||||
#define CODE_binlog_user_blocked 0xb2dea7cd
|
||||
#define CODE_binlog_set_user_full_name 0x4ceb4cf0
|
||||
#define CODE_binlog_encr_chat_delete 0xb9d33f87
|
||||
#define CODE_binlog_encr_chat_requested 0xf57d1ea2
|
||||
#define CODE_binlog_set_encr_chat_access_hash 0xe5612bb3
|
||||
#define CODE_binlog_set_encr_chat_date 0x54f16911
|
||||
#define CODE_binlog_set_encr_chat_state 0x76a6e45b
|
||||
#define CODE_binlog_encr_chat_accepted 0x4627e926
|
||||
#define CODE_binlog_set_encr_chat_key 0x179df2d4
|
||||
#define CODE_binlog_set_dh_params 0x20ba46bc
|
||||
#define CODE_binlog_encr_chat_init 0x939cd1c7
|
||||
#define CODE_binlog_set_pts 0x844e4c1c
|
||||
#define CODE_binlog_set_qts 0x3cf22b79
|
||||
#define CODE_binlog_set_date 0x33dfe392
|
||||
#define CODE_binlog_set_seq 0xb9294837
|
||||
#define CODE_binlog_chat_create 0xbaa75791
|
||||
#define CODE_binlog_chat_change_flags 0x1e494031
|
||||
#define CODE_binlog_set_chat_title 0x7dd9bea8
|
||||
#define CODE_binlog_set_chat_photo 0xb4ea1fd2
|
||||
#define CODE_binlog_set_chat_date 0x78d1114e
|
||||
#define CODE_binlog_set_chat_version 0xa5d3504f
|
||||
#define CODE_binlog_set_chat_admin 0x1e7cea04
|
||||
#define CODE_binlog_set_chat_participants 0x3a29d335
|
||||
#define CODE_binlog_chat_full_photo 0x6cca6629
|
||||
#define CODE_binlog_add_chat_participant 0x63345108
|
||||
#define CODE_binlog_del_chat_participant 0x82d1f0ee
|
||||
#define CODE_binlog_create_message_text 0x269acd5b
|
||||
#define CODE_binlog_create_message_text_fwd 0xa3d864cd
|
||||
#define CODE_binlog_create_message_service 0xbbe5e94b
|
||||
#define CODE_binlog_create_message_service_fwd 0xea9c57ae
|
||||
#define CODE_binlog_create_message_media 0x62a92d19
|
||||
#define CODE_binlog_create_message_media_fwd 0xbefdc462
|
||||
#define CODE_binlog_send_message_text 0x31cfd652
|
||||
#define CODE_binlog_set_unread 0x21d4c909
|
||||
#define CODE_binlog_set_message_sent 0xc335282b
|
||||
#define CODE_binlog_set_msg_id 0xf3285b6a
|
||||
#define CODE_binlog_create_message_media_encr 0x19cd7c9d
|
||||
#define CODE_binlog_create_message_service_encr 0x8b4b9395
|
||||
#define CODE_binlog_delete_msg 0xa1d6ab6d
|
||||
|
||||
void *alloc_log_event (struct binlog *bl, int l);
|
||||
void add_log_event (struct binlog *bl, struct mtproto_connection *self, const int *data, int l);
|
||||
void write_binlog (struct binlog *bl);
|
||||
void bl_do_set_auth_key_id (struct telegram *instance, int num, unsigned char *buf);
|
||||
|
||||
void bl_do_dc_option (struct binlog *bl, struct mtproto_connection *self, int id, int l1, const char *name, int l2, const char *ip, int port, struct telegram *instance);
|
||||
|
||||
void bl_do_set_our_id (struct binlog *bl, struct mtproto_connection *self, int id);
|
||||
void bl_do_new_user (struct binlog *bl, struct mtproto_connection *self, int id, const char *f, int fl, const char *l, int ll, long long access_token, const char *p, int pl, int contact);
|
||||
void bl_do_user_delete (struct binlog *bl, struct mtproto_connection *self, struct tgl_user *U);
|
||||
void bl_do_set_user_profile_photo (struct binlog *bl, struct mtproto_connection *self, struct tgl_user *U, long long photo_id, struct file_location *big, struct file_location *small);
|
||||
void bl_do_set_user_name (struct binlog *bl, struct mtproto_connection *self, struct tgl_user *U, const char *f, int fl, const char *l, int ll);
|
||||
void bl_do_set_user_access_token (struct binlog *bl, struct mtproto_connection *self, struct tgl_user *U, long long access_token);
|
||||
void bl_do_set_user_phone (struct binlog *bl, struct mtproto_connection *self, struct tgl_user *U, const char *p, int pl);
|
||||
void bl_do_set_user_friend (struct binlog *bl, struct mtproto_connection *self, struct tgl_user *U, int friend);
|
||||
void bl_do_set_user_full_photo (struct binlog *bl, struct mtproto_connection *self, struct tgl_user *U, const int *start, int len);
|
||||
void bl_do_set_user_blocked (struct binlog *bl, struct mtproto_connection *self, struct tgl_user *U, int blocked);
|
||||
void bl_do_set_user_real_name (struct binlog *bl, struct mtproto_connection *self, struct tgl_user *U, const char *f, int fl, const char *l, int ll);
|
||||
|
||||
void bl_do_encr_chat_delete (struct binlog *bl, struct mtproto_connection *self, struct secret_chat *U);
|
||||
void bl_do_encr_chat_requested (struct binlog *bl, struct mtproto_connection *self, struct secret_chat *U, long long access_hash, int date, int admin_id, int user_id, unsigned char g_key[], unsigned char nonce[]);
|
||||
void bl_do_set_encr_chat_access_hash (struct binlog *bl, struct mtproto_connection *self, struct secret_chat *U, long long access_hash);
|
||||
void bl_do_set_encr_chat_date (struct binlog *bl, struct mtproto_connection *self, struct secret_chat *U, int date);
|
||||
void bl_do_set_encr_chat_state (struct binlog *bl, struct mtproto_connection *self, struct secret_chat *U, enum secret_chat_state state);
|
||||
void bl_do_encr_chat_accepted (struct binlog *bl, struct mtproto_connection *self, struct secret_chat *U, const unsigned char g_key[], const unsigned char nonce[], long long key_fingerprint);
|
||||
void bl_do_set_encr_chat_key (struct binlog *bl, struct mtproto_connection *self, struct secret_chat *E, unsigned char key[], long long key_fingerprint);
|
||||
void bl_do_encr_chat_init (struct binlog *bl, struct mtproto_connection *self, int id, int user_id, unsigned char random[], unsigned char g_a[]);
|
||||
|
||||
void bl_do_dc_signed (struct binlog *bl, struct mtproto_connection *self, int id);
|
||||
void bl_do_set_working_dc (struct binlog *bl, struct mtproto_connection *self, int num);
|
||||
void bl_do_set_dh_params (struct binlog *bl, struct mtproto_connection *self, int root, unsigned char prime[], int version);
|
||||
|
||||
void bl_do_set_pts (struct binlog *bl, struct mtproto_connection *self, int pts);
|
||||
void bl_do_set_qts (struct binlog *bl, struct mtproto_connection *self, int qts);
|
||||
void bl_do_set_seq (struct binlog *bl, struct mtproto_connection *self, int seq);
|
||||
void bl_do_set_date (struct binlog *bl, struct mtproto_connection *self, int date);
|
||||
|
||||
void bl_do_create_chat (struct binlog *bl, struct mtproto_connection *self, struct chat *C, int y, const char *s, int l, int users_num, int date, int version, struct file_location *big, struct file_location *small);
|
||||
void bl_do_chat_forbid (struct binlog *bl, struct mtproto_connection *self, struct chat *C, int on);
|
||||
void bl_do_set_chat_title (struct binlog *bl, struct mtproto_connection *self, struct chat *C, const char *s, int l);
|
||||
void bl_do_set_chat_photo (struct binlog *bl, struct mtproto_connection *self, struct chat *C, struct file_location *big, struct file_location *small);
|
||||
void bl_do_set_chat_date (struct binlog *bl, struct mtproto_connection *self, struct chat *C, int date);
|
||||
void bl_do_set_chat_set_in_chat (struct binlog *bl, struct mtproto_connection *self, struct chat *C, int on);
|
||||
void bl_do_set_chat_version (struct binlog *bl, struct mtproto_connection *self, struct chat *C, int version, int user_num);
|
||||
void bl_do_set_chat_admin (struct binlog *bl, struct mtproto_connection *self, struct chat *C, int admin);
|
||||
void bl_do_set_chat_participants (struct binlog *bl, struct mtproto_connection *self, struct chat *C, int version, int user_num, struct chat_user *users);
|
||||
void bl_do_set_chat_full_photo (struct binlog *bl, struct mtproto_connection *self, struct chat *U, const int *start, int len);
|
||||
void bl_do_chat_add_user (struct binlog *bl, struct mtproto_connection *self, struct chat *C, int version, int user, int inviter, int date);
|
||||
void bl_do_chat_del_user (struct binlog *bl, struct mtproto_connection *self, struct chat *C, int version, int user);
|
||||
|
||||
void bl_do_create_message_text (struct binlog *bl, struct mtproto_connection *self, int msg_id, int from_id, int to_type, int to_id, int date, int l, const char *s);
|
||||
void bl_do_create_message_text_fwd (struct binlog *bl, struct mtproto_connection *self, int msg_id, int from_id, int to_type, int to_id, int date, int fwd, int fwd_date, int l, const char *s);
|
||||
void bl_do_create_message_service (struct binlog *bl, struct mtproto_connection *self, int msg_id, int from_id, int to_type, int to_id, int date, const int *data, int len);
|
||||
void bl_do_create_message_service_fwd (struct binlog *bl, struct mtproto_connection *self, int msg_id, int from_id, int to_type, int to_id, int date, int fwd, int fwd_date, const int *data, int len);
|
||||
void bl_do_create_message_media (struct binlog *bl, struct mtproto_connection *self, int msg_id, int from_id, int to_type, int to_id, int date, int l, const char *s, const int *data, int len);
|
||||
void bl_do_create_message_media_fwd (struct binlog *bl, struct mtproto_connection *self, int msg_id, int from_id, int to_type, int to_id, int date, int fwd, int fwd_date, int l, const char *s, const int *data, int len);
|
||||
void bl_do_create_message_media_encr (struct binlog *bl, struct mtproto_connection *self, long long msg_id, int from_id, int to_type, int to_id, int date, int l, const char *s, const int *data, int len, const int *data2, int len2);
|
||||
void bl_do_create_message_service_encr (struct binlog *bl, struct mtproto_connection *self, long long msg_id, int from_id, int to_type, int to_id, int date, const int *data, int len);
|
||||
void bl_do_send_message_text (struct binlog *bl, struct mtproto_connection *self, long long msg_id, int from_id, int to_type, int to_id, int date, int l, const char *s);
|
||||
void bl_do_set_unread (struct binlog *bl, struct mtproto_connection *self, struct message *M, int unread);
|
||||
void bl_do_set_message_sent (struct binlog *bl, struct mtproto_connection *self, struct message *M);
|
||||
void bl_do_set_msg_id (struct binlog *bl, struct mtproto_connection *self, struct message *M, int id);
|
||||
void bl_do_delete_msg (struct binlog *bl, struct mtproto_connection *self, struct message *M);
|
||||
#endif
|
10
binlog.tl
|
@ -1,10 +0,0 @@
|
|||
log.peer peer_type:int peer_id:int = log.Peer;
|
||||
|
||||
log.dc num:int hostname:string ip:string port:int = log.Event;
|
||||
log.dcRenum old_num:int new_num:int = log.Event;
|
||||
log.authKey dc:int key:bytes key_id:long = log.Event;
|
||||
log.signIn dc:int id:int = log.Event;
|
||||
|
||||
|
||||
log.user id:int flags:int access_hash:long first_name:string last_name:string real_first_name:string real_last_name:string phone:string photo:log.Photo photo_id:long photo_big:log.FileLocation photo_small:long.FileLocation = log.Event;
|
||||
|
383
constants.h
|
@ -1,383 +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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright Vitaly Valtman 2013
|
||||
*/
|
||||
#ifndef CONSTANTS_H
|
||||
#define CONSTANTS_H
|
||||
#define CODE_bool_false 0xbc799737
|
||||
#define CODE_bool_true 0x997275b5
|
||||
#define CODE_vector 0x1cb5c415
|
||||
#define CODE_error 0xc4b9f9bb
|
||||
#define CODE_null 0x56730bcc
|
||||
#define CODE_input_peer_empty 0x7f3b18ea
|
||||
#define CODE_input_peer_self 0x7da07ec9
|
||||
#define CODE_input_peer_contact 0x1023dbe8
|
||||
#define CODE_input_peer_foreign 0x9b447325
|
||||
#define CODE_input_peer_chat 0x179be863
|
||||
#define CODE_input_user_empty 0xb98886cf
|
||||
#define CODE_input_user_self 0xf7c1b13f
|
||||
#define CODE_input_user_contact 0x86e94f65
|
||||
#define CODE_input_user_foreign 0x655e74ff
|
||||
#define CODE_input_phone_contact 0xf392b7f4
|
||||
#define CODE_input_file 0xf52ff27f
|
||||
#define CODE_input_media_empty 0x9664f57f
|
||||
#define CODE_input_media_uploaded_photo 0x2dc53a7d
|
||||
#define CODE_input_media_photo 0x8f2ab2ec
|
||||
#define CODE_input_media_geo_point 0xf9c44144
|
||||
#define CODE_input_media_contact 0xa6e45987
|
||||
#define CODE_input_media_uploaded_video 0x4847d92a
|
||||
#define CODE_input_media_uploaded_thumb_video 0xe628a145
|
||||
#define CODE_input_media_video 0x7f023ae6
|
||||
#define CODE_input_chat_photo_empty 0x1ca48f57
|
||||
#define CODE_input_chat_uploaded_photo 0x94254732
|
||||
#define CODE_input_chat_photo 0xb2e1bf08
|
||||
#define CODE_input_geo_point_empty 0xe4c123d6
|
||||
#define CODE_input_geo_point 0xf3b7acc9
|
||||
#define CODE_input_photo_empty 0x1cd7bf0d
|
||||
#define CODE_input_photo 0xfb95c6c4
|
||||
#define CODE_input_video_empty 0x5508ec75
|
||||
#define CODE_input_video 0xee579652
|
||||
#define CODE_input_file_location 0x14637196
|
||||
#define CODE_input_video_file_location 0x3d0364ec
|
||||
#define CODE_input_photo_crop_auto 0xade6b004
|
||||
#define CODE_input_photo_crop 0xd9915325
|
||||
#define CODE_input_app_event 0x770656a8
|
||||
#define CODE_peer_user 0x9db1bc6d
|
||||
#define CODE_peer_chat 0xbad0e5bb
|
||||
#define CODE_storage_file_unknown 0xaa963b05
|
||||
#define CODE_storage_file_jpeg 0x7efe0e
|
||||
#define CODE_storage_file_gif 0xcae1aadf
|
||||
#define CODE_storage_file_png 0xa4f63c0
|
||||
#define CODE_storage_file_mp3 0x528a0677
|
||||
#define CODE_storage_file_mov 0x4b09ebbc
|
||||
#define CODE_storage_file_partial 0x40bc6f52
|
||||
#define CODE_storage_file_mp4 0xb3cea0e4
|
||||
#define CODE_storage_file_webp 0x1081464c
|
||||
#define CODE_file_location_unavailable 0x7c596b46
|
||||
#define CODE_file_location 0x53d69076
|
||||
#define CODE_user_empty 0x200250ba
|
||||
#define CODE_user_self 0x720535ec
|
||||
#define CODE_user_contact 0xf2fb8319
|
||||
#define CODE_user_request 0x22e8ceb0
|
||||
#define CODE_user_foreign 0x5214c89d
|
||||
#define CODE_user_deleted 0xb29ad7cc
|
||||
#define CODE_user_profile_photo_empty 0x4f11bae1
|
||||
#define CODE_user_profile_photo 0xd559d8c8
|
||||
#define CODE_user_status_empty 0x9d05049
|
||||
#define CODE_user_status_online 0xedb93949
|
||||
#define CODE_user_status_offline 0x8c703f
|
||||
#define CODE_chat_empty 0x9ba2d800
|
||||
#define CODE_chat 0x6e9c9bc7
|
||||
#define CODE_chat_forbidden 0xfb0ccc41
|
||||
#define CODE_chat_full 0x630e61be
|
||||
#define CODE_chat_participant 0xc8d7493e
|
||||
#define CODE_chat_participants_forbidden 0xfd2bb8a
|
||||
#define CODE_chat_participants 0x7841b415
|
||||
#define CODE_chat_photo_empty 0x37c1011c
|
||||
#define CODE_chat_photo 0x6153276a
|
||||
#define CODE_message_empty 0x83e5de54
|
||||
#define CODE_message 0x22eb6aba
|
||||
#define CODE_message_forwarded 0x5f46804
|
||||
#define CODE_message_service 0x9f8d60bb
|
||||
#define CODE_message_media_empty 0x3ded6320
|
||||
#define CODE_message_media_photo 0xc8c45a2a
|
||||
#define CODE_message_media_video 0xa2d24290
|
||||
#define CODE_message_media_geo 0x56e0d474
|
||||
#define CODE_message_media_contact 0x5e7d2f39
|
||||
#define CODE_message_media_unsupported 0x29632a36
|
||||
#define CODE_message_action_empty 0xb6aef7b0
|
||||
#define CODE_message_action_chat_create 0xa6638b9a
|
||||
#define CODE_message_action_chat_edit_title 0xb5a1ce5a
|
||||
#define CODE_message_action_chat_edit_photo 0x7fcb13a8
|
||||
#define CODE_message_action_chat_delete_photo 0x95e3fbef
|
||||
#define CODE_message_action_chat_add_user 0x5e3cfc4b
|
||||
#define CODE_message_action_chat_delete_user 0xb2ae9b0c
|
||||
#define CODE_dialog 0x214a8cdf
|
||||
#define CODE_photo_empty 0x2331b22d
|
||||
#define CODE_photo 0x22b56751
|
||||
#define CODE_photo_size_empty 0xe17e23c
|
||||
#define CODE_photo_size 0x77bfb61b
|
||||
#define CODE_photo_cached_size 0xe9a734fa
|
||||
#define CODE_video_empty 0xc10658a8
|
||||
#define CODE_video 0x5a04a49f
|
||||
#define CODE_geo_point_empty 0x1117dd5f
|
||||
#define CODE_geo_point 0x2049d70c
|
||||
#define CODE_auth_checked_phone 0xe300cc3b
|
||||
#define CODE_auth_sent_code 0xefed51d9
|
||||
#define CODE_auth_authorization 0xf6b673a4
|
||||
#define CODE_auth_exported_authorization 0xdf969c2d
|
||||
#define CODE_input_notify_peer 0xb8bc5b0c
|
||||
#define CODE_input_notify_users 0x193b4417
|
||||
#define CODE_input_notify_chats 0x4a95e84e
|
||||
#define CODE_input_notify_all 0xa429b886
|
||||
#define CODE_input_peer_notify_events_empty 0xf03064d8
|
||||
#define CODE_input_peer_notify_events_all 0xe86a2c74
|
||||
#define CODE_input_peer_notify_settings 0x46a2ce98
|
||||
#define CODE_peer_notify_events_empty 0xadd53cb3
|
||||
#define CODE_peer_notify_events_all 0x6d1ded88
|
||||
#define CODE_peer_notify_settings_empty 0x70a68512
|
||||
#define CODE_peer_notify_settings 0x8d5e11ee
|
||||
#define CODE_wall_paper 0xccb03657
|
||||
#define CODE_user_full 0x771095da
|
||||
#define CODE_contact 0xf911c994
|
||||
#define CODE_imported_contact 0xd0028438
|
||||
#define CODE_contact_blocked 0x561bc879
|
||||
#define CODE_contact_found 0xea879f95
|
||||
#define CODE_contact_suggested 0x3de191a1
|
||||
#define CODE_contact_status 0xaa77b873
|
||||
#define CODE_chat_located 0x3631cf4c
|
||||
#define CODE_contacts_foreign_link_unknown 0x133421f8
|
||||
#define CODE_contacts_foreign_link_requested 0xa7801f47
|
||||
#define CODE_contacts_foreign_link_mutual 0x1bea8ce1
|
||||
#define CODE_contacts_my_link_empty 0xd22a1c60
|
||||
#define CODE_contacts_my_link_requested 0x6c69efee
|
||||
#define CODE_contacts_my_link_contact 0xc240ebd9
|
||||
#define CODE_contacts_link 0xeccea3f5
|
||||
#define CODE_contacts_contacts 0x6f8b8cb2
|
||||
#define CODE_contacts_contacts_not_modified 0xb74ba9d2
|
||||
#define CODE_contacts_imported_contacts 0xd1cd0a4c
|
||||
#define CODE_contacts_blocked 0x1c138d15
|
||||
#define CODE_contacts_blocked_slice 0x900802a1
|
||||
#define CODE_contacts_found 0x566000e
|
||||
#define CODE_contacts_suggested 0x5649dcc5
|
||||
#define CODE_messages_dialogs 0x15ba6c40
|
||||
#define CODE_messages_dialogs_slice 0x71e094f3
|
||||
#define CODE_messages_messages 0x8c718e87
|
||||
#define CODE_messages_messages_slice 0xb446ae3
|
||||
#define CODE_messages_message_empty 0x3f4e0648
|
||||
#define CODE_messages_message 0xff90c417
|
||||
#define CODE_messages_stated_messages 0x969478bb
|
||||
#define CODE_messages_stated_message 0xd07ae726
|
||||
#define CODE_messages_sent_message 0xd1f4d35c
|
||||
#define CODE_messages_chat 0x40e9002a
|
||||
#define CODE_messages_chats 0x8150cbd8
|
||||
#define CODE_messages_chat_full 0xe5d7d19c
|
||||
#define CODE_messages_affected_history 0xb7de36f2
|
||||
#define CODE_input_messages_filter_empty 0x57e2f66c
|
||||
#define CODE_input_messages_filter_photos 0x9609a51c
|
||||
#define CODE_input_messages_filter_video 0x9fc00e65
|
||||
#define CODE_input_messages_filter_photo_video 0x56e9f0e4
|
||||
#define CODE_update_new_message 0x13abdb3
|
||||
#define CODE_update_message_i_d 0x4e90bfd6
|
||||
#define CODE_update_read_messages 0xc6649e31
|
||||
#define CODE_update_delete_messages 0xa92bfe26
|
||||
#define CODE_update_restore_messages 0xd15de04d
|
||||
#define CODE_update_user_typing 0x6baa8508
|
||||
#define CODE_update_chat_user_typing 0x3c46cfe6
|
||||
#define CODE_update_chat_participants 0x7761198
|
||||
#define CODE_update_user_status 0x1bfbd823
|
||||
#define CODE_update_user_name 0xda22d9ad
|
||||
#define CODE_update_user_photo 0x95313b0c
|
||||
#define CODE_update_contact_registered 0x2575bbb9
|
||||
#define CODE_update_contact_link 0x51a48a9a
|
||||
#define CODE_update_activation 0x6f690963
|
||||
#define CODE_update_new_authorization 0x8f06529a
|
||||
#define CODE_updates_state 0xa56c2a3e
|
||||
#define CODE_updates_difference_empty 0x5d75a138
|
||||
#define CODE_updates_difference 0xf49ca0
|
||||
#define CODE_updates_difference_slice 0xa8fb1981
|
||||
#define CODE_updates_too_long 0xe317af7e
|
||||
#define CODE_update_short_message 0xd3f45784
|
||||
#define CODE_update_short_chat_message 0x2b2fbd4e
|
||||
#define CODE_update_short 0x78d4dec1
|
||||
#define CODE_updates_combined 0x725b04c3
|
||||
#define CODE_updates 0x74ae4240
|
||||
#define CODE_photos_photos 0x8dca6aa5
|
||||
#define CODE_photos_photos_slice 0x15051f54
|
||||
#define CODE_photos_photo 0x20212ca8
|
||||
#define CODE_upload_file 0x96a18d5
|
||||
#define CODE_dc_option 0x2ec2a43c
|
||||
#define CODE_config 0x2e54dd74
|
||||
#define CODE_nearest_dc 0x8e1a1775
|
||||
#define CODE_help_app_update 0x8987f311
|
||||
#define CODE_help_no_app_update 0xc45a6536
|
||||
#define CODE_help_invite_text 0x18cb9f78
|
||||
#define CODE_messages_stated_messages_links 0x3e74f5c6
|
||||
#define CODE_messages_stated_message_link 0xa9af2881
|
||||
#define CODE_messages_sent_message_link 0xe9db4a3f
|
||||
#define CODE_input_geo_chat 0x74d456fa
|
||||
#define CODE_input_notify_geo_chat_peer 0x4d8ddec8
|
||||
#define CODE_geo_chat 0x75eaea5a
|
||||
#define CODE_geo_chat_message_empty 0x60311a9b
|
||||
#define CODE_geo_chat_message 0x4505f8e1
|
||||
#define CODE_geo_chat_message_service 0xd34fa24e
|
||||
#define CODE_geochats_stated_message 0x17b1578b
|
||||
#define CODE_geochats_located 0x48feb267
|
||||
#define CODE_geochats_messages 0xd1526db1
|
||||
#define CODE_geochats_messages_slice 0xbc5863e8
|
||||
#define CODE_message_action_geo_chat_create 0x6f038ebc
|
||||
#define CODE_message_action_geo_chat_checkin 0xc7d53de
|
||||
#define CODE_update_new_geo_chat_message 0x5a68e3f7
|
||||
#define CODE_wall_paper_solid 0x63117f24
|
||||
#define CODE_update_new_encrypted_message 0x12bcbd9a
|
||||
#define CODE_update_encrypted_chat_typing 0x1710f156
|
||||
#define CODE_update_encryption 0xb4a2e88d
|
||||
#define CODE_update_encrypted_messages_read 0x38fe25b7
|
||||
#define CODE_encrypted_chat_empty 0xab7ec0a0
|
||||
#define CODE_encrypted_chat_waiting 0x3bf703dc
|
||||
#define CODE_encrypted_chat_requested 0xc878527e
|
||||
#define CODE_encrypted_chat 0xfa56ce36
|
||||
#define CODE_encrypted_chat_discarded 0x13d6dd27
|
||||
#define CODE_input_encrypted_chat 0xf141b5e1
|
||||
#define CODE_encrypted_file_empty 0xc21f497e
|
||||
#define CODE_encrypted_file 0x4a70994c
|
||||
#define CODE_input_encrypted_file_empty 0x1837c364
|
||||
#define CODE_input_encrypted_file_uploaded 0x64bd0306
|
||||
#define CODE_input_encrypted_file 0x5a17b5e5
|
||||
#define CODE_input_encrypted_file_location 0xf5235d55
|
||||
#define CODE_encrypted_message 0xed18c118
|
||||
#define CODE_encrypted_message_service 0x23734b06
|
||||
#define CODE_decrypted_message_layer 0x99a438cf
|
||||
#define CODE_decrypted_message 0x1f814f1f
|
||||
#define CODE_decrypted_message_service 0xaa48327d
|
||||
#define CODE_decrypted_message_media_empty 0x89f5c4a
|
||||
#define CODE_decrypted_message_media_photo 0x32798a8c
|
||||
#define CODE_decrypted_message_media_video 0x4cee6ef3
|
||||
#define CODE_decrypted_message_media_geo_point 0x35480a59
|
||||
#define CODE_decrypted_message_media_contact 0x588a0a97
|
||||
#define CODE_decrypted_message_action_set_message_t_t_l 0xa1733aec
|
||||
#define CODE_messages_dh_config_not_modified 0xc0e24635
|
||||
#define CODE_messages_dh_config 0x2c221edd
|
||||
#define CODE_messages_sent_encrypted_message 0x560f8935
|
||||
#define CODE_messages_sent_encrypted_file 0x9493ff32
|
||||
#define CODE_input_file_big 0xfa4f0bb5
|
||||
#define CODE_input_encrypted_file_big_uploaded 0x2dc173c8
|
||||
#define CODE_update_chat_participant_add 0x3a0eeb22
|
||||
#define CODE_update_chat_participant_delete 0x6e5f8c22
|
||||
#define CODE_update_dc_options 0x8e5e9873
|
||||
#define CODE_input_media_uploaded_audio 0x61a6d436
|
||||
#define CODE_input_media_audio 0x89938781
|
||||
#define CODE_input_media_uploaded_document 0x34e794bd
|
||||
#define CODE_input_media_uploaded_thumb_document 0x3e46de5d
|
||||
#define CODE_input_media_document 0xd184e841
|
||||
#define CODE_message_media_document 0x2fda2204
|
||||
#define CODE_message_media_audio 0xc6b68300
|
||||
#define CODE_input_audio_empty 0xd95adc84
|
||||
#define CODE_input_audio 0x77d440ff
|
||||
#define CODE_input_document_empty 0x72f0eaae
|
||||
#define CODE_input_document 0x18798952
|
||||
#define CODE_input_audio_file_location 0x74dc404d
|
||||
#define CODE_input_document_file_location 0x4e45abe9
|
||||
#define CODE_decrypted_message_media_document 0xb095434b
|
||||
#define CODE_decrypted_message_media_audio 0x6080758f
|
||||
#define CODE_audio_empty 0x586988d8
|
||||
#define CODE_audio 0x427425e7
|
||||
#define CODE_document_empty 0x36f8c871
|
||||
#define CODE_document 0x9efc6326
|
||||
#define CODE_invoke_after_msg 0xcb9f372d
|
||||
#define CODE_invoke_after_msgs 0x3dc4b4f0
|
||||
#define CODE_invoke_with_layer1 0x53835315
|
||||
#define CODE_auth_check_phone 0x6fe51dfb
|
||||
#define CODE_auth_send_code 0x768d5f4d
|
||||
#define CODE_auth_send_call 0x3c51564
|
||||
#define CODE_auth_sign_up 0x1b067634
|
||||
#define CODE_auth_sign_in 0xbcd51581
|
||||
#define CODE_auth_log_out 0x5717da40
|
||||
#define CODE_auth_reset_authorizations 0x9fab0d1a
|
||||
#define CODE_auth_send_invites 0x771c1d97
|
||||
#define CODE_auth_export_authorization 0xe5bfffcd
|
||||
#define CODE_auth_import_authorization 0xe3ef9613
|
||||
#define CODE_account_register_device 0x446c712c
|
||||
#define CODE_account_unregister_device 0x65c55b40
|
||||
#define CODE_account_update_notify_settings 0x84be5b93
|
||||
#define CODE_account_get_notify_settings 0x12b3ad31
|
||||
#define CODE_account_reset_notify_settings 0xdb7e1747
|
||||
#define CODE_account_update_profile 0xf0888d68
|
||||
#define CODE_account_update_status 0x6628562c
|
||||
#define CODE_account_get_wall_papers 0xc04cfac2
|
||||
#define CODE_users_get_users 0xd91a548
|
||||
#define CODE_users_get_full_user 0xca30a5b1
|
||||
#define CODE_contacts_get_statuses 0xc4a353ee
|
||||
#define CODE_contacts_get_contacts 0x22c6aa08
|
||||
#define CODE_contacts_import_contacts 0xda30b32d
|
||||
#define CODE_contacts_search 0x11f812d8
|
||||
#define CODE_contacts_get_suggested 0xcd773428
|
||||
#define CODE_contacts_delete_contact 0x8e953744
|
||||
#define CODE_contacts_delete_contacts 0x59ab389e
|
||||
#define CODE_contacts_block 0x332b49fc
|
||||
#define CODE_contacts_unblock 0xe54100bd
|
||||
#define CODE_contacts_get_blocked 0xf57c350f
|
||||
#define CODE_messages_get_messages 0x4222fa74
|
||||
#define CODE_messages_get_dialogs 0xeccf1df6
|
||||
#define CODE_messages_get_history 0x92a1df2f
|
||||
#define CODE_messages_search 0x7e9f2ab
|
||||
#define CODE_messages_read_history 0xb04f2510
|
||||
#define CODE_messages_delete_history 0xf4f8fb61
|
||||
#define CODE_messages_delete_messages 0x14f2dd0a
|
||||
#define CODE_messages_restore_messages 0x395f9d7e
|
||||
#define CODE_messages_received_messages 0x28abcb68
|
||||
#define CODE_messages_set_typing 0x719839e9
|
||||
#define CODE_messages_send_message 0x4cde0aab
|
||||
#define CODE_messages_send_media 0xa3c85d76
|
||||
#define CODE_messages_forward_messages 0x514cd10f
|
||||
#define CODE_messages_get_chats 0x3c6aa187
|
||||
#define CODE_messages_get_full_chat 0x3b831c66
|
||||
#define CODE_messages_edit_chat_title 0xb4bc68b5
|
||||
#define CODE_messages_edit_chat_photo 0xd881821d
|
||||
#define CODE_messages_add_chat_user 0x2ee9ee9e
|
||||
#define CODE_messages_delete_chat_user 0xc3c5cd23
|
||||
#define CODE_messages_create_chat 0x419d9aee
|
||||
#define CODE_updates_get_state 0xedd4882a
|
||||
#define CODE_updates_get_difference 0xa041495
|
||||
#define CODE_photos_update_profile_photo 0xeef579a0
|
||||
#define CODE_photos_upload_profile_photo 0xd50f9c88
|
||||
#define CODE_upload_save_file_part 0xb304a621
|
||||
#define CODE_upload_get_file 0xe3a6cfb5
|
||||
#define CODE_help_get_config 0xc4f9186b
|
||||
#define CODE_help_get_nearest_dc 0x1fb33026
|
||||
#define CODE_help_get_app_update 0xc812ac7e
|
||||
#define CODE_help_save_app_log 0x6f02f748
|
||||
#define CODE_help_get_invite_text 0xa4a95186
|
||||
#define CODE_photos_get_user_photos 0xb7ee553c
|
||||
#define CODE_invoke_with_layer2 0x289dd1f6
|
||||
#define CODE_messages_forward_message 0x3f3f4f2
|
||||
#define CODE_messages_send_broadcast 0x41bb0972
|
||||
#define CODE_invoke_with_layer3 0xb7475268
|
||||
#define CODE_geochats_get_located 0x7f192d8f
|
||||
#define CODE_geochats_get_recents 0xe1427e6f
|
||||
#define CODE_geochats_checkin 0x55b3e8fb
|
||||
#define CODE_geochats_get_full_chat 0x6722dd6f
|
||||
#define CODE_geochats_edit_chat_title 0x4c8e2273
|
||||
#define CODE_geochats_edit_chat_photo 0x35d81a95
|
||||
#define CODE_geochats_search 0xcfcdc44d
|
||||
#define CODE_geochats_get_history 0xb53f7a68
|
||||
#define CODE_geochats_set_typing 0x8b8a729
|
||||
#define CODE_geochats_send_message 0x61b0044
|
||||
#define CODE_geochats_send_media 0xb8f0deff
|
||||
#define CODE_geochats_create_geo_chat 0xe092e16
|
||||
#define CODE_invoke_with_layer4 0xdea0d430
|
||||
#define CODE_invoke_with_layer5 0x417a57ae
|
||||
#define CODE_invoke_with_layer6 0x3a64d54d
|
||||
#define CODE_invoke_with_layer7 0xa5be56d3
|
||||
#define CODE_messages_get_dh_config 0x26cf8950
|
||||
#define CODE_messages_request_encryption 0xf64daf43
|
||||
#define CODE_messages_accept_encryption 0x3dbc0415
|
||||
#define CODE_messages_discard_encryption 0xedd923c5
|
||||
#define CODE_messages_set_encrypted_typing 0x791451ed
|
||||
#define CODE_messages_read_encrypted_history 0x7f4b690a
|
||||
#define CODE_messages_send_encrypted 0xa9776773
|
||||
#define CODE_messages_send_encrypted_file 0x9a901b66
|
||||
#define CODE_messages_send_encrypted_service 0x32d439a4
|
||||
#define CODE_messages_received_queue 0x55a5bb66
|
||||
#define CODE_invoke_with_layer8 0xe9abd9fd
|
||||
#define CODE_upload_save_big_file_part 0xde7b673d
|
||||
#define CODE_init_connection 0x69796de9
|
||||
#define CODE_invoke_with_layer9 0x76715a63
|
||||
#define CODE_invoke_with_layer10 0x39620c41
|
||||
#define CODE_invoke_with_layer11 0xa6b88fdf
|
||||
#define CODE_invoke_with_layer12 0xdda60d3c
|
||||
#endif
|
|
@ -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 <http://www.gnu.org/licenses/>.";
|
||||
print "";
|
||||
print " Copyright Vitaly Valtman 2013";
|
||||
print "*/";
|
||||
print "#ifndef CONSTANTS_H";
|
||||
print "#define CONSTANTS_H";
|
||||
}
|
||||
// {
|
||||
if (split ($1, a, "#") == 2) {
|
||||
gsub (/[A-Z]/, "_&", 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";
|
||||
}
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 671 B After Width: | Height: | Size: 671 B |
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 1 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
24
include.h
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright Vitaly Valtman 2013
|
||||
*/
|
||||
#ifndef __INCLUDE_H__
|
||||
#define __INCLUDE_H__
|
||||
|
||||
#define UU __attribute__ ((unused))
|
||||
|
||||
#endif
|
350
loop.c
|
@ -1,350 +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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright Vitaly Valtman 2013
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#define READLINE_CALLBACKS
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "net.h"
|
||||
#include "mtproto-client.h"
|
||||
#include "queries.h"
|
||||
#include "telegram.h"
|
||||
#include "loop.h"
|
||||
#include "binlog.h"
|
||||
|
||||
//
|
||||
|
||||
#include "purple-plugin/telegram-purple.h"
|
||||
//
|
||||
|
||||
char *get_auth_key_filename (void);
|
||||
char *get_state_filename (void);
|
||||
int zero[512];
|
||||
|
||||
|
||||
void write_dc (int auth_file_fd, struct dc *DC) {
|
||||
debug("writing to auth_file: auth_file_fd: %d, port: %d, ip: %s\n", auth_file_fd, DC->port, DC->ip);
|
||||
assert (write (auth_file_fd, &DC->port, 4) == 4);
|
||||
int l = strlen (DC->ip);
|
||||
assert (write (auth_file_fd, &l, 4) == 4);
|
||||
assert (write (auth_file_fd, DC->ip, l) == l);
|
||||
if (DC->flags & 1) {
|
||||
assert (write (auth_file_fd, &DC->auth_key_id, 8) == 8);
|
||||
assert (write (auth_file_fd, DC->auth_key, 256) == 256);
|
||||
} else {
|
||||
assert (write (auth_file_fd, zero, 256 + 8) == 256 + 8);
|
||||
}
|
||||
|
||||
assert (write (auth_file_fd, &DC->server_salt, 8) == 8);
|
||||
assert (write (auth_file_fd, &DC->has_auth, 4) == 4);
|
||||
}
|
||||
|
||||
void write_auth_file (struct authorization_state *state, const char *filename) {
|
||||
debug("Writing to auth_file: %s\n", filename);
|
||||
int auth_file_fd = open (filename, O_CREAT | O_RDWR, 0600);
|
||||
assert (auth_file_fd >= 0);
|
||||
int x = DC_SERIALIZED_MAGIC_V2;
|
||||
assert (write (auth_file_fd, &x, 4) == 4);
|
||||
x = MAX_DC_ID;
|
||||
assert (write (auth_file_fd, &x, 4) == 4);
|
||||
assert (write (auth_file_fd, &state->dc_working_num, 4) == 4);
|
||||
assert (write (auth_file_fd, &state->auth_state, 4) == 4);
|
||||
int i;
|
||||
for (i = 0; i <= MAX_DC_ID; i++) {
|
||||
if (state->DC_list[i]) {
|
||||
x = 1;
|
||||
assert (write (auth_file_fd, &x, 4) == 4);
|
||||
write_dc (auth_file_fd, state->DC_list[i]);
|
||||
} else {
|
||||
x = 0;
|
||||
assert (write (auth_file_fd, &x, 4) == 4);
|
||||
}
|
||||
}
|
||||
assert (write (auth_file_fd, &state->our_id, 4) == 4);
|
||||
close (auth_file_fd);
|
||||
}
|
||||
|
||||
void read_dc (int auth_file_fd, int id, unsigned ver, struct dc *DC_list[]) {
|
||||
int port = 0;
|
||||
assert (read (auth_file_fd, &port, 4) == 4);
|
||||
int l = 0;
|
||||
assert (read (auth_file_fd, &l, 4) == 4);
|
||||
assert (l >= 0);
|
||||
char *ip = talloc (l + 1);
|
||||
assert (read (auth_file_fd, ip, l) == l);
|
||||
ip[l] = 0;
|
||||
struct dc *DC = alloc_dc (DC_list, id, ip, port);
|
||||
assert (read (auth_file_fd, &DC->auth_key_id, 8) == 8);
|
||||
assert (read (auth_file_fd, &DC->auth_key, 256) == 256);
|
||||
assert (read (auth_file_fd, &DC->server_salt, 8) == 8);
|
||||
if (DC->auth_key_id) {
|
||||
DC->flags |= 1;
|
||||
}
|
||||
if (ver != DC_SERIALIZED_MAGIC) {
|
||||
assert (read (auth_file_fd, &DC->has_auth, 4) == 4);
|
||||
} else {
|
||||
DC->has_auth = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void empty_auth_file (const char *filename) {
|
||||
struct authorization_state state;
|
||||
memset(state.DC_list, 0, 11 * sizeof(void *));
|
||||
|
||||
debug("empty_auth_file()\n");
|
||||
alloc_dc (state.DC_list, TG_DC_NUM, tstrdup (TG_SERVER), TG_PORT);
|
||||
state.dc_working_num = TG_DC_NUM;
|
||||
state.auth_state = 0;
|
||||
write_auth_file (&state, filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the auth-file and return the read authorization state
|
||||
*
|
||||
* When the given file doesn't exist, create a new empty
|
||||
* file containing the default authorization state at this
|
||||
* path
|
||||
*/
|
||||
struct authorization_state read_auth_file (const char *filename) {
|
||||
debug("read_auth_file()\n");
|
||||
|
||||
struct authorization_state state;
|
||||
memset(state.DC_list, 0, 11 * sizeof(void *));
|
||||
|
||||
int auth_file_fd = open (filename, O_RDWR, 0600);
|
||||
debug("fd: %d\n", auth_file_fd);
|
||||
if (auth_file_fd < 0) {
|
||||
debug("auth_file does not exist, creating empty...\n");
|
||||
empty_auth_file (filename);
|
||||
}
|
||||
auth_file_fd = open (filename, O_RDWR, 0600);
|
||||
assert (auth_file_fd >= 0);
|
||||
|
||||
// amount of data centers
|
||||
unsigned x;
|
||||
// magic number of file
|
||||
unsigned m;
|
||||
if (read (auth_file_fd, &m, 4) < 4 || (m != DC_SERIALIZED_MAGIC && m != DC_SERIALIZED_MAGIC_V2)) {
|
||||
debug("Invalid File content, wrong Magic numebr\n");
|
||||
close (auth_file_fd);
|
||||
empty_auth_file (filename);
|
||||
return state;
|
||||
}
|
||||
assert (read (auth_file_fd, &x, 4) == 4);
|
||||
assert (x <= MAX_DC_ID);
|
||||
assert (read (auth_file_fd, &state.dc_working_num, 4) == 4);
|
||||
assert (read (auth_file_fd, &state.auth_state, 4) == 4);
|
||||
debug ("dc_working_num=%d, auth_state=%d \n", state.dc_working_num, state.auth_state);
|
||||
if (m == DC_SERIALIZED_MAGIC) {
|
||||
state.auth_state = 700;
|
||||
}
|
||||
int i;
|
||||
for (i = 0; i <= (int)x; i++) {
|
||||
int y;
|
||||
assert (read (auth_file_fd, &y, 4) == 4);
|
||||
if (y) {
|
||||
read_dc (auth_file_fd, i, m, state.DC_list);
|
||||
debug("loaded dc[%d] - port: %d, ip: %s, auth_key_id: %lli, server_salt: %lli, has_auth: %d\n",
|
||||
i, state.DC_list[i]->port, state.DC_list[i]->ip, state.DC_list[i]->auth_key_id,
|
||||
state.DC_list[i]->server_salt, state.DC_list[i]->has_auth);
|
||||
} else {
|
||||
debug("loaded dc[%d] - NULL\n", i);
|
||||
}
|
||||
}
|
||||
int l = read (auth_file_fd, &state.our_id, 4);
|
||||
if (l < 4) {
|
||||
assert (!l);
|
||||
}
|
||||
close (auth_file_fd);
|
||||
struct dc *DC_working = state.DC_list[state.dc_working_num];
|
||||
if (m == DC_SERIALIZED_MAGIC) {
|
||||
DC_working->has_auth = 1;
|
||||
}
|
||||
debug("loaded authorization state - our_id: %d, auth_state: %d, dc_working_num: %d \n", state.our_id, state.auth_state, state.dc_working_num);
|
||||
return state;
|
||||
}
|
||||
|
||||
struct protocol_state read_state_file (const char *filename) {
|
||||
debug("read_state_file()\n");
|
||||
struct protocol_state state = {0, 0, 0, 0};
|
||||
|
||||
int state_file_fd = open (filename, O_CREAT | O_RDWR, 0600);
|
||||
if (state_file_fd < 0) {
|
||||
return state;
|
||||
}
|
||||
int version, magic;
|
||||
if (read (state_file_fd, &magic, 4) < 4) { close (state_file_fd); return state; }
|
||||
if (magic != (int)STATE_FILE_MAGIC) { close (state_file_fd); return state; }
|
||||
if (read (state_file_fd, &version, 4) < 4) { close (state_file_fd); return state; }
|
||||
assert (version >= 0);
|
||||
int x[4];
|
||||
if (read (state_file_fd, x, 16) < 16) {
|
||||
close (state_file_fd);
|
||||
return state;
|
||||
}
|
||||
state.pts = x[0];
|
||||
state.qts = x[1];
|
||||
state.seq = x[2];
|
||||
state.last_date = x[3];
|
||||
close (state_file_fd);
|
||||
debug("loaded session state - pts: %d, qts: %d, seq: %d, last_date: %d.\n", state.pts,
|
||||
state.qts, state.seq, state.last_date);
|
||||
return state;
|
||||
}
|
||||
|
||||
void write_state_file (struct protocol_state *state, const char* filename) {
|
||||
int state_file_fd = open (filename, O_CREAT | O_RDWR, 0600);
|
||||
if (state_file_fd < 0) {
|
||||
return;
|
||||
}
|
||||
int x[6];
|
||||
x[0] = STATE_FILE_MAGIC;
|
||||
x[1] = 0;
|
||||
x[2] = state->pts;
|
||||
x[3] = state->qts;
|
||||
x[4] = state->seq;
|
||||
x[5] = state->last_date;
|
||||
assert (write (state_file_fd, x, 24) == 24);
|
||||
close (state_file_fd);
|
||||
}
|
||||
|
||||
void read_secret_chat_file (struct telegram *instance, const char *file) {
|
||||
struct binlog *bl = instance->bl;
|
||||
|
||||
int fd = open (file, O_CREAT | O_RDWR, 0600);
|
||||
if (fd < 0) {
|
||||
return;
|
||||
}
|
||||
int x[2];
|
||||
if (read (fd, x, 8) < 8) {
|
||||
close (fd); return;
|
||||
}
|
||||
if (x[0] != (int)SECRET_CHAT_FILE_MAGIC) { close (fd); return; }
|
||||
int version = x[1];
|
||||
assert (version >= 0);
|
||||
int cc;
|
||||
assert (read (fd, &cc, 4) == 4);
|
||||
int i;
|
||||
for (i = 0; i < cc; i++) {
|
||||
peer_t *P = talloc0 (sizeof (*P));
|
||||
struct secret_chat *E = &P->encr_chat;
|
||||
int t;
|
||||
assert (read (fd, &t, 4) == 4);
|
||||
P->id = MK_ENCR_CHAT (t);
|
||||
assert (read (fd, &P->flags, 4) == 4);
|
||||
assert (read (fd, &t, 4) == 4);
|
||||
assert (t > 0);
|
||||
P->print_name = talloc (t + 1);
|
||||
assert (read (fd, P->print_name, t) == t);
|
||||
P->print_name[t] = 0;
|
||||
peer_insert_name (bl, P);
|
||||
|
||||
assert (read (fd, &E->state, 4) == 4);
|
||||
assert (read (fd, &E->user_id, 4) == 4);
|
||||
assert (read (fd, &E->admin_id, 4) == 4);
|
||||
assert (read (fd, &E->ttl, 4) == 4);
|
||||
assert (read (fd, &E->access_hash, 8) == 8);
|
||||
|
||||
if (E->state != sc_waiting) {
|
||||
E->g_key = talloc (256);
|
||||
assert (read (fd, E->g_key, 256) == 256);
|
||||
E->nonce = talloc (256);
|
||||
assert (read (fd, E->nonce, 256) == 256);
|
||||
}
|
||||
assert (read (fd, E->key, 256) == 256);
|
||||
assert (read (fd, &E->key_fingerprint, 8) == 8);
|
||||
insert_encrypted_chat (bl, P);
|
||||
}
|
||||
if (version >= 1) {
|
||||
assert (read (fd, &instance->encr_root, 4) == 4);
|
||||
if (instance->encr_root) {
|
||||
assert (read (fd, &instance->encr_param_version, 4) == 4);
|
||||
instance->encr_prime = talloc (256);
|
||||
assert (read (fd, instance->encr_prime, 256) == 256);
|
||||
}
|
||||
}
|
||||
close (fd);
|
||||
}
|
||||
|
||||
// TODO: Refactor
|
||||
void write_secret_chat_file (struct telegram *instance, const char *filename) {
|
||||
struct binlog *bl = instance->bl;
|
||||
|
||||
int fd = open (filename, O_CREAT | O_RDWR, 0600);
|
||||
if (fd < 0) {
|
||||
return;
|
||||
}
|
||||
int x[2];
|
||||
x[0] = SECRET_CHAT_FILE_MAGIC;
|
||||
x[1] = 1;
|
||||
assert (write (fd, x, 8) == 8);
|
||||
int i;
|
||||
int cc = 0;
|
||||
for (i = 0; i < bl->peer_num; i++) if (get_peer_type (bl->Peers[i]->id) == PEER_ENCR_CHAT) {
|
||||
if (bl->Peers[i]->encr_chat.state != sc_none && bl->Peers[i]->encr_chat.state != sc_deleted) {
|
||||
cc ++;
|
||||
}
|
||||
}
|
||||
assert (write (fd, &cc, 4) == 4);
|
||||
for (i = 0; i < bl->peer_num; i++) if (get_peer_type (bl->Peers[i]->id) == PEER_ENCR_CHAT) {
|
||||
if (bl->Peers[i]->encr_chat.state != sc_none && bl->Peers[i]->encr_chat.state != sc_deleted) {
|
||||
int t = get_peer_id (bl->Peers[i]->id);
|
||||
assert (write (fd, &t, 4) == 4);
|
||||
t = bl->Peers[i]->flags;
|
||||
assert (write (fd, &t, 4) == 4);
|
||||
t = strlen (bl->Peers[i]->print_name);
|
||||
assert (write (fd, &t, 4) == 4);
|
||||
assert (write (fd, bl->Peers[i]->print_name, t) == t);
|
||||
|
||||
assert (write (fd, &bl->Peers[i]->encr_chat.state, 4) == 4);
|
||||
|
||||
assert (write (fd, &bl->Peers[i]->encr_chat.user_id, 4) == 4);
|
||||
assert (write (fd, &bl->Peers[i]->encr_chat.admin_id, 4) == 4);
|
||||
assert (write (fd, &bl->Peers[i]->encr_chat.ttl, 4) == 4);
|
||||
assert (write (fd, &bl->Peers[i]->encr_chat.access_hash, 8) == 8);
|
||||
if (bl->Peers[i]->encr_chat.state != sc_waiting) {
|
||||
assert (write (fd, bl->Peers[i]->encr_chat.g_key, 256) == 256);
|
||||
}
|
||||
if (bl->Peers[i]->encr_chat.state != sc_waiting) {
|
||||
assert (write (fd, bl->Peers[i]->encr_chat.nonce, 256) == 256);
|
||||
}
|
||||
assert (write (fd, bl->Peers[i]->encr_chat.key, 256) == 256);
|
||||
assert (write (fd, &bl->Peers[i]->encr_chat.key_fingerprint, 8) == 8);
|
||||
}
|
||||
}
|
||||
assert (write (fd, &instance->encr_root, 4) == 4);
|
||||
if (instance->encr_root) {
|
||||
assert (write (fd, &instance->encr_param_version, 4) == 4);
|
||||
assert (write (fd, instance->encr_prime, 256) == 256);
|
||||
}
|
||||
close (fd);
|
||||
}
|
||||
|
79
loop.h
|
@ -1,79 +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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright Vitaly Valtman 2013
|
||||
*/
|
||||
|
||||
#include "telegram.h"
|
||||
|
||||
#ifndef __LOOP_H__
|
||||
#define __LOOP_H__
|
||||
// forward declarations
|
||||
|
||||
struct dc;
|
||||
struct telegram;
|
||||
|
||||
|
||||
/**
|
||||
* The authorization state, storing all known data centers of the telegram
|
||||
* network and associated shared keys for transport encryption
|
||||
*/
|
||||
struct authorization_state {
|
||||
int dc_working_num;
|
||||
int auth_state;
|
||||
struct dc* DC_list[11];
|
||||
int our_id;
|
||||
};
|
||||
|
||||
/**
|
||||
* Stores the current update state of a client
|
||||
*/
|
||||
struct protocol_state {
|
||||
|
||||
/**
|
||||
* Number of events occured in a text box
|
||||
*/
|
||||
int pts;
|
||||
|
||||
/**
|
||||
* Position within a siccession of unconfirmed updates, used for encrypted
|
||||
* messages
|
||||
*/
|
||||
int qts;
|
||||
|
||||
/**
|
||||
* Number of sent updates
|
||||
*/
|
||||
int seq;
|
||||
|
||||
/**
|
||||
* Last update
|
||||
*/
|
||||
int last_date;
|
||||
};
|
||||
|
||||
void write_secret_chat_file (struct telegram *instance, const char *filename);
|
||||
|
||||
void write_auth_file (struct authorization_state *state, const char *filename);
|
||||
struct authorization_state read_auth_file (const char *filename);
|
||||
|
||||
void write_state_file (struct protocol_state *state, const char *filename);
|
||||
struct protocol_state read_state_file (const char *filename);
|
||||
|
||||
void write_secret_chat_file (struct telegram *instance, const char *filename);
|
||||
void read_secret_chat_file (struct telegram *instance, const char *filename);
|
||||
|
||||
#endif
|
4
msglog.c
|
@ -1,7 +1,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include "debug.h"
|
||||
#include "purple-plugin/telegram-purple.h"
|
||||
#include <debug.h>
|
||||
#include "telegram-purple.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#define COLOR_GREY "\033[37;1m"
|
||||
|
|
1735
mtproto-client.c
514
mtproto-client.h
|
@ -1,514 +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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright Nikolay Durov, Andrey Lopatin 2012-2013
|
||||
Copyright Vitaly Valtman 2013
|
||||
*/
|
||||
#ifndef __MTPROTO_CLIENT_H__
|
||||
#define __MTPROTO_CLIENT_H__
|
||||
|
||||
|
||||
/*
|
||||
* COMMON
|
||||
*/
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include "include.h"
|
||||
#include "tools.h"
|
||||
#include "constants.h"
|
||||
#include "msglog.h"
|
||||
#include "net.h"
|
||||
|
||||
#ifdef __MACH__
|
||||
#include <mach/clock.h>
|
||||
#include <mach/mach.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* 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_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
|
||||
|
||||
/* 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 _FILE_OFFSET_BITS 64
|
||||
|
||||
char *rsa_public_key_name;
|
||||
|
||||
#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)
|
||||
|
||||
/*
|
||||
* CONNECTION STATES
|
||||
*/
|
||||
|
||||
enum dc_state {
|
||||
st_init,
|
||||
st_reqpq_sent,
|
||||
st_reqdh_sent,
|
||||
st_client_dh_sent,
|
||||
st_authorized,
|
||||
st_error
|
||||
};
|
||||
|
||||
/*
|
||||
* CLIENT
|
||||
*/
|
||||
|
||||
// forward-declarations
|
||||
struct timespec;
|
||||
struct telegram;
|
||||
struct mtproto_connection;
|
||||
void mtproto_destroy (struct mtproto_connection *self);
|
||||
|
||||
#define DECRYPT_BUFFER_INTS 16384
|
||||
#define ENCRYPT_BUFFER_INTS 16384
|
||||
#define PACKET_BUFFER_SIZE (16384 * 100 + 16) // temp fix
|
||||
|
||||
struct mtproto_connection {
|
||||
struct connection *connection;
|
||||
|
||||
int auth_success;
|
||||
enum dc_state c_state;
|
||||
char nonce[256];
|
||||
char new_nonce[256];
|
||||
char server_nonce[256];
|
||||
|
||||
int total_packets_sent;
|
||||
long long total_data_sent;
|
||||
|
||||
unsigned long long what;
|
||||
unsigned p1, p2;
|
||||
|
||||
int *in_ptr, *in_end;
|
||||
|
||||
// common
|
||||
|
||||
int __packet_buffer[PACKET_BUFFER_SIZE], *packet_ptr;
|
||||
int *packet_buffer;
|
||||
|
||||
long long rsa_encrypted_chunks, rsa_decrypted_chunks;
|
||||
|
||||
BN_CTX *BN_ctx;
|
||||
|
||||
|
||||
// DH
|
||||
|
||||
int encrypt_buffer[ENCRYPT_BUFFER_INTS];
|
||||
int decrypt_buffer[ENCRYPT_BUFFER_INTS];
|
||||
char s_power [256];
|
||||
BIGNUM dh_prime, dh_g, g_a, dh_power, auth_key_num;
|
||||
|
||||
struct {
|
||||
long long auth_key_id;
|
||||
long long out_msg_id;
|
||||
int msg_len;
|
||||
} unenc_msg_header;
|
||||
|
||||
|
||||
// AES IGE
|
||||
|
||||
unsigned char aes_key_raw[32], aes_iv[32];
|
||||
AES_KEY aes_key;
|
||||
|
||||
// authorized
|
||||
|
||||
struct encrypted_message enc_msg;
|
||||
long long client_last_msg_id;
|
||||
long long server_last_msg_id;
|
||||
|
||||
int longpoll_count, good_messages;
|
||||
|
||||
// TODO: decide whether this should be in struct telegram
|
||||
// or in struct mtproto_client
|
||||
int unread_messages;
|
||||
int our_id;
|
||||
int pts;
|
||||
int qts;
|
||||
int last_date;
|
||||
int seq;
|
||||
|
||||
// extra (queries.c)
|
||||
|
||||
int *encr_extra;
|
||||
int *encr_ptr;
|
||||
int *encr_end;
|
||||
|
||||
// callbacks
|
||||
|
||||
void (*on_ready)(struct mtproto_connection *self, void* data);
|
||||
void *on_ready_data;
|
||||
|
||||
void (*on_error)(struct mtproto_connection *self, void *data);
|
||||
|
||||
// the amount of currently outgoing messages that
|
||||
// have not yet received a response
|
||||
int queries_num;
|
||||
|
||||
// binlog that consumes all updates and events of this connection
|
||||
struct binlog *bl;
|
||||
|
||||
// marks this connection for destruction, so it
|
||||
// will be freed once all queries received a response or timed out
|
||||
int destroy;
|
||||
|
||||
//
|
||||
// the corresponding telegram instance
|
||||
//
|
||||
struct telegram *instance;
|
||||
void *handle;
|
||||
};
|
||||
|
||||
void mtproto_connection_init (struct mtproto_connection *c);
|
||||
struct mtproto_connection *mtproto_new(struct dc *DC, int fd, struct telegram *tg);
|
||||
void mtproto_close(struct mtproto_connection *c);
|
||||
void mtproto_connect(struct mtproto_connection *c);
|
||||
|
||||
void on_start (struct mtproto_connection *self);
|
||||
long long encrypt_send_message (struct mtproto_connection *self, int *msg, int msg_ints, int useful);
|
||||
void work_update (struct mtproto_connection *self, long long msg_id);
|
||||
void work_update_binlog (struct mtproto_connection *self);
|
||||
int check_g (unsigned char p[256], BIGNUM *g);
|
||||
int check_g_bn (BIGNUM *p, BIGNUM *g);
|
||||
int check_DH_params (struct mtproto_connection *self, BIGNUM *p, int g);
|
||||
void secure_random (void *s, int l);
|
||||
|
||||
/*
|
||||
* Common 2
|
||||
*/
|
||||
|
||||
void prng_seed (struct mtproto_connection *self, const char *password_filename, int password_length);
|
||||
int serialize_bignum (BIGNUM *b, char *buffer, int maxlen);
|
||||
long long compute_rsa_key_fingerprint (RSA *key);
|
||||
|
||||
static inline void out_ints (struct mtproto_connection *self, const int *what, int len) {
|
||||
assert (self->packet_ptr + len <= self->packet_buffer + PACKET_BUFFER_SIZE);
|
||||
memcpy (self->packet_ptr, what, len * 4);
|
||||
self->packet_ptr += len;
|
||||
}
|
||||
|
||||
|
||||
static inline void out_int (struct mtproto_connection *self, int x) {
|
||||
assert (self->packet_ptr + 1 <= self->packet_buffer + PACKET_BUFFER_SIZE);
|
||||
*self->packet_ptr++ = x;
|
||||
}
|
||||
|
||||
|
||||
static inline void out_long (struct mtproto_connection *self, long long x) {
|
||||
assert (self->packet_ptr + 2 <= self->packet_buffer + PACKET_BUFFER_SIZE);
|
||||
*(long long *)self->packet_ptr = x;
|
||||
self->packet_ptr += 2;
|
||||
}
|
||||
|
||||
static inline void clear_packet (struct mtproto_connection *self) {
|
||||
self->packet_ptr = self->packet_buffer;
|
||||
}
|
||||
|
||||
void out_cstring (struct mtproto_connection *self, const char *str, long len);
|
||||
void out_cstring_careful (struct mtproto_connection *self, const char *str, long len);
|
||||
void out_data (struct mtproto_connection *self, const void *data, long len);
|
||||
|
||||
static inline void out_string (struct mtproto_connection *self, const char *str) {
|
||||
out_cstring (self, str, strlen (str));
|
||||
}
|
||||
|
||||
static inline void out_bignum (struct mtproto_connection *self, BIGNUM *n) {
|
||||
int l = serialize_bignum (n, (char *)self->packet_ptr, (PACKET_BUFFER_SIZE - (self->packet_ptr - self->packet_buffer)) * 4);
|
||||
assert (l > 0);
|
||||
self->packet_ptr += l >> 2;
|
||||
}
|
||||
|
||||
|
||||
void fetch_pts (struct mtproto_connection *self);
|
||||
void fetch_qts (struct mtproto_connection *self);
|
||||
void fetch_date (struct mtproto_connection *self);
|
||||
void fetch_seq (struct mtproto_connection *self);
|
||||
static inline int prefetch_strlen (struct mtproto_connection *self) {
|
||||
if (self->in_ptr >= self->in_end) {
|
||||
return -1;
|
||||
}
|
||||
unsigned l = *self->in_ptr;
|
||||
if ((l & 0xff) < 0xfe) {
|
||||
l &= 0xff;
|
||||
return (self->in_end >= self->in_ptr + (l >> 2) + 1) ? (int)l : -1;
|
||||
} else if ((l & 0xff) == 0xfe) {
|
||||
l >>= 8;
|
||||
return (l >= 254 && self->in_end >= self->in_ptr + ((l + 7) >> 2)) ? (int)l : -1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
extern int verbosity;
|
||||
static inline char *fetch_str (struct mtproto_connection *self, int len) {
|
||||
assert (len >= 0);
|
||||
if (verbosity > 6) {
|
||||
debug ("fetch_string: len = %d\n", len);
|
||||
}
|
||||
if (len < 254) {
|
||||
char *str = (char *) self->in_ptr + 1;
|
||||
self->in_ptr += 1 + (len >> 2);
|
||||
return str;
|
||||
} else {
|
||||
char *str = (char *) self->in_ptr + 4;
|
||||
self->in_ptr += (len + 7) >> 2;
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
static inline char *fetch_str_dup (struct mtproto_connection *self) {
|
||||
int l = prefetch_strlen (self);
|
||||
assert (l >= 0);
|
||||
int i;
|
||||
char *s = fetch_str (self, 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 (struct mtproto_connection *self, char **s) {
|
||||
if (!*s) {
|
||||
*s = fetch_str_dup (self);
|
||||
return 1;
|
||||
}
|
||||
int l = prefetch_strlen (self);
|
||||
char *r = fetch_str (self, 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 (struct mtproto_connection *self, int *value) {
|
||||
if (*value == *self->in_ptr) {
|
||||
self->in_ptr ++;
|
||||
return 0;
|
||||
} else {
|
||||
*value = *(self->in_ptr ++);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int fetch_update_long (struct mtproto_connection *self, long long *value) {
|
||||
if (*value == *(long long *)self->in_ptr) {
|
||||
self->in_ptr += 2;
|
||||
return 0;
|
||||
} else {
|
||||
*value = *(long long *)(self->in_ptr);
|
||||
self->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 (struct mtproto_connection *self, int n) {
|
||||
self->in_ptr += n;
|
||||
assert (self->in_ptr <= self->in_end);
|
||||
}
|
||||
|
||||
static inline void fetch_skip_str (struct mtproto_connection *self) {
|
||||
int l = prefetch_strlen (self);
|
||||
assert (l >= 0);
|
||||
fetch_str (self, l);
|
||||
}
|
||||
|
||||
static inline long have_prefetch_ints (struct mtproto_connection *self) {
|
||||
return self->in_end - self->in_ptr;
|
||||
}
|
||||
|
||||
int fetch_bignum (struct mtproto_connection *self, BIGNUM *x);
|
||||
|
||||
static inline int fetch_int (struct mtproto_connection *self) {
|
||||
assert (self->in_ptr + 1 <= self->in_end);
|
||||
if (verbosity > 6) {
|
||||
debug ("fetch_int: 0x%08x (%d)\n", *self->in_ptr, *self->in_ptr);
|
||||
}
|
||||
return *(self->in_ptr ++);
|
||||
}
|
||||
|
||||
static inline int fetch_bool (struct mtproto_connection *self) {
|
||||
if (verbosity > 6) {
|
||||
debug ("fetch_bool: 0x%08x (%d)\n", *self->in_ptr, *self->in_ptr);
|
||||
}
|
||||
assert (self->in_ptr + 1 <= self->in_end);
|
||||
assert (*(self->in_ptr) == (int)CODE_bool_true || *(self->in_ptr) == (int)CODE_bool_false);
|
||||
return *(self->in_ptr ++) == (int)CODE_bool_true;
|
||||
}
|
||||
|
||||
static inline int prefetch_int (struct mtproto_connection *self) {
|
||||
assert (self->in_ptr < self->in_end);
|
||||
return *(self->in_ptr);
|
||||
}
|
||||
|
||||
static inline void prefetch_data (struct mtproto_connection *self, void *data, int size) {
|
||||
assert (self->in_ptr + (size >> 2) <= self->in_end);
|
||||
memcpy (data, self->in_ptr, size);
|
||||
}
|
||||
|
||||
static inline void fetch_data (struct mtproto_connection *self, void *data, int size) {
|
||||
assert (self->in_ptr + (size >> 2) <= self->in_end);
|
||||
memcpy (data, self->in_ptr, size);
|
||||
assert (!(size & 3));
|
||||
self->in_ptr += (size >> 2);
|
||||
}
|
||||
|
||||
static inline long long fetch_long (struct mtproto_connection *self) {
|
||||
assert (self->in_ptr + 2 <= self->in_end);
|
||||
long long r = *(long long *)self->in_ptr;
|
||||
self->in_ptr += 2;
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline double fetch_double (struct mtproto_connection *self) {
|
||||
assert (self->in_ptr + 2 <= self->in_end);
|
||||
double r = *(double *)self->in_ptr;
|
||||
self->in_ptr += 2;
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline void fetch_ints (struct mtproto_connection *self, void *data, int count) {
|
||||
assert (self->in_ptr + count <= self->in_end);
|
||||
memcpy (data, self->in_ptr, 4 * count);
|
||||
self->in_ptr += count;
|
||||
}
|
||||
|
||||
int get_random_bytes (unsigned char *buf, int n);
|
||||
|
||||
int pad_rsa_encrypt (struct mtproto_connection *self, char *from, int from_len, char *to, int size, BIGNUM *N, BIGNUM *E);
|
||||
int pad_rsa_decrypt (struct mtproto_connection *self, char *from, int from_len, char *to, int size, BIGNUM *N, BIGNUM *D);
|
||||
|
||||
void init_aes_unauth (struct mtproto_connection *self, const char server_nonce[16], const char hidden_client_nonce[32], int encrypt);
|
||||
void init_aes_auth (struct mtproto_connection *self, char auth_key[192], char msg_key[16], int encrypt);
|
||||
int pad_aes_encrypt (struct mtproto_connection *self, char *from, int from_len, char *to, int size);
|
||||
int pad_aes_decrypt (struct mtproto_connection *self, char *from, int from_len, char *to, int size);
|
||||
|
||||
static inline void hexdump_in (struct mtproto_connection *self) {
|
||||
hexdump (self->in_ptr, self->in_end);
|
||||
}
|
||||
|
||||
static inline void hexdump_out (struct mtproto_connection *self) {
|
||||
hexdump (self->packet_buffer, self->packet_ptr);
|
||||
}
|
||||
|
||||
#ifdef __MACH__
|
||||
#define CLOCK_REALTIME 0
|
||||
#define CLOCK_MONOTONIC 1
|
||||
#endif
|
||||
void my_clock_gettime (int clock_id, struct timespec *T);
|
||||
|
||||
void mtproto_close_foreign (struct telegram *instance);
|
||||
void mtproto_free_closed (struct telegram *tg, int force);
|
||||
|
||||
#endif
|
||||
|
357
mtproto-common.c
|
@ -1,357 +0,0 @@
|
|||
#include "mtproto-client.h"
|
||||
|
||||
/*
|
||||
* struct mtproto_connection-Common.c
|
||||
*/
|
||||
|
||||
int verbosity;
|
||||
|
||||
#ifndef __MTPROTO_COMMON_C__
|
||||
#define __MTPROTO_COMMON_C__
|
||||
|
||||
int get_random_bytes (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) {
|
||||
if (verbosity >= 3) {
|
||||
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;
|
||||
}
|
||||
|
||||
void my_clock_gettime (int clock_id UU, struct timespec *T) {
|
||||
#ifdef __MACH__
|
||||
// We are ignoring MONOTONIC and hope time doesn't go back to often
|
||||
clock_serv_t cclock;
|
||||
mach_timespec_t mts;
|
||||
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
|
||||
clock_get_time(cclock, &mts);
|
||||
mach_port_deallocate(mach_task_self(), cclock);
|
||||
T->tv_sec = mts.tv_sec;
|
||||
T->tv_nsec = mts.tv_nsec;
|
||||
#else
|
||||
assert (clock_gettime(clock_id, T) >= 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* 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 prng_seed (struct mtproto_connection *self, const char *password_filename, int password_length) {
|
||||
struct timespec T;
|
||||
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 (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) {
|
||||
debug ( "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) {
|
||||
debug ( "Warning: fail to read password file - \"%s\", %m.\n", password_filename);
|
||||
} else {
|
||||
debug ( "read %d bytes from password file.\n", l);
|
||||
RAND_add (a, l, l);
|
||||
}
|
||||
close (fd);
|
||||
tfree_secure (a, password_length);
|
||||
}
|
||||
}
|
||||
self->BN_ctx = BN_CTX_new ();
|
||||
ensure_ptr (self->BN_ctx);
|
||||
}
|
||||
|
||||
int 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 compute_rsa_key_fingerprint (RSA *key) {
|
||||
static char tempbuff[4096];
|
||||
static unsigned char sha[20];
|
||||
assert (key->n && key->e);
|
||||
int l1 = serialize_bignum (key->n, tempbuff, 4096);
|
||||
assert (l1 > 0);
|
||||
int l2 = 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 out_cstring (struct mtproto_connection *self, const char *str, long len) {
|
||||
assert (len >= 0 && len < (1 << 24));
|
||||
assert ((char *) self->packet_ptr + len + 8 < (char *) (self->packet_buffer + PACKET_BUFFER_SIZE));
|
||||
char *dest = (char *) self->packet_ptr;
|
||||
if (len < 254) {
|
||||
*dest++ = len;
|
||||
} else {
|
||||
*self->packet_ptr = (len << 8) + 0xfe;
|
||||
dest += 4;
|
||||
}
|
||||
memcpy (dest, str, len);
|
||||
dest += len;
|
||||
while ((long) dest & 3) {
|
||||
*dest++ = 0;
|
||||
}
|
||||
self->packet_ptr = (int *) dest;
|
||||
}
|
||||
|
||||
void out_cstring_careful (struct mtproto_connection *self, const char *str, long len) {
|
||||
assert (len >= 0 && len < (1 << 24));
|
||||
assert ((char *) self->packet_ptr + len + 8 < (char *) (self->packet_buffer + PACKET_BUFFER_SIZE));
|
||||
char *dest = (char *) self->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);
|
||||
}
|
||||
*self->packet_ptr = (len << 8) + 0xfe;
|
||||
}
|
||||
dest += len;
|
||||
while ((long) dest & 3) {
|
||||
*dest++ = 0;
|
||||
}
|
||||
self->packet_ptr = (int *) dest;
|
||||
}
|
||||
|
||||
|
||||
void out_data (struct mtproto_connection *self, const void *data, long len) {
|
||||
assert (len >= 0 && len < (1 << 24) && !(len & 3));
|
||||
assert ((char *) self->packet_ptr + len + 8 < (char *) (self->packet_buffer + PACKET_BUFFER_SIZE));
|
||||
memcpy (self->packet_ptr, data, len);
|
||||
self->packet_ptr += len >> 2;
|
||||
}
|
||||
|
||||
|
||||
int fetch_bignum (struct mtproto_connection *self, BIGNUM *x) {
|
||||
int l = prefetch_strlen (self);
|
||||
if (l < 0) {
|
||||
return l;
|
||||
}
|
||||
char *str = fetch_str (self, l);
|
||||
assert (BN_bin2bn ((unsigned char *) str, l, x) == x);
|
||||
return l;
|
||||
}
|
||||
|
||||
int pad_rsa_encrypt (struct mtproto_connection *self, 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);
|
||||
self->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, self->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 pad_rsa_decrypt (struct mtproto_connection *self, 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++) {
|
||||
++self->rsa_decrypted_chunks;
|
||||
BN_bin2bn ((unsigned char *) from, 256, &x);
|
||||
assert (BN_mod_exp (&y, &x, D, N, self->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;
|
||||
}
|
||||
|
||||
void init_aes_unauth (struct mtproto_connection *self, 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, self->aes_key_raw);
|
||||
memcpy (buffer + 32, hidden_client_nonce, 32);
|
||||
SHA1 (buffer, 64, self->aes_iv + 8);
|
||||
memcpy (buffer, server_nonce, 16);
|
||||
memcpy (buffer + 16, hidden_client_nonce, 32);
|
||||
SHA1 (buffer, 48, hash);
|
||||
memcpy (self->aes_key_raw + 20, hash, 12);
|
||||
memcpy (self->aes_iv, hash + 12, 8);
|
||||
memcpy (self->aes_iv + 28, hidden_client_nonce, 4);
|
||||
if (encrypt == AES_ENCRYPT) {
|
||||
AES_set_encrypt_key (self->aes_key_raw, 32*8, &self->aes_key);
|
||||
} else {
|
||||
AES_set_decrypt_key (self->aes_key_raw, 32*8, &self->aes_key);
|
||||
}
|
||||
memset (self->aes_key_raw, 0, sizeof (self->aes_key_raw));
|
||||
}
|
||||
|
||||
void init_aes_auth (struct mtproto_connection *self, 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 (self->aes_key_raw, hash, 8);
|
||||
memcpy (self->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 (self->aes_key_raw + 8, hash + 8, 12);
|
||||
memcpy (self->aes_iv + 12, hash, 8);
|
||||
|
||||
memcpy (buffer, auth_key + 64, 32);
|
||||
memcpy (buffer + 32, msg_key, 16);
|
||||
SHA1 (buffer, 48, hash);
|
||||
memcpy (self->aes_key_raw + 20, hash + 4, 12);
|
||||
memcpy (self->aes_iv + 20, hash + 16, 4);
|
||||
|
||||
memcpy (buffer, msg_key, 16);
|
||||
memcpy (buffer + 16, auth_key + 96, 32);
|
||||
SHA1 (buffer, 48, hash);
|
||||
memcpy (self->aes_iv + 24, hash, 8);
|
||||
|
||||
if (encrypt == AES_ENCRYPT) {
|
||||
AES_set_encrypt_key (self->aes_key_raw, 32*8, &self->aes_key);
|
||||
} else {
|
||||
AES_set_decrypt_key (self->aes_key_raw, 32*8, &self->aes_key);
|
||||
}
|
||||
memset (self->aes_key_raw, 0, sizeof (self->aes_key_raw));
|
||||
}
|
||||
|
||||
int pad_aes_encrypt (struct mtproto_connection *self, 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, &self->aes_key, self->aes_iv, AES_ENCRYPT);
|
||||
return padded_size;
|
||||
}
|
||||
|
||||
int pad_aes_decrypt (struct mtproto_connection *self, 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, &self->aes_key, self->aes_iv, AES_DECRYPT);
|
||||
return from_len;
|
||||
}
|
||||
#endif
|
549
net.c
|
@ -1,549 +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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright Vitaly Valtman 2013
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <poll.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "net.h"
|
||||
#include "include.h"
|
||||
#include "mtproto-client.h"
|
||||
#include "tree.h"
|
||||
|
||||
#ifndef POLLRDHUP
|
||||
#define POLLRDHUP 0
|
||||
#endif
|
||||
|
||||
#define long_cmp(a,b) ((a) > (b) ? 1 : (a) == (b) ? 0 : -1)
|
||||
DEFINE_TREE(long,long long,long_cmp,0)
|
||||
double get_utime (int clock_id);
|
||||
|
||||
int verbosity;
|
||||
extern struct connection_methods auth_methods;
|
||||
//extern FILE *log_net_f;
|
||||
FILE *log_net_f = 0;
|
||||
|
||||
void fail_connection (struct connection *c);
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
||||
#define PING_TIMEOUT 10
|
||||
|
||||
void start_ping_timer (struct connection *c);
|
||||
int ping_alarm (struct connection *c) {
|
||||
assert (c->state == conn_ready || c->state == conn_connecting);
|
||||
if (get_double_time () - c->last_receive_time > 20 * PING_TIMEOUT) {
|
||||
warning ( "fail connection: reason: ping timeout\n");
|
||||
c->state = conn_failed;
|
||||
fail_connection (c);
|
||||
} else if (get_double_time () - c->last_receive_time > 5 * PING_TIMEOUT && c->state == conn_ready) {
|
||||
debug ("sending PING...\n");
|
||||
int x[3];
|
||||
x[0] = CODE_ping;
|
||||
*(long long *)(x + 1) = lrand48 () * (1ll << 32) + lrand48 ();
|
||||
encrypt_send_message (c->mtconnection, x, 3, 0);
|
||||
start_ping_timer (c);
|
||||
} else {
|
||||
start_ping_timer (c);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void stop_ping_timer (struct connection *c) {
|
||||
if (c->ev.self) {
|
||||
remove_event_timer (c->instance, &c->ev);
|
||||
} else {
|
||||
warning ("trying to stop non-existing ping timer fd: #%d\n", c->fd);
|
||||
}
|
||||
}
|
||||
|
||||
void start_ping_timer (struct connection *c) {
|
||||
c->ev.timeout = get_double_time () + PING_TIMEOUT;
|
||||
c->ev.alarm = (void *)ping_alarm;
|
||||
c->ev.self = c;
|
||||
insert_event_timer (c->instance, &c->ev);
|
||||
}
|
||||
|
||||
void restart_connection (struct connection *c);
|
||||
int fail_alarm (void *ev) {
|
||||
((struct connection *)ev)->in_fail_timer = 0;
|
||||
restart_connection (ev);
|
||||
return 0;
|
||||
}
|
||||
void start_fail_timer (struct connection *c) {
|
||||
if (c->in_fail_timer) { return; }
|
||||
c->in_fail_timer = 1;
|
||||
c->ev.timeout = get_double_time () + 10;
|
||||
c->ev.alarm = (void *)fail_alarm;
|
||||
c->ev.self = c;
|
||||
insert_event_timer (c->instance, &c->ev);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void delete_connection_buffer (struct connection_buffer *b) {
|
||||
tfree (b->start, b->end - b->start);
|
||||
tfree (b, sizeof (*b));
|
||||
}
|
||||
|
||||
int write_out (struct connection *c, const void *_data, int len) {
|
||||
const unsigned char *data = _data;
|
||||
if (!len) { return 0; }
|
||||
assert (len > 0);
|
||||
int x = 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 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 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 flush_out (struct connection *c UU) {
|
||||
}
|
||||
|
||||
#define MAX_CONNECTIONS 100
|
||||
struct connection *Connections[MAX_CONNECTIONS];
|
||||
int max_connection_fd;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void restart_connection (struct connection *c) {
|
||||
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) {
|
||||
debug ("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);
|
||||
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) {
|
||||
debug ( "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 = get_double_time ();
|
||||
start_ping_timer (c);
|
||||
Connections[fd] = c;
|
||||
|
||||
char byte = 0xef;
|
||||
assert (write_out (c, &byte, 1) == 1);
|
||||
flush_out (c);
|
||||
}
|
||||
|
||||
void fail_connection (struct connection *c) {
|
||||
warning ("Lost connection to server... %s:%d\n", c->ip, c->port);
|
||||
telegram_change_state(c->mtconnection->instance, STATE_ERROR, "Lost connection to server\n");
|
||||
}
|
||||
|
||||
extern FILE *log_net_f;
|
||||
int try_write (struct connection *c) {
|
||||
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);
|
||||
|
||||
// Log all written packages
|
||||
if (r > 0 && log_net_f) {
|
||||
// fprintf (log_net_f, "%.02lf %d OUT %s:%d", get_utime (CLOCK_REALTIME), r, c->ip, c->port);
|
||||
int i;
|
||||
for (i = 0; i < r; i++) {
|
||||
// fprintf (log_net_f, " %02x", *(unsigned char *)(c->out_head->rptr + i));
|
||||
}
|
||||
fprintf (log_net_f, "\n");
|
||||
fflush (log_net_f);
|
||||
}
|
||||
|
||||
if (r >= 0) {
|
||||
x += r;
|
||||
c->out_head->rptr += r;
|
||||
if (c->out_head->rptr != c->out_head->wptr) {
|
||||
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) {
|
||||
debug ("fail_connection: write_error %m\n");
|
||||
fail_connection (c);
|
||||
return 0;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
debug ( "Sent %d bytes to %d\n", x, c->fd);
|
||||
c->out_bytes -= x;
|
||||
return x;
|
||||
}
|
||||
|
||||
void hexdump_buf (struct connection_buffer *b) {
|
||||
// TODO: figure out how to log hexdumps to purple log
|
||||
int pos = 0;
|
||||
int rem = 8;
|
||||
while (b) {
|
||||
unsigned char *c = b->rptr;
|
||||
while (c != b->wptr) {
|
||||
if (rem == 8) {
|
||||
//if (pos) { printf ("\n"); }
|
||||
//printf ("%04d", pos);
|
||||
}
|
||||
//printf (" %02x", (int)*c);
|
||||
rem --;
|
||||
pos ++;
|
||||
if (!rem) {
|
||||
rem = 8;
|
||||
}
|
||||
c ++;
|
||||
}
|
||||
b = b->next;
|
||||
}
|
||||
//printf ("\n");
|
||||
|
||||
}
|
||||
|
||||
void try_rpc_read (struct connection *c) {
|
||||
assert (c->in_head);
|
||||
if (verbosity >= 3) {
|
||||
hexdump_buf (c->in_head);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (c->in_bytes < 1) { return; }
|
||||
unsigned len = 0;
|
||||
unsigned t = 0;
|
||||
assert (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 (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 (read_in (c, &t, 1) == 1);
|
||||
assert (t == len);
|
||||
assert (len >= 1);
|
||||
} else {
|
||||
assert (len == 0x7f);
|
||||
assert (read_in (c, &len, 4) == 4);
|
||||
len = (len >> 8);
|
||||
assert (len >= 1);
|
||||
}
|
||||
len *= 4;
|
||||
int op;
|
||||
assert (read_in_lookup (c, &op, 4) == 4);
|
||||
c->methods->execute (c, op, len);
|
||||
}
|
||||
}
|
||||
|
||||
void try_read (struct connection *c) {
|
||||
debug ( "try read: fd = %d\n", c->fd);
|
||||
if (!c->in_tail) {
|
||||
c->in_head = c->in_tail = new_connection_buffer (1 << 20);
|
||||
}
|
||||
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 && log_net_f) {
|
||||
fprintf (log_net_f, "%.02lf %d IN %s:%d", get_utime (CLOCK_REALTIME), r, c->ip, c->port);
|
||||
int i;
|
||||
for (i = 0; i < r; i++) {
|
||||
fprintf (log_net_f, " %02x", *(unsigned char *)(c->in_tail->wptr + i));
|
||||
}
|
||||
fprintf (log_net_f, "\n");
|
||||
fflush (log_net_f);
|
||||
}
|
||||
if (r > 0) {
|
||||
c->last_receive_time = 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) {
|
||||
debug ("fail_connection: read_error %m\n");
|
||||
fail_connection (c);
|
||||
return;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
debug ( "Received %d bytes from fd=#%d and DC %d(%s, %d)\n", x,
|
||||
c->fd, c->session->dc->id, c->session->dc->ip, c->session->dc->port);
|
||||
c->in_bytes += x;
|
||||
if (x) {
|
||||
try_rpc_read (c);
|
||||
}
|
||||
}
|
||||
|
||||
int send_all_acks (struct session *S) {
|
||||
info ("send_all_acks(dc=%d)\n", S->dc->id);
|
||||
if (!S->c) {
|
||||
warning ("WARNING: cannot send acks, session has no active connection");
|
||||
return -1;
|
||||
}
|
||||
struct mtproto_connection *mt = S->c->mtconnection;
|
||||
|
||||
clear_packet (mt);
|
||||
out_int (mt, CODE_msgs_ack);
|
||||
out_int (mt, CODE_vector);
|
||||
out_int (mt, tree_count_long (S->ack_tree));
|
||||
while (S->ack_tree) {
|
||||
long long x = tree_get_min_long (S->ack_tree);
|
||||
out_long (mt, x);
|
||||
S->ack_tree = tree_delete_long (S->ack_tree, x);
|
||||
}
|
||||
encrypt_send_message (mt, mt->packet_buffer, mt->packet_ptr - mt->packet_buffer, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void insert_msg_id (struct session *S, long long id) {
|
||||
if (!S->ack_tree) {
|
||||
debug ("Creating ack_tree pointing to session %p\n");
|
||||
S->ev.alarm = (void *)send_all_acks;
|
||||
S->ev.self = (void *)S;
|
||||
S->ev.timeout = get_double_time () + ACK_TIMEOUT;
|
||||
insert_event_timer (S->c->instance, &S->ev);
|
||||
}
|
||||
if (!tree_lookup_long (S->ack_tree, id)) {
|
||||
S->ack_tree = tree_insert_long (S->ack_tree, id, lrand48 ());
|
||||
}
|
||||
}
|
||||
|
||||
struct dc *alloc_dc (struct dc* DC_list[], int id, char *ip, int port UU) {
|
||||
assert (!DC_list[id]);
|
||||
struct dc *DC = talloc0 (sizeof (*DC));
|
||||
DC->id = id;
|
||||
DC->ip = ip;
|
||||
DC->port = port;
|
||||
DC_list[id] = DC;
|
||||
return DC;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap an existing socket file descriptor and make it usable as a connection,
|
||||
*/
|
||||
struct connection *fd_create_connection (struct dc *DC, int fd,
|
||||
struct telegram *instance, struct connection_methods *methods,
|
||||
struct mtproto_connection *mtp) {
|
||||
|
||||
// create a connection
|
||||
struct connection *c = talloc0 (sizeof (*c));
|
||||
c->fd = fd;
|
||||
c->ip = tstrdup (DC->ip);
|
||||
c->flags = 0;
|
||||
c->state = conn_ready;
|
||||
c->port = DC->port;
|
||||
c->methods = methods;
|
||||
c->instance = instance;
|
||||
c->last_receive_time = get_double_time ();
|
||||
debug ( "connect to %s:%d successful\n", DC->ip, DC->port);
|
||||
|
||||
if (!DC->sessions[0]) {
|
||||
struct session *S = talloc0 (sizeof (*S));
|
||||
assert (RAND_pseudo_bytes ((unsigned char *) &S->session_id, 8) >= 0);
|
||||
S->dc = DC;
|
||||
S->c = c;
|
||||
DC->sessions[0] = S;
|
||||
}
|
||||
if (!DC->sessions[0]->c) {
|
||||
DC->sessions[0]->c = c;
|
||||
}
|
||||
// add backreference to session
|
||||
c->session = DC->sessions[0];
|
||||
|
||||
// add backreference to used mtproto-connection
|
||||
c->mtconnection = mtp;
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the connection by freeing all attached buffers and setting
|
||||
* the state to conn_stopped, but does NOT close the attached file descriptor
|
||||
*/
|
||||
void fd_close_connection(struct connection *c) {
|
||||
struct connection_buffer *b = c->out_head;
|
||||
while (b) {
|
||||
struct connection_buffer *d = b;
|
||||
b = b->next;
|
||||
delete_connection_buffer (d);
|
||||
}
|
||||
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_stopped;
|
||||
c->out_bytes = c->in_bytes = 0;
|
||||
tfree(c, sizeof(struct connection));
|
||||
}
|
||||
|
163
net.h
|
@ -1,163 +0,0 @@
|
|||
/*
|
||||
This file is part of telegram-client.
|
||||
|
||||
struct telegram-client is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
struct telegram-client is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this telegram-client. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright Vitaly Valtman 2013
|
||||
*/
|
||||
#ifndef __NET_H__
|
||||
#define __NET_H__
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <poll.h>
|
||||
struct dc;
|
||||
#include "mtproto-client.h"
|
||||
#include "telegram.h"
|
||||
#include "queries.h"
|
||||
|
||||
#define TG_SERVER "149.154.167.50"
|
||||
#define TG_DC_NUM 2
|
||||
#define TG_SERVER_TEST "149.154.167.40"
|
||||
#define TG_TEST_DC_NUM 2
|
||||
#define TG_APP_HASH "99428c722d0ed59b9cd844e4577cb4bb"
|
||||
#define TG_APP_ID 16154
|
||||
#define TG_PORT 443
|
||||
|
||||
#define ACK_TIMEOUT 1
|
||||
#define MAX_DC_ID 10
|
||||
|
||||
// typedef struct mtproto_connection not available right now
|
||||
struct mtproto_connection;
|
||||
|
||||
struct connection;
|
||||
struct connection_methods {
|
||||
int (*ready) (struct connection *c);
|
||||
int (*close) (struct connection *c);
|
||||
int (*execute) (struct connection *c, int op, int len);
|
||||
};
|
||||
|
||||
|
||||
#define MAX_DC_SESSIONS 3
|
||||
|
||||
struct session {
|
||||
struct dc *dc;
|
||||
long long session_id;
|
||||
int seq_no;
|
||||
struct connection *c;
|
||||
struct tree_long *ack_tree;
|
||||
struct event_timer ev;
|
||||
};
|
||||
|
||||
struct dc {
|
||||
int id;
|
||||
int port;
|
||||
int flags;
|
||||
char *ip;
|
||||
char *user;
|
||||
struct session *sessions[MAX_DC_SESSIONS];
|
||||
char auth_key[256];
|
||||
long long auth_key_id;
|
||||
long long server_salt;
|
||||
|
||||
int server_time_delta;
|
||||
double server_time_udelta;
|
||||
int has_auth;
|
||||
};
|
||||
|
||||
#define DC_SERIALIZED_MAGIC 0x64582faa
|
||||
#define DC_SERIALIZED_MAGIC_V2 0x94032abb
|
||||
#define STATE_FILE_MAGIC 0x84217a0d
|
||||
#define SECRET_CHAT_FILE_MAGIC 0xa9840add
|
||||
|
||||
struct dc_serialized {
|
||||
int magic;
|
||||
int port;
|
||||
char ip[64];
|
||||
char user[64];
|
||||
char auth_key[256];
|
||||
long long auth_key_id, server_salt;
|
||||
int authorized;
|
||||
};
|
||||
|
||||
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 connection_methods *methods;
|
||||
struct session *session;
|
||||
void *extra;
|
||||
struct event_timer ev;
|
||||
double last_receive_time;
|
||||
struct telegram *instance;
|
||||
struct mtproto_connection *mtconnection;
|
||||
};
|
||||
|
||||
extern struct connection *Connections[];
|
||||
|
||||
int write_out (struct connection *c, const void *data, int len);
|
||||
void flush_out (struct connection *c);
|
||||
int read_in (struct connection *c, void *data, int len);
|
||||
|
||||
void create_all_outbound_connections (void);
|
||||
|
||||
void dc_create_session (struct dc *DC);
|
||||
void insert_msg_id (struct session *S, long long id);
|
||||
struct dc *alloc_dc (struct dc* DC_list[], int id, char *ip, int port);
|
||||
|
||||
#define GET_DC(c) (c->session->dc)
|
||||
|
||||
// export read and write methods to redirect network control
|
||||
void try_read (struct connection *c);
|
||||
void try_rpc_read (struct connection *c);
|
||||
int try_write (struct connection *c);
|
||||
|
||||
struct connection *fd_create_connection (struct dc *DC, int fd, struct telegram *instance,
|
||||
struct connection_methods *methods, struct mtproto_connection *mtp);
|
||||
void fd_close_connection(struct connection *c);
|
||||
|
||||
void start_ping_timer (struct connection *c);
|
||||
void stop_ping_timer (struct connection *c);
|
||||
int send_all_acks (struct session *S);
|
||||
|
||||
#endif
|
105
no-preview.h
|
@ -1,105 +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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright Vitaly Valtman 2013
|
||||
*/
|
||||
|
||||
// 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};
|
|
@ -1,177 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
width="240"
|
||||
height="240"
|
||||
sodipodi:docname="a2c88e812ef42ae72650a2e4e4745a90.png">
|
||||
<metadata
|
||||
id="metadata8">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs6">
|
||||
<linearGradient
|
||||
id="linearGradient3877">
|
||||
<stop
|
||||
style="stop-color:#eff7fc;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3879" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop3881" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3829">
|
||||
<stop
|
||||
id="stop3831"
|
||||
offset="0"
|
||||
style="stop-color:#1f96d4;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop3833"
|
||||
offset="1"
|
||||
style="stop-color:#37aee2;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3821">
|
||||
<stop
|
||||
style="stop-color:#37aee2;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3823" />
|
||||
<stop
|
||||
style="stop-color:#1e96c8;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop3825" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient3783">
|
||||
<stop
|
||||
style="stop-color:#1e94d3;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3785" />
|
||||
<stop
|
||||
id="stop3803"
|
||||
offset="1"
|
||||
style="stop-color:#1e94d3;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3783"
|
||||
id="linearGradient3827"
|
||||
x1="-10"
|
||||
y1="90"
|
||||
x2="30"
|
||||
y2="50"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3783-1"
|
||||
id="linearGradient3827-7"
|
||||
x1="-10"
|
||||
y1="90"
|
||||
x2="30"
|
||||
y2="50"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
id="linearGradient3783-1">
|
||||
<stop
|
||||
style="stop-color:#1e94d3;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop3785-2" />
|
||||
<stop
|
||||
id="stop3803-6"
|
||||
offset="1"
|
||||
style="stop-color:#1e94d3;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3821"
|
||||
id="linearGradient3873"
|
||||
x1="16.666666"
|
||||
y1="56.666668"
|
||||
x2="6.6666665"
|
||||
y2="80"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3877"
|
||||
id="linearGradient3883"
|
||||
x1="135"
|
||||
y1="120"
|
||||
x2="160"
|
||||
y2="160"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1366"
|
||||
inkscape:window-height="705"
|
||||
id="namedview4"
|
||||
showgrid="false"
|
||||
inkscape:zoom="0.70710678"
|
||||
inkscape:cx="268.45834"
|
||||
inkscape:cy="192.89138"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg2">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid2987" />
|
||||
</sodipodi:namedview>
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:url(#linearGradient3873);fill-opacity:1;stroke:none"
|
||||
id="path2995-1-0"
|
||||
sodipodi:cx="10"
|
||||
sodipodi:cy="70"
|
||||
sodipodi:rx="20"
|
||||
sodipodi:ry="20"
|
||||
d="m 30,70 a 20,20 0 1 1 -40,0 20,20 0 1 1 40,0 z"
|
||||
transform="matrix(6,0,0,6,60,-300)" />
|
||||
<path
|
||||
style="fill:#c8daea;fill-opacity:1;stroke:none"
|
||||
d="m 98,175 c -3.887644,0 -3.226996,-1.46793 -4.567796,-5.16949 l -11.440678,-37.62712 70.805084,-44.237289 8.26271,2.161017 -6.8644,18.813562 z"
|
||||
id="path2993"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccc" />
|
||||
<path
|
||||
style="fill:#a9c9dd;fill-opacity:1;stroke:none"
|
||||
d="m 98,175 c 3,0 4.32989,-1.36747 6,-3 2.57835,-2.52034 36,-35 36,-35 l -20.47193,-4.95511 -19,12 L 98,174 z"
|
||||
id="path2989"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="csccccc" />
|
||||
<path
|
||||
style="fill:url(#linearGradient3883);stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
|
||||
d="m 100.04237,144.40678 48.36017,35.72884 c 5.51851,3.04487 9.5014,1.46836 10.87626,-5.12353 l 19.68513,-92.762819 c 2.01542,-8.080226 -3.08008,-11.745195 -8.35944,-9.348192 L 55.010511,117.48476 c -7.890082,3.1647 -7.844107,7.56662 -1.438184,9.52797 l 29.662531,9.2583 68.673252,-43.325271 c 3.24187,-1.965881 6.21727,-0.908988 3.77523,1.25841 z"
|
||||
id="path2991"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccccc" />
|
||||
</svg>
|
Before Width: | Height: | Size: 5.4 KiB |
161
queries.h
|
@ -1,161 +0,0 @@
|
|||
/*
|
||||
This file is part of telegram-client.
|
||||
|
||||
struct telegram-client is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
struct telegram-client is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this telegram-client. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright Vitaly Valtman 2013
|
||||
*/
|
||||
#ifndef __QUERIES_H__
|
||||
#define __QUERIES_H__
|
||||
|
||||
#pragma once
|
||||
#include "structures.h"
|
||||
|
||||
struct telegram;
|
||||
struct encr_video;
|
||||
struct document;
|
||||
struct secret_chat;
|
||||
struct tree_query;
|
||||
struct tree_timer;
|
||||
#define QUERY_ACK_RECEIVED 1
|
||||
|
||||
struct query;
|
||||
struct query_methods {
|
||||
int (*on_answer)(struct query *q);
|
||||
int (*on_error)(struct query *q, int error_code, int len, char *error);
|
||||
int (*on_timeout)(struct query *q);
|
||||
};
|
||||
|
||||
struct download_desc{
|
||||
void *data;
|
||||
int type;
|
||||
};
|
||||
|
||||
struct download {
|
||||
int offset;
|
||||
int size;
|
||||
long long volume;
|
||||
long long secret;
|
||||
long long access_hash;
|
||||
int local_id;
|
||||
int dc;
|
||||
void *extra;
|
||||
int fd;
|
||||
char *name;
|
||||
long long id;
|
||||
unsigned char *iv;
|
||||
unsigned char *key;
|
||||
int type;
|
||||
struct mtproto_connection *c;
|
||||
};
|
||||
void load_next_part (struct telegram *instance, struct download *D);
|
||||
|
||||
struct event_timer {
|
||||
double timeout;
|
||||
int (*alarm)(void *self);
|
||||
void *self;
|
||||
};
|
||||
|
||||
struct query {
|
||||
long long msg_id;
|
||||
int data_len;
|
||||
int flags;
|
||||
int seq_no;
|
||||
void *data;
|
||||
struct query_methods *methods;
|
||||
struct event_timer ev;
|
||||
struct dc *DC;
|
||||
struct session *session;
|
||||
void *extra;
|
||||
};
|
||||
|
||||
|
||||
struct query *send_query (struct telegram *instance, struct dc *DC, int len, void *data, struct query_methods *methods, void *extra);
|
||||
void query_ack (struct telegram *instance, long long id);
|
||||
void query_error (struct telegram *instance, long long id);
|
||||
void query_result (struct telegram *instance, long long id);
|
||||
void query_restart (struct telegram *instance, long long id);
|
||||
|
||||
void insert_event_timer (struct telegram *instance, struct event_timer *ev);
|
||||
void remove_event_timer (struct telegram *instance, struct event_timer *ev);
|
||||
double next_timer_in (struct telegram *instance);
|
||||
void work_timers (struct telegram *instance);
|
||||
|
||||
extern struct query_methods help_get_config_methods;
|
||||
|
||||
void do_send_code (struct telegram *instance, const char *user);
|
||||
void do_phone_call (struct telegram *instance, const char *user);
|
||||
void do_send_code_result (struct telegram *instance, const char *code);
|
||||
double get_double_time (void);
|
||||
|
||||
void do_update_contact_list (struct telegram *instance);
|
||||
union user_chat;
|
||||
void do_send_message (struct telegram *instance, peer_id_t id, const char *msg, int len);
|
||||
void do_send_text (struct telegram *instance, peer_id_t id, char *file);
|
||||
void do_get_history (struct telegram *instance, peer_id_t id, int limit);
|
||||
void do_get_dialog_list (struct telegram*);
|
||||
void do_get_dialog_list_ex (struct telegram*);
|
||||
void do_send_photo (struct telegram *instance, int type, peer_id_t to_id, char *file_name);
|
||||
void do_get_chat_info (struct telegram *instance, peer_id_t id);
|
||||
void do_get_user_list_info_silent (struct telegram *instance, int num, int *list);
|
||||
void do_get_user_info (struct telegram *instance, peer_id_t id, int showInfo);
|
||||
void do_forward_message (struct telegram *instance, peer_id_t id, int n);
|
||||
void do_rename_chat (struct telegram *instance, peer_id_t id, char *name);
|
||||
void do_load_encr_video (struct telegram *instance, struct encr_video *V, void *extra);
|
||||
void do_create_encr_chat_request (struct telegram *instance, int user_id);
|
||||
void do_create_secret_chat (struct telegram *instance, peer_id_t id);
|
||||
void do_create_group_chat (struct telegram *instance, peer_id_t id, char *chat_topic);
|
||||
void do_get_suggested (struct telegram*);
|
||||
|
||||
struct photo;
|
||||
struct video;
|
||||
void do_load_photo (struct telegram *instance, struct photo *photo, int photoBig, void *extra);
|
||||
void do_load_video_thumb (struct telegram *instance, struct video *video, void *extra);
|
||||
void do_load_audio (struct telegram *instance, struct video *V, void *extra);
|
||||
void do_load_video (struct telegram *instance, struct video *V, void *extra);
|
||||
void do_load_document (struct telegram *instance, struct document *V, void *extra);
|
||||
void do_load_document_thumb (struct telegram *instance, struct document *video, void *extra);
|
||||
void do_help_get_config (struct telegram *instance);
|
||||
void do_auth_check_phone (struct telegram *instance, const char *user);
|
||||
void do_get_nearest_dc (struct telegram*);
|
||||
void do_send_code_result_auth (struct telegram *instance, const char *code, const char *first_name, const char *last_name);
|
||||
void do_import_auth (struct telegram *instance, int num, void (*cb)(void *extra), void *extra);
|
||||
void do_export_auth (struct telegram *instance, int num, void (*cb)(char *export_auth_str, int len, void *extra), void *extra);
|
||||
void do_add_contact (struct telegram *instance, const char *phone, int phone_len, const char *first_name, int first_name_len, const char *last_name, int last_name_len, int force);
|
||||
void do_msg_search (struct telegram *instance, peer_id_t id, int from, int to, int limit, const char *s);
|
||||
void do_accept_encr_chat_request (struct telegram *instance, struct secret_chat *E);
|
||||
void do_get_difference (struct telegram*, int sync_from_start);
|
||||
void do_mark_read (struct telegram *instance, peer_id_t id);
|
||||
void do_visualize_key (struct binlog *bl, peer_id_t id);
|
||||
void do_create_keys_end (struct telegram *, struct secret_chat *U);
|
||||
|
||||
void do_add_user_to_chat (struct telegram *instance, peer_id_t chat_id, peer_id_t id, int limit);
|
||||
void do_del_user_from_chat (struct telegram *instance, peer_id_t chat_id, peer_id_t id);
|
||||
void do_update_status (struct telegram *instance, int online);
|
||||
void do_contacts_search (struct telegram *instance, int limit, const char *s);
|
||||
void do_send_msg (struct telegram *instance, struct message *M);
|
||||
void do_delete_msg (struct telegram *instance, long long id);
|
||||
void do_restore_msg (struct telegram *instance, long long id);
|
||||
|
||||
// For binlog
|
||||
|
||||
int get_dh_config_on_answer (struct query *q);
|
||||
void fetch_dc_option (struct telegram *instance);
|
||||
void free_queries (struct telegram *instance);
|
||||
void free_timers (struct telegram *instance);
|
||||
#endif
|
||||
|
||||
const char *get_last_err();
|
||||
|
||||
int all_queries_done();
|
2090
structures.c
423
structures.h
|
@ -1,423 +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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright Vitaly Valtman 2013
|
||||
*/
|
||||
#ifndef __STRUCTURES_H__
|
||||
#define __STRUCTURES_H__
|
||||
#pragma once
|
||||
|
||||
// forward-declrataions
|
||||
struct mtproto_connection;
|
||||
struct binlog;
|
||||
typedef struct { int type; int id; } peer_id_t;
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
//#define FLAG_EMPTY 1
|
||||
#define FLAG_MESSAGE_EMPTY 1
|
||||
#define FLAG_DELETED 2
|
||||
#define FLAG_FORBIDDEN 4
|
||||
#define FLAG_HAS_PHOTO 8
|
||||
#define FLAG_CREATED 16
|
||||
|
||||
#define FLAG_USER_SELF 128
|
||||
#define FLAG_USER_FOREIGN 256
|
||||
#define FLAG_USER_CONTACT 512
|
||||
#define FLAG_USER_IN_CONTACT 1024
|
||||
#define FLAG_USER_OUT_CONTACT 2048
|
||||
|
||||
#define FLAG_CHAT_IN_CHAT 128
|
||||
|
||||
#define FLAG_ENCRYPTED 4096
|
||||
#define FLAG_PENDING 8192
|
||||
|
||||
|
||||
struct file_location {
|
||||
int dc;
|
||||
long long volume;
|
||||
int local_id;
|
||||
long long secret;
|
||||
};
|
||||
|
||||
struct photo_size {
|
||||
char *type;
|
||||
struct file_location loc;
|
||||
int w;
|
||||
int h;
|
||||
int size;
|
||||
char *data;
|
||||
};
|
||||
|
||||
struct geo {
|
||||
double longitude;
|
||||
double latitude;
|
||||
};
|
||||
|
||||
struct photo {
|
||||
long long id;
|
||||
long long access_hash;
|
||||
int user_id;
|
||||
int date;
|
||||
char *caption;
|
||||
struct geo geo;
|
||||
int sizes_num;
|
||||
struct photo_size *sizes;
|
||||
};
|
||||
|
||||
struct encr_photo {
|
||||
long long id;
|
||||
long long access_hash;
|
||||
int dc_id;
|
||||
int size;
|
||||
int key_fingerprint;
|
||||
|
||||
unsigned char *key;
|
||||
unsigned char *iv;
|
||||
int w;
|
||||
int h;
|
||||
};
|
||||
|
||||
struct encr_video {
|
||||
long long id;
|
||||
long long access_hash;
|
||||
int dc_id;
|
||||
int size;
|
||||
int key_fingerprint;
|
||||
|
||||
unsigned char *key;
|
||||
unsigned char *iv;
|
||||
int w;
|
||||
int h;
|
||||
int duration;
|
||||
};
|
||||
|
||||
struct encr_audio {
|
||||
long long id;
|
||||
long long access_hash;
|
||||
int dc_id;
|
||||
int size;
|
||||
int key_fingerprint;
|
||||
|
||||
unsigned char *key;
|
||||
unsigned char *iv;
|
||||
int duration;
|
||||
};
|
||||
|
||||
struct encr_document {
|
||||
long long id;
|
||||
long long access_hash;
|
||||
int dc_id;
|
||||
int size;
|
||||
int key_fingerprint;
|
||||
|
||||
unsigned char *key;
|
||||
unsigned char *iv;
|
||||
char *file_name;
|
||||
char *mime_type;
|
||||
};
|
||||
|
||||
struct encr_file {
|
||||
char *filename;
|
||||
unsigned char *key;
|
||||
unsigned char *iv;
|
||||
};
|
||||
|
||||
|
||||
struct user_status {
|
||||
int online;
|
||||
int when;
|
||||
};
|
||||
|
||||
struct tgl_user {
|
||||
peer_id_t id;
|
||||
int flags;
|
||||
struct message *last;
|
||||
char *print_name;
|
||||
int structure_version;
|
||||
struct file_location photo_big;
|
||||
struct file_location photo_small;
|
||||
long long photo_id;
|
||||
struct photo photo;
|
||||
char *first_name;
|
||||
char *last_name;
|
||||
char *phone;
|
||||
long long access_hash;
|
||||
struct user_status status;
|
||||
int blocked;
|
||||
char *real_first_name;
|
||||
char *real_last_name;
|
||||
};
|
||||
|
||||
|
||||
struct chat_user {
|
||||
int user_id;
|
||||
int inviter_id;
|
||||
int date;
|
||||
};
|
||||
|
||||
struct chat {
|
||||
peer_id_t id;
|
||||
int flags;
|
||||
struct message *last;
|
||||
char *print_title;
|
||||
int structure_version;
|
||||
struct file_location photo_big;
|
||||
struct file_location photo_small;
|
||||
struct photo photo;
|
||||
char *title;
|
||||
int users_num;
|
||||
int user_list_size;
|
||||
int user_list_version;
|
||||
struct chat_user *user_list;
|
||||
int date;
|
||||
int version;
|
||||
int admin_id;
|
||||
};
|
||||
|
||||
enum secret_chat_state {
|
||||
sc_none,
|
||||
sc_waiting,
|
||||
sc_request,
|
||||
sc_ok,
|
||||
sc_deleted
|
||||
};
|
||||
|
||||
struct secret_chat {
|
||||
peer_id_t id;
|
||||
int flags;
|
||||
struct message *last;
|
||||
char *print_name;
|
||||
int structure_version;
|
||||
struct file_location photo_big;
|
||||
struct file_location photo_small;
|
||||
struct photo photo;
|
||||
int user_id;
|
||||
int admin_id;
|
||||
int date;
|
||||
int ttl;
|
||||
long long access_hash;
|
||||
unsigned char *g_key;
|
||||
unsigned char *nonce;
|
||||
|
||||
enum secret_chat_state state;
|
||||
int key[64];
|
||||
long long key_fingerprint;
|
||||
};
|
||||
|
||||
typedef union peer {
|
||||
struct {
|
||||
peer_id_t id;
|
||||
int flags;
|
||||
struct message *last;
|
||||
char *print_name;
|
||||
int structure_version;
|
||||
struct file_location photo_big;
|
||||
struct file_location photo_small;
|
||||
struct photo photo;
|
||||
};
|
||||
struct tgl_user user;
|
||||
struct chat chat;
|
||||
struct secret_chat encr_chat;
|
||||
} peer_t;
|
||||
|
||||
struct video {
|
||||
long long id;
|
||||
long long access_hash;
|
||||
int user_id;
|
||||
int date;
|
||||
int size;
|
||||
int dc_id;
|
||||
struct photo_size thumb;
|
||||
char *caption;
|
||||
int duration;
|
||||
int w;
|
||||
int h;
|
||||
};
|
||||
|
||||
struct audio {
|
||||
long long id;
|
||||
long long access_hash;
|
||||
int user_id;
|
||||
int date;
|
||||
int size;
|
||||
int dc_id;
|
||||
int duration;
|
||||
};
|
||||
|
||||
struct document {
|
||||
long long id;
|
||||
long long access_hash;
|
||||
int user_id;
|
||||
int date;
|
||||
int size;
|
||||
int dc_id;
|
||||
struct photo_size thumb;
|
||||
char *caption;
|
||||
char *mime_type;
|
||||
};
|
||||
|
||||
struct message_action {
|
||||
unsigned type;
|
||||
union {
|
||||
struct {
|
||||
char *title;
|
||||
int user_num;
|
||||
int *users;
|
||||
};
|
||||
char *new_title;
|
||||
struct photo photo;
|
||||
int user;
|
||||
int ttl;
|
||||
};
|
||||
};
|
||||
|
||||
struct message_media {
|
||||
unsigned type;
|
||||
union {
|
||||
struct photo photo;
|
||||
struct video video;
|
||||
struct audio audio;
|
||||
struct document document;
|
||||
struct geo geo;
|
||||
struct {
|
||||
char *phone;
|
||||
char *first_name;
|
||||
char *last_name;
|
||||
int user_id;
|
||||
};
|
||||
struct encr_photo encr_photo;
|
||||
struct encr_video encr_video;
|
||||
struct encr_audio encr_audio;
|
||||
struct encr_document encr_document;
|
||||
struct encr_file encr_file;
|
||||
struct {
|
||||
void *data;
|
||||
int data_size;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
struct message {
|
||||
struct message *next_use, *prev_use;
|
||||
struct message *next, *prev;
|
||||
long long id;
|
||||
int flags;
|
||||
peer_id_t fwd_from_id;
|
||||
int fwd_date;
|
||||
peer_id_t from_id;
|
||||
peer_id_t to_id;
|
||||
int out;
|
||||
int unread;
|
||||
int date;
|
||||
int service;
|
||||
struct telegram *instance;
|
||||
union {
|
||||
struct message_action action;
|
||||
struct {
|
||||
char *message;
|
||||
int message_len;
|
||||
struct message_media media;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
int fetch_file_location (struct mtproto_connection *mtp, struct file_location *loc);
|
||||
int fetch_user_status (struct mtproto_connection *mtp, struct user_status *S);
|
||||
int fetch_user (struct mtproto_connection *mtp, struct tgl_user *U);
|
||||
struct tgl_user *fetch_alloc_user (struct mtproto_connection *mtp);
|
||||
struct tgl_user *fetch_alloc_user_full (struct mtproto_connection *mtp);
|
||||
struct chat *fetch_alloc_chat (struct mtproto_connection *mtp);
|
||||
struct chat *fetch_alloc_chat_full (struct mtproto_connection *mtp);
|
||||
struct secret_chat *fetch_alloc_encrypted_chat (struct mtproto_connection *mtp);
|
||||
struct message *fetch_alloc_message (struct mtproto_connection *self, struct telegram *instance);
|
||||
struct message *fetch_alloc_geo_message (struct mtproto_connection *mtp, struct telegram *instance);
|
||||
struct message *fetch_alloc_message_short (struct mtproto_connection *mtp, struct telegram *instance);
|
||||
struct message *fetch_alloc_message_short_chat (struct mtproto_connection *self, struct telegram *instance);
|
||||
struct message *fetch_alloc_encrypted_message (struct mtproto_connection *mtp, struct telegram *instance);
|
||||
void fetch_encrypted_message_file (struct mtproto_connection *mtp, struct message_media *M);
|
||||
void fetch_skip_encrypted_message_file (struct mtproto_connection *mtp);
|
||||
void fetch_message_action_encrypted (struct mtproto_connection *mtp, struct message_action *M);
|
||||
peer_id_t fetch_peer_id (struct mtproto_connection *mtp);
|
||||
|
||||
void fetch_message_media (struct mtproto_connection *mtp, struct message_media *M);
|
||||
void fetch_message_media_encrypted (struct mtproto_connection *mtp, struct message_media *M);
|
||||
void fetch_message_action (struct mtproto_connection *mtp, struct message_action *M);
|
||||
void message_insert_tree (struct message *M);
|
||||
|
||||
void free_user (struct tgl_user *U);
|
||||
void free_chat (struct chat *U);
|
||||
|
||||
char *create_print_name (struct binlog *bl, peer_id_t id, const char *a1, const char *a2, const char *a3, const char *a4);
|
||||
|
||||
int print_stat (struct binlog *bl, char *s, int len);
|
||||
peer_t *user_chat_get (struct binlog *bl, peer_id_t id);
|
||||
struct message *message_get (struct binlog *bl, long long id);
|
||||
void update_message_id (struct message *M, long long id);
|
||||
void message_insert (struct message *M);
|
||||
void fetch_photo (struct mtproto_connection *mtp, struct photo *P);
|
||||
void insert_encrypted_chat (struct binlog *bl, peer_t *P);
|
||||
void insert_user (struct binlog *bl, peer_t *P);
|
||||
void insert_chat (struct binlog *bl, peer_t *P);
|
||||
void free_photo (struct photo *P);
|
||||
void message_insert_unsent (struct message *M);
|
||||
void message_remove_unsent (struct message *M);
|
||||
void send_all_unsent (struct binlog *bl);
|
||||
void message_remove_tree (struct message *M);
|
||||
void message_add_peer (struct message *M);
|
||||
void message_del_peer (struct message *M);
|
||||
void free_message (struct message *M);
|
||||
void message_del_use (struct message *M);
|
||||
void peer_insert_name (struct binlog *bl, peer_t *P);
|
||||
void peer_delete_name (struct binlog *bl, peer_t *P);
|
||||
peer_t *peer_lookup_name (struct binlog *bl, const char *s);
|
||||
|
||||
int user_get_alias(peer_t *user, char *buffer, int maxlen);
|
||||
|
||||
#define PEER_USER 1
|
||||
#define PEER_CHAT 2
|
||||
#define PEER_GEO_CHAT 3
|
||||
#define PEER_ENCR_CHAT 4
|
||||
#define PEER_UNKNOWN 0
|
||||
|
||||
#define MK_USER(id) set_peer_id (PEER_USER,id)
|
||||
#define MK_CHAT(id) set_peer_id (PEER_CHAT,id)
|
||||
#define MK_GEO_CHAT(id) set_peer_id (PEER_GEO_CHAT,id)
|
||||
#define MK_ENCR_CHAT(id) set_peer_id (PEER_ENCR_CHAT,id)
|
||||
|
||||
static inline int get_peer_type (peer_id_t id) {
|
||||
return id.type;
|
||||
}
|
||||
|
||||
static inline int get_peer_id (peer_id_t id) {
|
||||
return id.id;
|
||||
}
|
||||
|
||||
static inline peer_id_t set_peer_id (int type, int id) {
|
||||
peer_id_t ID;
|
||||
ID.id = id;
|
||||
ID.type = type;
|
||||
return ID;
|
||||
}
|
||||
|
||||
static inline int cmp_peer_id (peer_id_t a, peer_id_t b) {
|
||||
return memcmp (&a, &b, sizeof (a));
|
||||
}
|
||||
|
||||
void free_messages (struct binlog *bl);
|
||||
void free_peers (struct binlog *bl);
|
||||
#endif
|
||||
|
372
telegram-base.c
Normal file
|
@ -0,0 +1,372 @@
|
|||
#define _GNU_SOURCE
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <tgl.h>
|
||||
#include <binlog.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <request.h>
|
||||
|
||||
#include "telegram-purple.h"
|
||||
#include "msglog.h"
|
||||
|
||||
#define DC_SERIALIZED_MAGIC 0x868aa81d
|
||||
#define STATE_FILE_MAGIC 0x28949a93
|
||||
#define SECRET_CHAT_FILE_MAGIC 0x37a1988a
|
||||
|
||||
|
||||
void read_state_file (struct tgl_state *TLS) {
|
||||
char *name = 0;
|
||||
if (asprintf (&name, "%s/%s", TLS->base_path, "state") < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int state_file_fd = open (name, O_CREAT | O_RDWR, 0600);
|
||||
free (name);
|
||||
|
||||
if (state_file_fd < 0) {
|
||||
return;
|
||||
}
|
||||
int version, magic;
|
||||
if (read (state_file_fd, &magic, 4) < 4) { close (state_file_fd); return; }
|
||||
if (magic != (int)STATE_FILE_MAGIC) { close (state_file_fd); return; }
|
||||
if (read (state_file_fd, &version, 4 || version < 0) < 4) { close (state_file_fd); return; }
|
||||
int x[4];
|
||||
if (read (state_file_fd, x, 16) < 16) {
|
||||
close (state_file_fd);
|
||||
return;
|
||||
}
|
||||
int pts = x[0];
|
||||
int qts = x[1];
|
||||
int seq = x[2];
|
||||
int date = x[3];
|
||||
close (state_file_fd);
|
||||
bl_do_set_seq (TLS, seq);
|
||||
bl_do_set_pts (TLS, pts);
|
||||
bl_do_set_qts (TLS, qts);
|
||||
bl_do_set_date (TLS, date);
|
||||
}
|
||||
|
||||
void write_state_file (struct tgl_state *TLS) {
|
||||
int wseq;
|
||||
int wpts;
|
||||
int wqts;
|
||||
int wdate;
|
||||
wseq = TLS->seq; wpts = TLS->pts; wqts = TLS->qts; wdate = TLS->date;
|
||||
|
||||
char *name = 0;
|
||||
if (asprintf (&name, "%s/%s", TLS->base_path, "state") < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int state_file_fd = open (name, O_CREAT | O_RDWR, 0600);
|
||||
free (name);
|
||||
|
||||
if (state_file_fd < 0) {
|
||||
return;
|
||||
}
|
||||
int x[6];
|
||||
x[0] = STATE_FILE_MAGIC;
|
||||
x[1] = 0;
|
||||
x[2] = wpts;
|
||||
x[3] = wqts;
|
||||
x[4] = wseq;
|
||||
x[5] = wdate;
|
||||
assert (write (state_file_fd, x, 24) == 24);
|
||||
close (state_file_fd);
|
||||
}
|
||||
|
||||
void write_dc (struct tgl_dc *DC, void *extra) {
|
||||
int auth_file_fd = *(int *)extra;
|
||||
if (!DC) {
|
||||
int x = 0;
|
||||
assert (write (auth_file_fd, &x, 4) == 4);
|
||||
return;
|
||||
} else {
|
||||
int x = 1;
|
||||
assert (write (auth_file_fd, &x, 4) == 4);
|
||||
}
|
||||
|
||||
assert (DC->has_auth);
|
||||
|
||||
assert (write (auth_file_fd, &DC->port, 4) == 4);
|
||||
int l = strlen (DC->ip);
|
||||
assert (write (auth_file_fd, &l, 4) == 4);
|
||||
assert (write (auth_file_fd, DC->ip, l) == l);
|
||||
assert (write (auth_file_fd, &DC->auth_key_id, 8) == 8);
|
||||
assert (write (auth_file_fd, DC->auth_key, 256) == 256);
|
||||
}
|
||||
|
||||
void write_auth_file (struct tgl_state *TLS) {
|
||||
char *name = 0;
|
||||
if (asprintf (&name, "%s/%s", TLS->base_path, "auth") < 0) {
|
||||
return;
|
||||
}
|
||||
int auth_file_fd = open (name, O_CREAT | O_RDWR, 0600);
|
||||
free (name);
|
||||
if (auth_file_fd < 0) { return; }
|
||||
int x = DC_SERIALIZED_MAGIC;
|
||||
assert (write (auth_file_fd, &x, 4) == 4);
|
||||
assert (write (auth_file_fd, &TLS->max_dc_num, 4) == 4);
|
||||
assert (write (auth_file_fd, &TLS->dc_working_num, 4) == 4);
|
||||
|
||||
tgl_dc_iterator_ex (TLS, write_dc, &auth_file_fd);
|
||||
|
||||
assert (write (auth_file_fd, &TLS->our_id, 4) == 4);
|
||||
close (auth_file_fd);
|
||||
}
|
||||
|
||||
void read_dc (struct tgl_state *TLS, int auth_file_fd, int id, unsigned ver) {
|
||||
int port = 0;
|
||||
assert (read (auth_file_fd, &port, 4) == 4);
|
||||
int l = 0;
|
||||
assert (read (auth_file_fd, &l, 4) == 4);
|
||||
assert (l >= 0 && l < 100);
|
||||
char ip[100];
|
||||
assert (read (auth_file_fd, ip, l) == l);
|
||||
ip[l] = 0;
|
||||
|
||||
long long auth_key_id;
|
||||
static unsigned char auth_key[256];
|
||||
assert (read (auth_file_fd, &auth_key_id, 8) == 8);
|
||||
assert (read (auth_file_fd, auth_key, 256) == 256);
|
||||
|
||||
//bl_do_add_dc (id, ip, l, port, auth_key_id, auth_key);
|
||||
bl_do_dc_option (TLS, id, 2, "DC", l, ip, port);
|
||||
bl_do_set_auth_key_id (TLS, id, auth_key);
|
||||
bl_do_dc_signed (TLS, id);
|
||||
}
|
||||
|
||||
void empty_auth_file (struct tgl_state *TLS) {
|
||||
if (TLS->test_mode) {
|
||||
bl_do_dc_option (TLS, 1, 0, "", strlen (TG_SERVER_TEST_1), TG_SERVER_TEST_1, 443);
|
||||
bl_do_dc_option (TLS, 2, 0, "", strlen (TG_SERVER_TEST_2), TG_SERVER_TEST_2, 443);
|
||||
bl_do_dc_option (TLS, 3, 0, "", strlen (TG_SERVER_TEST_3), TG_SERVER_TEST_3, 443);
|
||||
bl_do_set_working_dc (TLS, TG_SERVER_TEST_DEFAULT);
|
||||
} else {
|
||||
bl_do_dc_option (TLS, 1, 0, "", strlen (TG_SERVER_1), TG_SERVER_1, 443);
|
||||
bl_do_dc_option (TLS, 2, 0, "", strlen (TG_SERVER_2), TG_SERVER_2, 443);
|
||||
bl_do_dc_option (TLS, 3, 0, "", strlen (TG_SERVER_3), TG_SERVER_3, 443);
|
||||
bl_do_dc_option (TLS, 4, 0, "", strlen (TG_SERVER_4), TG_SERVER_4, 443);
|
||||
bl_do_dc_option (TLS, 5, 0, "", strlen (TG_SERVER_5), TG_SERVER_5, 443);
|
||||
bl_do_set_working_dc (TLS, TG_SERVER_DEFAULT);;
|
||||
}
|
||||
}
|
||||
|
||||
void read_auth_file (struct tgl_state *TLS) {
|
||||
char *name = 0;
|
||||
if (asprintf (&name, "%s/%s", TLS->base_path, "auth") < 0) {
|
||||
return;
|
||||
}
|
||||
int auth_file_fd = open (name, O_CREAT | O_RDWR, 0600);
|
||||
free (name);
|
||||
if (auth_file_fd < 0) {
|
||||
empty_auth_file (TLS);
|
||||
return;
|
||||
}
|
||||
assert (auth_file_fd >= 0);
|
||||
unsigned x;
|
||||
unsigned m;
|
||||
if (read (auth_file_fd, &m, 4) < 4 || (m != DC_SERIALIZED_MAGIC)) {
|
||||
close (auth_file_fd);
|
||||
empty_auth_file (TLS);
|
||||
return;
|
||||
}
|
||||
assert (read (auth_file_fd, &x, 4) == 4);
|
||||
assert (x > 0);
|
||||
int dc_working_num;
|
||||
assert (read (auth_file_fd, &dc_working_num, 4) == 4);
|
||||
|
||||
int i;
|
||||
for (i = 0; i <= (int)x; i++) {
|
||||
int y;
|
||||
assert (read (auth_file_fd, &y, 4) == 4);
|
||||
if (y) {
|
||||
read_dc (TLS, auth_file_fd, i, m);
|
||||
}
|
||||
}
|
||||
bl_do_set_working_dc (TLS, dc_working_num);
|
||||
int our_id;
|
||||
int l = read (auth_file_fd, &our_id, 4);
|
||||
if (l < 4) {
|
||||
assert (!l);
|
||||
}
|
||||
if (our_id) {
|
||||
bl_do_set_our_id (TLS, our_id);
|
||||
}
|
||||
close (auth_file_fd);
|
||||
}
|
||||
|
||||
void telegram_export_authorization (struct tgl_state *TLS);
|
||||
void export_auth_callback (struct tgl_state *TLS, void *extra, int success) {
|
||||
assert (success);
|
||||
telegram_export_authorization (TLS);
|
||||
}
|
||||
|
||||
void telegram_export_authorization (struct tgl_state *TLS) {
|
||||
int i;
|
||||
for (i = 0; i <= TLS->max_dc_num; i++) if (TLS->DC_list[i] && !tgl_signed_dc (TLS, TLS->DC_list[i])) {
|
||||
tgl_do_export_auth (TLS, i, export_auth_callback, (void*)(long)TLS->DC_list[i]);
|
||||
return;
|
||||
}
|
||||
write_auth_file (TLS);
|
||||
telegram_on_ready (TLS);
|
||||
}
|
||||
|
||||
static void request_code (struct tgl_state *TLS);
|
||||
static void request_name_and_code (struct tgl_state *TLS);
|
||||
static void code_receive_result (struct tgl_state *TLS, void *extra, int success, struct tgl_user *U) {
|
||||
if (!success) {
|
||||
debug ("Bad code...\n");
|
||||
request_code (TLS);
|
||||
} else {
|
||||
telegram_export_authorization (TLS);
|
||||
}
|
||||
}
|
||||
|
||||
static void code_auth_receive_result (struct tgl_state *TLS, void *extra, int success, struct tgl_user *U) {
|
||||
if (!success) {
|
||||
debug ("Bad code...\n");
|
||||
request_name_and_code (TLS);
|
||||
} else {
|
||||
telegram_export_authorization (TLS);
|
||||
}
|
||||
}
|
||||
|
||||
static void request_code_entered (gpointer data, const gchar *code) {
|
||||
struct tgl_state *TLS = data;
|
||||
telegram_conn *conn = TLS->ev_base;
|
||||
char const *username = purple_account_get_username(conn->pa);
|
||||
tgl_do_send_code_result (TLS, username, conn->hash, code, code_receive_result, 0) ;
|
||||
}
|
||||
|
||||
static void request_code_canceled (gpointer data) {
|
||||
struct tgl_state *TLS = data;
|
||||
telegram_conn *conn = TLS->ev_base;
|
||||
|
||||
purple_connection_error_reason(conn->gc,
|
||||
PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, "registration canceled");
|
||||
}
|
||||
|
||||
static void request_name_code_entered (PurpleConnection* gc, PurpleRequestFields* fields) {
|
||||
telegram_conn *conn = purple_connection_get_protocol_data(gc);
|
||||
struct tgl_state *TLS = conn->TLS;
|
||||
char const *username = purple_account_get_username(conn->pa);
|
||||
|
||||
const char* first = purple_request_fields_get_string(fields, "first_name");
|
||||
const char* last = purple_request_fields_get_string(fields, "last_name");
|
||||
const char* code = purple_request_fields_get_string(fields, "code");
|
||||
if (!first || !last || !code) {
|
||||
request_name_and_code (TLS);
|
||||
return;
|
||||
}
|
||||
|
||||
tgl_do_send_code_result_auth (TLS, username, conn->hash, code, first, last, code_auth_receive_result, NULL);
|
||||
}
|
||||
|
||||
static void request_code (struct tgl_state *TLS) {
|
||||
debug ("Client is not registered, registering...\n");
|
||||
telegram_conn *conn = TLS->ev_base;
|
||||
|
||||
purple_request_input (
|
||||
conn->gc, // handle (the PurpleAccount)
|
||||
"Telegram Code", // title
|
||||
"Enter Telegram Code", // primary
|
||||
"Telegram wants to verify your identity, please enter the code, that you have received via SMS.", // secondary
|
||||
NULL, // default_value
|
||||
0, // multiline
|
||||
0, // masked
|
||||
"code", // hint
|
||||
"OK", // ok_text
|
||||
G_CALLBACK(request_code_entered), // ok_cb
|
||||
"Cancel", // cancel_text
|
||||
G_CALLBACK(request_code_canceled), // cancel_cb
|
||||
conn->pa, // account
|
||||
NULL, // who
|
||||
NULL, // conv
|
||||
TLS // user_data
|
||||
);
|
||||
}
|
||||
|
||||
static void request_name_and_code (struct tgl_state *TLS) {
|
||||
telegram_conn *conn = TLS->ev_base;
|
||||
|
||||
debug ("Phone is not registered, registering...\n");
|
||||
|
||||
PurpleRequestFields* fields = purple_request_fields_new();
|
||||
PurpleRequestField* field = 0;
|
||||
|
||||
PurpleRequestFieldGroup* group = purple_request_field_group_new("Registration");
|
||||
field = purple_request_field_string_new("first_name", "First Name", "", 0);
|
||||
purple_request_field_group_add_field(group, field);
|
||||
field = purple_request_field_string_new("last_name", "Last Name", "", 0);
|
||||
purple_request_field_group_add_field(group, field);
|
||||
purple_request_fields_add_group(fields, group);
|
||||
|
||||
group = purple_request_field_group_new("Authorization");
|
||||
field = purple_request_field_string_new("code", "Telegram Code", "", 0);
|
||||
purple_request_field_group_add_field(group, field);
|
||||
purple_request_fields_add_group(fields, group);
|
||||
|
||||
purple_request_fields(conn->gc, "Register", "Please register your phone number.", NULL, fields, "Ok",
|
||||
G_CALLBACK( request_name_code_entered ), "Cancel", NULL, conn->pa, NULL, NULL, conn->gc);
|
||||
}
|
||||
|
||||
static void sign_in_callback (struct tgl_state *TLS, void *extra, int success, int registered, const char *mhash) {
|
||||
assert (success); // TODO proper error handle
|
||||
telegram_conn *conn = TLS->ev_base;
|
||||
conn->hash = strdup (mhash);
|
||||
|
||||
if (registered) {
|
||||
request_code (TLS);
|
||||
} else {
|
||||
request_name_and_code (TLS);
|
||||
}
|
||||
}
|
||||
|
||||
static void telegram_send_sms (struct tgl_state *TLS) {
|
||||
if (tgl_signed_dc (TLS, TLS->DC_working)) {
|
||||
telegram_export_authorization (TLS);
|
||||
return;
|
||||
}
|
||||
telegram_conn *conn = TLS->ev_base;
|
||||
char const *username = purple_account_get_username(conn->pa);
|
||||
tgl_do_send_code (TLS, username, sign_in_callback, 0);
|
||||
}
|
||||
|
||||
static int all_authorized (struct tgl_state *TLS) {
|
||||
int i;
|
||||
for (i = 0; i <= TLS->max_dc_num; i++) if (TLS->DC_list[i]) {
|
||||
if (!tgl_authorized_dc (TLS, TLS->DC_list[i])) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int check_all_authorized (gpointer arg) {
|
||||
struct tgl_state *TLS = arg;
|
||||
if (all_authorized (TLS)) {
|
||||
telegram_send_sms (TLS);
|
||||
return FALSE;
|
||||
} else {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
void telegram_login (struct tgl_state *TLS) {
|
||||
read_auth_file (TLS);
|
||||
read_state_file (TLS);
|
||||
if (all_authorized (TLS)) {
|
||||
telegram_send_sms (TLS);
|
||||
return;
|
||||
}
|
||||
purple_timeout_add (100, check_all_authorized, TLS);
|
||||
}
|
||||
|
9
telegram-base.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#ifndef __TELEGRAM_BASE_H__
|
||||
#define __TELEGRAM_BASE_H__
|
||||
void read_state_file (struct tgl_state *TLS);
|
||||
void read_auth_file (struct tgl_state *TLS);
|
||||
void write_auth_file (struct tgl_state *TLS);
|
||||
void write_state_file (struct tgl_state *TLS);
|
||||
|
||||
void telegram_login (struct tgl_state *TLS);
|
||||
#endif
|
|
@ -26,62 +26,45 @@
|
|||
#define TG_BUILD "8"
|
||||
|
||||
#include <glib.h>
|
||||
#include "notify.h"
|
||||
#include "plugin.h"
|
||||
#include "version.h"
|
||||
#include "account.h"
|
||||
#include "connection.h"
|
||||
#include "mtproto-client.h"
|
||||
#include <notify.h>
|
||||
#include <plugin.h>
|
||||
#include <version.h>
|
||||
#include <account.h>
|
||||
#include <connection.h>
|
||||
|
||||
typedef struct {
|
||||
struct telegram *tg;
|
||||
PurpleAccount *pa;
|
||||
struct tgl_state *TLS;
|
||||
|
||||
/*
|
||||
* Used during login
|
||||
*/
|
||||
char *hash;
|
||||
|
||||
PurpleAccount *pa;
|
||||
PurpleConnection *gc;
|
||||
|
||||
/**
|
||||
* Whether the state of the protocol has changed since the last save
|
||||
*/
|
||||
int updated;
|
||||
/**
|
||||
* Whether the state of the protocol has changed since the last save
|
||||
*/
|
||||
int updated;
|
||||
|
||||
/**
|
||||
* The used purple timeout handler
|
||||
*/
|
||||
guint timer;
|
||||
|
||||
/**
|
||||
* Queue of all new messages that need to be added to a chat
|
||||
*/
|
||||
GQueue *new_messages;
|
||||
/**
|
||||
* Queue of all new messages that need to be added to a chat
|
||||
*/
|
||||
GQueue *new_messages;
|
||||
|
||||
/**
|
||||
* Queue of all joined chats
|
||||
*/
|
||||
GHashTable *joining_chats;
|
||||
/**
|
||||
* Queue of all joined chats
|
||||
*/
|
||||
GHashTable *joining_chats;
|
||||
|
||||
guint timer;
|
||||
} telegram_conn;
|
||||
|
||||
typedef struct {
|
||||
|
||||
/**
|
||||
* The mtproto_connection associated with this handle
|
||||
*/
|
||||
struct mtproto_connection *mtp;
|
||||
|
||||
/**
|
||||
* Write handler returned by purple_input_add
|
||||
*/
|
||||
guint wh;
|
||||
|
||||
/**
|
||||
* Read handler returned by purple_input_add
|
||||
*/
|
||||
guint rh;
|
||||
|
||||
/**
|
||||
* The file descriptor of the used socket
|
||||
*/
|
||||
int fd;
|
||||
|
||||
} mtproto_handle;
|
||||
struct download_desc {
|
||||
int type;
|
||||
void *data;
|
||||
};
|
||||
|
||||
void telegram_on_ready (struct tgl_state *TLS);
|
||||
#endif
|
480
telegram.c
|
@ -1,480 +0,0 @@
|
|||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "telegram.h"
|
||||
#include "msglog.h"
|
||||
#include "glib.h"
|
||||
#include "tools.h"
|
||||
#include "mtproto-client.h"
|
||||
#include "binlog.h"
|
||||
#include "loop.h"
|
||||
|
||||
|
||||
/*
|
||||
* Events
|
||||
*/
|
||||
void event_user_info_received_handler(struct telegram *instance, struct tgl_user *peer, int show_info)
|
||||
{
|
||||
if (instance->config->on_user_info_received_handler) {
|
||||
instance->config->on_user_info_received_handler (instance, peer, show_info);
|
||||
}
|
||||
}
|
||||
|
||||
DEFINE_EVENT_HANDLER (peer_allocated, void);
|
||||
DEFINE_EVENT_HANDLER (update_user_status, void);
|
||||
DEFINE_EVENT_HANDLER (update_user_typing, void);
|
||||
|
||||
DEFINE_EVENT_HANDLER (update_user_name, peer_t);
|
||||
DEFINE_EVENT_HANDLER (update_user_photo, peer_t);
|
||||
DEFINE_EVENT_HANDLER (update_user_registered, peer_t);
|
||||
|
||||
DEFINE_EVENT_HANDLER (update_chat_participants, peer_t);
|
||||
DEFINE_EVENT_HANDLER_3(update_chat_add_participant, peer_t *, peer_id_t, peer_id_t);
|
||||
DEFINE_EVENT_HANDLER_3(update_chat_del_participant, peer_t *, peer_id_t, void *);
|
||||
DEFINE_EVENT_HANDLER_3(update_chat_user_typing, peer_t *, peer_t *, void *);
|
||||
DEFINE_EVENT_HANDLER (update_auth_new, char);
|
||||
|
||||
DEFINE_EVENT_HANDLER (update_new_message, struct message);
|
||||
DEFINE_EVENT_HANDLER (download_finished, struct download);
|
||||
|
||||
|
||||
/**
|
||||
* Calculate the configuration path for the given config file and the given instance
|
||||
*
|
||||
* @returns The full path to the configuration.
|
||||
*
|
||||
* NOTE: the returned string must be freed manually using gfree
|
||||
*/
|
||||
char *telegram_get_config(struct telegram *instance, char *config)
|
||||
{
|
||||
return g_strdup_printf("%s/%s", instance->config_path, config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the current client is registered.
|
||||
*/
|
||||
int telegram_is_registered(struct telegram *tg)
|
||||
{
|
||||
return telegram_get_working_dc(tg)->has_auth;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle state changes of the telegram instance
|
||||
*
|
||||
* Execute all actions necessary when a certain state is reached. The state machine executes
|
||||
* the authorization and registration steps needed to connect the client to the telegram network,
|
||||
* and will either trigger RPC queries or callbacks to the GUI to request input from the user.
|
||||
*/
|
||||
void telegram_change_state (struct telegram *instance, int state, void *data)
|
||||
{
|
||||
instance->session_state = state;
|
||||
debug("on_state_change: %d\n", state);
|
||||
switch (state) {
|
||||
case STATE_ERROR: {
|
||||
const char* err = data;
|
||||
if (err == NULL) {
|
||||
err = "<no error description>";
|
||||
}
|
||||
debug("telegram errored: %s\n", err);
|
||||
mtproto_close (instance->connection);
|
||||
instance->config->on_error (instance, err);
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_AUTHORIZED:
|
||||
debug("requesting configuration\n");
|
||||
telegram_change_state(instance, STATE_CONFIG_REQUESTED, NULL);
|
||||
if (telegram_is_registered(instance)) {
|
||||
telegram_change_state (instance, STATE_READY, NULL);
|
||||
return;
|
||||
}
|
||||
do_help_get_config (instance);
|
||||
break;
|
||||
|
||||
case STATE_CONFIG_RECEIVED:
|
||||
debug("received network configuration, checking whether phone is registered.\n");
|
||||
telegram_store_session(instance);
|
||||
do_auth_check_phone(instance, instance->login);
|
||||
break;
|
||||
|
||||
case STATE_PHONE_NOT_REGISTERED:
|
||||
debug("phone is not registered, need to register phone number.\n");
|
||||
do_send_code(instance, instance->login);
|
||||
break;
|
||||
|
||||
case STATE_PHONE_CODE_NOT_ENTERED:
|
||||
debug("phone authenticion, user needs to enter code, first and last name.\n");
|
||||
assert (instance->config->on_phone_registration_required);
|
||||
instance->config->on_phone_registration_required (instance);
|
||||
break;
|
||||
|
||||
case STATE_CLIENT_NOT_REGISTERED:
|
||||
debug("phone is already registered, need to register client.\n");
|
||||
do_send_code(instance, instance->login);
|
||||
break;
|
||||
|
||||
case STATE_CLIENT_CODE_NOT_ENTERED:
|
||||
debug("client authentication, user needs to enter code.\n");
|
||||
assert (instance->config->on_client_registration_required);
|
||||
instance->config->on_client_registration_required (instance);
|
||||
// wait for user input ...
|
||||
break;
|
||||
|
||||
case STATE_READY:
|
||||
debug("telegram is registered and ready.\n");
|
||||
telegram_store_session (instance);
|
||||
instance->config->on_ready (instance);
|
||||
break;
|
||||
|
||||
case STATE_DISCONNECTED_SWITCH_DC: {
|
||||
// telegram demands that we use a different data center, which caused
|
||||
// the current mtproto_connection to be disconnected
|
||||
|
||||
int target_dc = *(int*) data;
|
||||
debug ("Disconnected: Migrate to data center %d\n", target_dc);
|
||||
|
||||
// close old connection and mark it for destruction
|
||||
mtproto_close (instance->connection);
|
||||
assert (instance->config->proxy_request_cb);
|
||||
|
||||
// remove all left over queries and timers
|
||||
free_timers (instance);
|
||||
free_queries (instance);
|
||||
|
||||
// start a new connection to the demanded data center. The pointer to the
|
||||
// new dc should was already updated by the on_error function of the query
|
||||
telegram_connect (instance);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct telegram *telegram_new(const char* login, struct telegram_config *config)
|
||||
{
|
||||
struct telegram *this = talloc0(sizeof(struct telegram));
|
||||
this->protocol_data = NULL;
|
||||
this->bl = talloc0 (sizeof(struct binlog));
|
||||
this->config = config;
|
||||
|
||||
this->login = g_strdup(login);
|
||||
this->config_path = g_strdup_printf("%s/%s", config->base_config_path, login);
|
||||
this->download_path = telegram_get_config(this, "downloads");
|
||||
this->auth_path = telegram_get_config(this, "auth");
|
||||
this->state_path = telegram_get_config(this, "state");
|
||||
this->secret_path = telegram_get_config(this, "secret");
|
||||
|
||||
debug("%s\n", this->login);
|
||||
debug("%s\n", this->config_path);
|
||||
debug("%s\n", this->download_path);
|
||||
debug("%s\n", this->auth_path);
|
||||
debug("%s\n", this->state_path);
|
||||
debug("%s\n", this->secret_path);
|
||||
|
||||
telegram_change_state(this, STATE_INITIALISED, NULL);
|
||||
return this;
|
||||
}
|
||||
|
||||
void free_bl (struct binlog *bl);
|
||||
void free_auth (struct dc* DC_list[], int count);
|
||||
void telegram_destroy(struct telegram *this)
|
||||
{
|
||||
// close all open connections
|
||||
int i = 0;
|
||||
for (; i < 100; i++) {
|
||||
if (this->Cs[i] != NULL && !this->Cs[i]->destroy) {
|
||||
mtproto_close (this->Cs[i]);
|
||||
}
|
||||
}
|
||||
free_queries (this);
|
||||
free_timers (this);
|
||||
mtproto_free_closed (this, 1);
|
||||
|
||||
free_bl (this->bl);
|
||||
free_auth (this->auth.DC_list, 11);
|
||||
|
||||
g_free(this->login);
|
||||
g_free(this->config_path);
|
||||
g_free(this->download_path);
|
||||
g_free(this->auth_path);
|
||||
g_free(this->state_path);
|
||||
g_free(this->secret_path);
|
||||
|
||||
// TODO: BN_CTX *ctx
|
||||
if (this->phone_code_hash) free (this->phone_code_hash);
|
||||
if (this->suser) free (this->suser);
|
||||
if (this->export_auth_str) free (this->export_auth_str);
|
||||
//tfree (this->ML, sizeof(struct message) * MSG_STORE_SIZE);
|
||||
tfree(this, sizeof(struct telegram));
|
||||
}
|
||||
|
||||
void free_bl (struct binlog *bl)
|
||||
{
|
||||
// TODO: rptr, wptr
|
||||
free_peers (bl);
|
||||
free_messages (bl);
|
||||
tfree (bl, sizeof (struct binlog));
|
||||
}
|
||||
|
||||
void free_auth (struct dc* DC_list[], int count)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < count; i++ ) if (DC_list[i]) {
|
||||
tfree (DC_list[i], sizeof(struct dc));
|
||||
}
|
||||
}
|
||||
|
||||
void assert_file_usable(const char *file)
|
||||
{
|
||||
debug ("assert_file_usable (%s)\n", file);
|
||||
assert(access(file, W_OK | R_OK | F_OK) != -1);
|
||||
}
|
||||
|
||||
void assure_file_exists(const char *dir, const char *file)
|
||||
{
|
||||
g_mkdir_with_parents(dir, 0700);
|
||||
char *f = g_strdup_printf("%s/%s", dir, file);
|
||||
close(open(f, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR));
|
||||
assert_file_usable(f);
|
||||
g_free(f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the currently used connection
|
||||
*
|
||||
* Will only work after telegram_connect has been called and the connection has
|
||||
* not errored.
|
||||
*/
|
||||
struct connection *telegram_get_connection(struct telegram *instance)
|
||||
{
|
||||
assert(instance->session_state != STATE_ERROR);
|
||||
|
||||
struct dc *DC = telegram_get_working_dc(instance);
|
||||
assert(DC);
|
||||
assert(DC->sessions[0]);
|
||||
assert(DC->sessions[0]->c);
|
||||
return DC->sessions[0]->c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the currently used DC
|
||||
*
|
||||
* Will only work after restore_session has been called and the data center configuration
|
||||
* was properly loaded
|
||||
*/
|
||||
struct dc *telegram_get_working_dc(struct telegram *instance)
|
||||
{
|
||||
assert(instance->session_state != STATE_ERROR);
|
||||
|
||||
assert(instance->auth.DC_list);
|
||||
assert(instance->auth.dc_working_num > 0);
|
||||
struct dc *DC = instance->auth.DC_list[instance->auth.dc_working_num];
|
||||
return DC;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the current session state to a file
|
||||
*/
|
||||
void telegram_restore_session(struct telegram *instance)
|
||||
{
|
||||
g_mkdir_with_parents(instance->config_path, 0700);
|
||||
g_mkdir_with_parents(instance->download_path, 0700);
|
||||
instance->auth = read_auth_file(instance->auth_path);
|
||||
instance->proto = read_state_file(instance->state_path);
|
||||
read_secret_chat_file (instance, instance->secret_path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the current session state
|
||||
*/
|
||||
void telegram_store_session(struct telegram *instance)
|
||||
{
|
||||
assure_file_exists(instance->config_path, "auth");
|
||||
assure_file_exists(instance->config_path, "state");
|
||||
assure_file_exists(instance->config_path, "secret");
|
||||
write_auth_file(&instance->auth, instance->auth_path);
|
||||
write_state_file(&instance->proto, instance->state_path);
|
||||
write_secret_chat_file(instance, instance->secret_path);
|
||||
}
|
||||
|
||||
void on_authorized(struct mtproto_connection *c, void* data);
|
||||
|
||||
void telegram_main_connected (struct proxy_request *req)
|
||||
{
|
||||
struct telegram *instance = req->data;
|
||||
debug("Authorized... storing current session %d.\n",
|
||||
instance->connection->connection->session[0]);
|
||||
telegram_store_session(instance);
|
||||
telegram_change_state(instance, STATE_AUTHORIZED, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to the nearest data center
|
||||
*/
|
||||
void telegram_connect (struct telegram *instance)
|
||||
{
|
||||
debug ("telegram_network_connect()\n");
|
||||
if (! instance->auth.DC_list) {
|
||||
debug("telegram_network_connect(): cannot connect, restore / init a session first.\n");
|
||||
assert(0);
|
||||
}
|
||||
struct dc *DC_working = telegram_get_working_dc (instance);
|
||||
|
||||
struct proxy_request *req = talloc0(sizeof(struct proxy_request));
|
||||
req->type = REQ_CONNECTION;
|
||||
req->tg = instance;
|
||||
req->data = instance;
|
||||
req->DC = DC_working;
|
||||
req->done = telegram_main_connected;
|
||||
|
||||
assert (instance->config->proxy_request_cb);
|
||||
instance->config->proxy_request_cb (instance, req);
|
||||
}
|
||||
|
||||
void on_auth_imported (void *extra)
|
||||
{
|
||||
debug ("on_auth_imported()\n");
|
||||
struct download *dl = extra;
|
||||
struct mtproto_connection *c = dl->c;
|
||||
struct telegram *tg = c->instance;
|
||||
bl_do_dc_signed (tg->bl, c, dl->dc);
|
||||
write_auth_file (&tg->auth, tg->auth_path);
|
||||
load_next_part (tg, dl);
|
||||
telegram_flush (tg);
|
||||
}
|
||||
|
||||
void on_auth_exported (char *export_auth_str UU, int len UU, void *extra)
|
||||
{
|
||||
debug ("on_auth_exported()\n");
|
||||
struct download *dl = extra;
|
||||
do_import_auth (dl->c->instance, dl->dc, on_auth_imported, extra);
|
||||
telegram_flush (dl->c->instance);
|
||||
}
|
||||
|
||||
void telegram_dl_connected (struct proxy_request *req)
|
||||
{
|
||||
debug ("telegram_dl_connected(dc=%d)\n", req->DC->id);
|
||||
struct telegram *tg = req->tg;
|
||||
// TODO: error handling
|
||||
|
||||
struct download *dl = req->data;
|
||||
dl->c = req->conn;
|
||||
struct dc *DC = tg->auth.DC_list[dl->dc];
|
||||
if (!DC->has_auth) {
|
||||
do_export_auth (tg, dl->dc, on_auth_exported, dl);
|
||||
telegram_flush (tg);
|
||||
} else {
|
||||
on_auth_imported (dl);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a connection for the given download
|
||||
*/
|
||||
void telegram_dl_add (struct telegram *instance, struct download *dl)
|
||||
{
|
||||
debug ("telegram_connect_dl(dc_num=%d, dc=%d)\n", dl->dc, instance->auth.DC_list[dl->dc]);
|
||||
if (!instance->dl_queue) {
|
||||
instance->dl_queue = g_queue_new ();
|
||||
}
|
||||
g_queue_push_tail(instance->dl_queue, dl);
|
||||
}
|
||||
|
||||
void telegram_dl_next (struct telegram *instance)
|
||||
{
|
||||
assert (instance->dl_queue);
|
||||
assert (instance->config->proxy_request_cb);
|
||||
if (!instance->dl_curr) {
|
||||
struct download *dl = g_queue_pop_head (instance->dl_queue);
|
||||
if (dl) {
|
||||
struct proxy_request *req = talloc0(sizeof(struct proxy_request));
|
||||
req->type = REQ_DOWNLOAD;
|
||||
req->DC = instance->auth.DC_list[dl->dc];
|
||||
req->tg = instance;
|
||||
req->done = telegram_dl_connected;
|
||||
req->data = dl;
|
||||
instance->dl_curr = dl;
|
||||
|
||||
debug ("telegrma_dl_start(workin_dc=%d, ): starting new download..\n", instance->auth.dc_working_num);
|
||||
if (dl->dc == instance->auth.dc_working_num) {
|
||||
debug ("is working DC, start download...\n");
|
||||
assert (telegram_get_working_dc(instance)->sessions[0]->c);
|
||||
req->conn = instance->connection;
|
||||
dl->c = req->conn;
|
||||
telegram_dl_connected (req);
|
||||
} else {
|
||||
debug ("is remote DC, requesting connection...\n");
|
||||
instance->config->proxy_request_cb (instance, req);
|
||||
}
|
||||
} else {
|
||||
debug ("telegrma_dl_start(): no more downloads, DONE!\n");
|
||||
mtproto_close_foreign (instance);
|
||||
}
|
||||
} else {
|
||||
debug ("telegrma_dl_start(): download busy...\n");
|
||||
}
|
||||
}
|
||||
|
||||
void on_authorized(struct mtproto_connection *c UU, void *data)
|
||||
{
|
||||
debug ("on_authorized()...\n");
|
||||
struct proxy_request *req = data;
|
||||
assert (req->done);
|
||||
req->done (req);
|
||||
tfree (req, sizeof(struct proxy_request));
|
||||
}
|
||||
|
||||
struct mtproto_connection *telegram_add_proxy(struct telegram *instance, struct proxy_request *req,
|
||||
int fd, void *handle)
|
||||
{
|
||||
struct mtproto_connection *c = mtproto_new (req->DC, fd, instance);
|
||||
c->handle = handle;
|
||||
c->on_ready = on_authorized;
|
||||
c->on_ready_data = req;
|
||||
req->conn = c;
|
||||
if (req->type == REQ_CONNECTION) {
|
||||
req->tg->connection = c;
|
||||
}
|
||||
mtproto_connect (c);
|
||||
return c;
|
||||
}
|
||||
|
||||
void mtp_read_input (struct mtproto_connection *mtp)
|
||||
{
|
||||
try_read (mtp->connection);
|
||||
}
|
||||
|
||||
int mtp_write_output (struct mtproto_connection *mtp)
|
||||
{
|
||||
return try_write(mtp->connection);
|
||||
}
|
||||
|
||||
int telegram_authenticated (struct telegram *instance)
|
||||
{
|
||||
return telegram_get_working_dc (instance)->auth_key_id > 0;
|
||||
}
|
||||
|
||||
void telegram_flush (struct telegram *instance)
|
||||
{
|
||||
debug ("telegram flush()\n");
|
||||
int i;
|
||||
for (i = 0; i < 100; i++) {
|
||||
struct mtproto_connection *c = instance->Cs[i];
|
||||
if (!c) continue;
|
||||
if (!c->connection) continue;
|
||||
if (c->connection->out_bytes) {
|
||||
debug ("connection %d has %d bytes, triggering on_output.\n",
|
||||
i, c->connection->out_bytes);
|
||||
instance->config->on_output(c->handle);
|
||||
} else {
|
||||
debug ("connection %d has no bytes, skipping\n", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
484
telegram.h
|
@ -1,484 +0,0 @@
|
|||
#ifndef __TELEGRAM_H__
|
||||
#define __TELEGRAM_H__
|
||||
|
||||
#define MAX_PACKED_SIZE (1 << 24)
|
||||
#define MAX_DC_NUM 9
|
||||
#define MAX_PEER_NUM 100000
|
||||
|
||||
#ifndef PROG_NAME
|
||||
#define PROG_NAME "telegram-purple"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include "glib.h"
|
||||
#include "loop.h"
|
||||
#include "tree.h"
|
||||
#include "queries.h"
|
||||
#include <openssl/bn.h>
|
||||
|
||||
// forward declarations
|
||||
struct message;
|
||||
struct protocol_state;
|
||||
struct authorization_state;
|
||||
struct tree_query;
|
||||
struct tree_timer;
|
||||
|
||||
|
||||
/*
|
||||
* telegram states
|
||||
*/
|
||||
|
||||
#define STATE_INITIALISED 0
|
||||
#define STATE_DISCONNECTED 1
|
||||
#define STATE_ERROR 2
|
||||
#define STATE_AUTHORIZED 6
|
||||
|
||||
|
||||
// dc discovery
|
||||
#define STATE_CONFIG_REQUESTED 7
|
||||
#define STATE_EXPORTING_CONFIG 8
|
||||
#define STATE_DISCONNECTED_SWITCH_DC 9
|
||||
#define STATE_CONFIG_RECEIVED 11
|
||||
|
||||
// login
|
||||
|
||||
// - Phone Registration
|
||||
#define STATE_PHONE_NOT_REGISTERED 13
|
||||
#define STATE_PHONE_CODE_REQUESTED 14
|
||||
#define STATE_PHONE_CODE_NOT_ENTERED 15
|
||||
#define STATE_PHONE_CODE_ENTERED 16
|
||||
|
||||
// - Client Registration
|
||||
#define STATE_CLIENT_IS_REGISTERED_SENT 17
|
||||
#define STATE_CLIENT_NOT_REGISTERED 18
|
||||
#define STATE_CLIENT_CODE_REQUESTED 19
|
||||
#define STATE_CLIENT_CODE_NOT_ENTERED 20
|
||||
#define STATE_CLIENT_CODE_ENTERED 21
|
||||
|
||||
// Ready for sending and receiving messages
|
||||
#define STATE_READY 22
|
||||
|
||||
struct tree_peer;
|
||||
struct tree_peer_by_name;
|
||||
struct tree_message;
|
||||
|
||||
#define BINLOG_BUFFER_SIZE (1 << 20)
|
||||
|
||||
/**
|
||||
* Binary log
|
||||
*/
|
||||
struct binlog {
|
||||
int binlog_buffer[BINLOG_BUFFER_SIZE];
|
||||
int *rptr;
|
||||
int *wptr;
|
||||
int test_dc; // = 0
|
||||
int in_replay_log;
|
||||
int binlog_enabled; // = 0;
|
||||
int binlog_fd;
|
||||
long long binlog_pos;
|
||||
|
||||
int s[1000];
|
||||
|
||||
//
|
||||
struct tree_peer *peer_tree;
|
||||
struct tree_peer_by_name *peer_by_name_tree;
|
||||
struct tree_message *message_tree;
|
||||
struct tree_message *message_unsent_tree;
|
||||
|
||||
int users_allocated;
|
||||
int chats_allocated;
|
||||
int messages_allocated;
|
||||
int peer_num;
|
||||
int encr_chats_allocated;
|
||||
int geo_chats_allocated;
|
||||
|
||||
peer_t *Peers[MAX_PEER_NUM];
|
||||
};
|
||||
|
||||
#define REQ_CONNECTION 1
|
||||
#define REQ_DOWNLOAD 2
|
||||
struct proxy_request {
|
||||
struct telegram *tg;
|
||||
struct dc *DC;
|
||||
struct mtproto_connection *conn;
|
||||
int type;
|
||||
void *data;
|
||||
void (*done) (struct proxy_request *req);
|
||||
void *extra;
|
||||
};
|
||||
|
||||
struct telegram;
|
||||
struct download;
|
||||
|
||||
/*
|
||||
* Events 1 arg
|
||||
*/
|
||||
|
||||
#define DEFINE_EVENT_LISTENER(E_NAME, D_TYPE) void (*on_ ## E_NAME) (struct telegram *tg, D_TYPE *data);
|
||||
|
||||
#define DECLARE_EVENT_HANDLER(E_NAME, D_TYPE) \
|
||||
void event_ ## E_NAME (struct telegram *tg, D_TYPE *data)
|
||||
|
||||
#define DEFINE_EVENT_HANDLER(E_NAME, D_TYPE) \
|
||||
void event_ ## E_NAME (struct telegram *tg, D_TYPE *data) \
|
||||
{ \
|
||||
if (tg->config->on_ ## E_NAME) { \
|
||||
tg->config->on_ ## E_NAME (tg, data); \
|
||||
} else { \
|
||||
warning ("Trying to execute non-existing event listener %s\n", "E_NAME"); \
|
||||
} \
|
||||
}
|
||||
|
||||
/*
|
||||
* Events 3 args
|
||||
*/
|
||||
|
||||
#define DEFINE_EVENT_LISTENER_3(E_NAME, D_TYPE, D_TYPE2, D_TYPE3) void (*on_ ## E_NAME) (struct telegram *tg, D_TYPE data, D_TYPE2 data2, D_TYPE3 data3);
|
||||
|
||||
#define DECLARE_EVENT_HANDLER_3(E_NAME, D_TYPE, D_TYPE2, D_TYPE3) \
|
||||
void event_ ## E_NAME (struct telegram *tg, D_TYPE data, D_TYPE2 data2, D_TYPE3 data3)
|
||||
|
||||
#define DEFINE_EVENT_HANDLER_3(E_NAME, D_TYPE, D_TYPE2, D_TYPE3) \
|
||||
void event_ ## E_NAME (struct telegram *tg, D_TYPE data, D_TYPE2 data2, D_TYPE3 data3) \
|
||||
{ \
|
||||
if (tg->config->on_ ## E_NAME) { \
|
||||
tg->config->on_ ## E_NAME (tg, data, data2, data3); \
|
||||
} else { \
|
||||
warning ("Trying to execute non-existing event listener %s\n", "E_NAME"); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Contains all options and pointer to callback functions required by telegram
|
||||
*/
|
||||
struct telegram_config {
|
||||
|
||||
/**
|
||||
* The base path containing the telegram configuration
|
||||
*/
|
||||
char* base_config_path;
|
||||
|
||||
/**
|
||||
* Called when there is pending network output
|
||||
*/
|
||||
void (*on_output)(void *handle);
|
||||
|
||||
/**
|
||||
* A callback function that delivers a connections to the given hostname
|
||||
* and port by calling telegram_set_proxy. This is useful for tunelling
|
||||
* the connection through a proxy server.
|
||||
*/
|
||||
void (*proxy_request_cb) (struct telegram *instance, struct proxy_request *req);
|
||||
|
||||
/**
|
||||
* A callback function that is called once the proxy connection is no longer
|
||||
* needed. This is useful for freeing all used resources.
|
||||
*/
|
||||
void (*proxy_close_cb) (void *handle);
|
||||
|
||||
/**
|
||||
* A callback function that is called when a phone registration is required.
|
||||
*
|
||||
* This callback must query first name, last name and the
|
||||
* authentication code from the user and call do_send_code_result_auth once done
|
||||
*/
|
||||
void (*on_phone_registration_required) (struct telegram *instance);
|
||||
|
||||
/**
|
||||
* A callback function that is called when a client registration is required.
|
||||
*
|
||||
* This callback must query the authentication code from the user and
|
||||
* call do_send_code_result once done
|
||||
*/
|
||||
void (*on_client_registration_required) (struct telegram *instance);
|
||||
|
||||
/**
|
||||
* A callback function that is called when telegram is ready
|
||||
*/
|
||||
void (*on_ready) (struct telegram *instance);
|
||||
|
||||
/**
|
||||
* A callback function that is called when telegram is disconnected
|
||||
*/
|
||||
void (*on_error) (struct telegram *instance, const char *err);
|
||||
|
||||
/**
|
||||
* A callback function that is called when a new peer was allocated. This is useful
|
||||
* for populating the GUI with new peers.
|
||||
*/
|
||||
DEFINE_EVENT_LISTENER(peer_allocated, void);
|
||||
|
||||
/**
|
||||
* A callback function that is called when a user's status has changed
|
||||
*/
|
||||
DEFINE_EVENT_LISTENER(update_user_status, void);
|
||||
|
||||
/**
|
||||
* A callback function that is called when a user starts or stops typing
|
||||
*/
|
||||
DEFINE_EVENT_LISTENER(update_user_typing, void);
|
||||
DEFINE_EVENT_LISTENER(update_user_name, peer_t);
|
||||
DEFINE_EVENT_LISTENER(update_user_photo, peer_t);
|
||||
DEFINE_EVENT_LISTENER(update_user_registered, peer_t);
|
||||
|
||||
DEFINE_EVENT_LISTENER(update_chat_participants, peer_t);
|
||||
|
||||
/**
|
||||
* A new user is added to a chat
|
||||
*
|
||||
* @param data1 The chat
|
||||
* @param data2 The added user
|
||||
* @param data3 The inviter
|
||||
*/
|
||||
DEFINE_EVENT_LISTENER_3(update_chat_add_participant, peer_t *, peer_id_t, peer_id_t);
|
||||
|
||||
/**
|
||||
* A user is deleted from a chat
|
||||
*
|
||||
* @param data1 The chat
|
||||
* @param data2 The added user
|
||||
* @param data3 NULL
|
||||
*/
|
||||
DEFINE_EVENT_LISTENER_3(update_chat_del_participant, peer_t *, peer_id_t, void *);
|
||||
|
||||
/**
|
||||
* A user in a chat is typing
|
||||
*
|
||||
* @param data1 The chat
|
||||
* @param data2 The user
|
||||
* @param data3 NULL
|
||||
*/
|
||||
DEFINE_EVENT_LISTENER_3(update_chat_user_typing, peer_t *, peer_t *, void *);
|
||||
|
||||
/**
|
||||
* A new device was registered for @location
|
||||
*
|
||||
* @param tg
|
||||
* @param location
|
||||
*/
|
||||
DEFINE_EVENT_LISTENER(update_auth_new, char);
|
||||
|
||||
/**
|
||||
* A callback function that is called when a new message was allocated. This is useful
|
||||
* for adding new messages to the GUI.
|
||||
*/
|
||||
DEFINE_EVENT_LISTENER(update_new_message, struct message);
|
||||
|
||||
/**
|
||||
* A callback function that is called when a download is completed. This is useful
|
||||
* for populating the GUI with new user photos.
|
||||
*/
|
||||
DEFINE_EVENT_LISTENER(download_finished, struct download);
|
||||
|
||||
/**
|
||||
* A callback function that is called when a peer user info was received. This is useful
|
||||
* for populating the GUI with new user photos.
|
||||
*/
|
||||
void (*on_user_info_received_handler) (struct telegram *instance, struct tgl_user *peer, int showInfo);
|
||||
|
||||
/**
|
||||
* A callback function that is called when chat info is received
|
||||
*/
|
||||
void (*on_chat_info_received) (struct telegram *instance, peer_id_t chatid);
|
||||
};
|
||||
|
||||
DECLARE_EVENT_HANDLER (peer_allocated, void);
|
||||
DECLARE_EVENT_HANDLER (update_user_status, void);
|
||||
DECLARE_EVENT_HANDLER (update_user_typing, void);
|
||||
|
||||
DECLARE_EVENT_HANDLER (update_user_name, peer_t);
|
||||
DECLARE_EVENT_HANDLER (update_user_photo, peer_t);
|
||||
DECLARE_EVENT_HANDLER (update_user_registered, peer_t);
|
||||
|
||||
DECLARE_EVENT_HANDLER (update_chat_participants, peer_t);
|
||||
DECLARE_EVENT_HANDLER_3 (update_chat_add_participant, peer_t *, peer_id_t, peer_id_t);
|
||||
DECLARE_EVENT_HANDLER_3 (update_chat_del_participant, peer_t *, peer_id_t, void *);
|
||||
DECLARE_EVENT_HANDLER_3 (update_chat_user_typing, peer_t *, peer_t *, void *);
|
||||
DECLARE_EVENT_HANDLER (update_auth_new, char);
|
||||
|
||||
DECLARE_EVENT_HANDLER (update_new_message, struct message);
|
||||
DECLARE_EVENT_HANDLER (download_finished, struct download);
|
||||
|
||||
#define MSG_STORE_SIZE 10000
|
||||
|
||||
/**
|
||||
* A telegram session
|
||||
*
|
||||
* Contains all globals from the telegram-cli application is passed to every
|
||||
* query call
|
||||
*/
|
||||
struct telegram {
|
||||
void *protocol_data;
|
||||
//int curr_dc;
|
||||
|
||||
char *login;
|
||||
char *config_path;
|
||||
char *download_path;
|
||||
char *auth_path;
|
||||
char *state_path;
|
||||
char *secret_path;
|
||||
|
||||
int session_state;
|
||||
struct telegram_config *config;
|
||||
|
||||
/*
|
||||
* protocol state
|
||||
*/
|
||||
struct protocol_state proto;
|
||||
struct authorization_state auth;
|
||||
|
||||
/*
|
||||
* connection
|
||||
*/
|
||||
struct mtproto_connection *connection;
|
||||
|
||||
/*
|
||||
* binlog
|
||||
*/
|
||||
struct binlog *bl;
|
||||
|
||||
// TODO: Bind this to the current data center, since the code hash is only
|
||||
// valid in its context
|
||||
char *phone_code_hash;
|
||||
|
||||
int unread_messages;
|
||||
long long cur_uploading_bytes;
|
||||
long long cur_uploaded_bytes;
|
||||
long long cur_downloading_bytes;
|
||||
long long cur_downloaded_bytes;
|
||||
int our_id;
|
||||
struct tgl_user User;
|
||||
BN_CTX *ctx;
|
||||
int encr_root;
|
||||
unsigned char *encr_prime;
|
||||
int encr_param_version;
|
||||
int max_chat_size;
|
||||
int max_bcast_size;
|
||||
int want_dc_num;
|
||||
int new_dc_num;
|
||||
int out_message_num;
|
||||
char *suser;
|
||||
int nearest_dc_num;
|
||||
int packed_buffer[MAX_PACKED_SIZE / 4];
|
||||
struct tree_query *queries_tree;
|
||||
struct tree_timer *timer_tree;
|
||||
char *export_auth_str;
|
||||
int export_auth_str_len;
|
||||
char g_a[256];
|
||||
// do_get_difference
|
||||
int get_difference_active;
|
||||
struct message *ML[MSG_STORE_SIZE];
|
||||
|
||||
/*
|
||||
* All active MtProto connections
|
||||
*/
|
||||
int cs;
|
||||
struct mtproto_connection *Cs[100];
|
||||
|
||||
/*
|
||||
* Downloads
|
||||
*/
|
||||
GQueue *dl_queue;
|
||||
struct download *dl_curr;
|
||||
|
||||
/*
|
||||
* additional user data
|
||||
*/
|
||||
void *extra;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new telegram application
|
||||
*
|
||||
* @param login The phone number to use as login name
|
||||
* @param config Contains all callbacks used for the telegram instance
|
||||
*/
|
||||
struct telegram *telegram_new(const char* login, struct telegram_config *config);
|
||||
|
||||
void telegram_restore_session(struct telegram *instance);
|
||||
void telegram_store_session(struct telegram *instance);
|
||||
void telegram_destroy(struct telegram *instance);
|
||||
|
||||
/**
|
||||
* Get the currently active connection
|
||||
*/
|
||||
struct connection *telegram_get_connection(struct telegram *instance);
|
||||
|
||||
/**
|
||||
* Return the current working dc
|
||||
*/
|
||||
struct dc *telegram_get_working_dc(struct telegram *instance);
|
||||
|
||||
/*
|
||||
* Events
|
||||
*/
|
||||
|
||||
/**
|
||||
* Change the state of the given telegram instance and execute all event handlers
|
||||
*
|
||||
* @param instance The telegram instance that changed its state
|
||||
* @param state The changed state
|
||||
* @param data Extra data that depends on switched state
|
||||
*/
|
||||
void telegram_change_state(struct telegram *instance, int state, void *data);
|
||||
|
||||
/**
|
||||
* Connect to the telegram network with the given configuration
|
||||
*/
|
||||
void telegram_connect(struct telegram *instance);
|
||||
|
||||
/**
|
||||
* Read and process all available input from the network
|
||||
*/
|
||||
void mtp_read_input (struct mtproto_connection *mtp);
|
||||
|
||||
/**
|
||||
* Write all available output to the network
|
||||
*/
|
||||
int mtp_write_output (struct mtproto_connection *mtp);
|
||||
|
||||
/**
|
||||
* Try to interpret RPC calls and apply the changes to the current telegram state
|
||||
*/
|
||||
void try_rpc_interpret(struct telegram *instance, int op, int len);
|
||||
|
||||
/**
|
||||
* Request a registration code
|
||||
*/
|
||||
char* network_request_registration();
|
||||
|
||||
/**
|
||||
* Verify the registration with the given registration code
|
||||
*/
|
||||
int network_verify_registration(const char *code, const char *sms_hash);
|
||||
|
||||
/**
|
||||
* Verify the registration with the given registration code
|
||||
*/
|
||||
int network_verify_phone_registration(const char *code, const char *sms_hash,
|
||||
const char *first, const char *last);
|
||||
|
||||
/*
|
||||
* Load known users and chats on connect
|
||||
*/
|
||||
void event_user_info_received_handler(struct telegram *instance, struct tgl_user *peer, int showInfo);
|
||||
|
||||
/**
|
||||
* Set the connection after a proxy_request_cb
|
||||
*
|
||||
* @param fd The file-descriptor of the acquired connection
|
||||
* @param handle A handle that will be passed back on output and close callbacks
|
||||
*/
|
||||
struct mtproto_connection *telegram_add_proxy(struct telegram *tg, struct proxy_request *req, int fd, void *handle);
|
||||
|
||||
/**
|
||||
* Return wether telegram is authenticated with the currently active data center
|
||||
*/
|
||||
int telegram_authenticated (struct telegram *instance);
|
||||
|
||||
void telegram_flush (struct telegram *instance);
|
||||
void telegram_dl_add (struct telegram *instance, struct download *dl);
|
||||
void telegram_dl_next (struct telegram *instance);
|
||||
|
||||
#endif
|
|
@ -6,4 +6,3 @@ Efzk2DWgkBluml8OREmvfraX3bkHZJTKX4EQSjBbbdJ2ZXIsRrYOXfaA+xayEGB+
|
|||
8hdlLmAjbCVfaigxX0CDqWeR1yFL9kwd9P0NsZRPsmoqVwMbMu7mStFai6aIhc3n
|
||||
Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
|
||||
-----END RSA PUBLIC KEY-----
|
||||
|
||||
|
|
584
tgp-net.c
Normal file
|
@ -0,0 +1,584 @@
|
|||
/*
|
||||
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 <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <sys/types.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <poll.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "tgp-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"
|
||||
|
||||
#include <glib.h>
|
||||
#include <eventloop.h>
|
||||
|
||||
#include "telegram-purple.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 int ping_alarm (gpointer 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);
|
||||
return FALSE;
|
||||
} else if (tglt_get_double_time () - c->last_receive_time > 3 * PING_TIMEOUT && c->state == conn_ready) {
|
||||
tgl_do_send_ping (c->TLS, c);
|
||||
return TRUE;
|
||||
} else {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static void stop_ping_timer (struct connection *c) {
|
||||
purple_timeout_remove (c->ping_ev);
|
||||
}
|
||||
|
||||
static void start_ping_timer (struct connection *c) {
|
||||
c->ping_ev = purple_timeout_add_seconds (PING_TIMEOUT, ping_alarm, c);
|
||||
}
|
||||
|
||||
static void restart_connection (struct connection *c);
|
||||
|
||||
static int fail_alarm (gpointer arg) {
|
||||
struct connection *c = arg;
|
||||
c->in_fail_timer = 0;
|
||||
restart_connection (c);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void start_fail_timer (struct connection *c) {
|
||||
if (c->in_fail_timer) { return; }
|
||||
c->in_fail_timer = 1;
|
||||
|
||||
c->fail_ev = purple_timeout_add_seconds (10, fail_alarm, c);
|
||||
}
|
||||
|
||||
static struct connection_buffer *new_connection_buffer (int size) {
|
||||
struct connection_buffer *b = malloc (sizeof (*b));
|
||||
memset (b, 0, sizeof (*b));
|
||||
b->start = malloc (size);
|
||||
b->end = b->start + size;
|
||||
b->rptr = b->wptr = b->start;
|
||||
return b;
|
||||
}
|
||||
|
||||
static void delete_connection_buffer (struct connection_buffer *b) {
|
||||
free (b->start);
|
||||
free (b);
|
||||
}
|
||||
|
||||
static void conn_try_write (gpointer arg, gint source, PurpleInputCondition cond);
|
||||
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) {
|
||||
assert (c->write_ev == -1);
|
||||
c->write_ev = purple_input_add (c->fd, PURPLE_INPUT_WRITE, conn_try_write, c);
|
||||
}
|
||||
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) {
|
||||
}
|
||||
|
||||
//#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 (gpointer arg, gint source, PurpleInputCondition cond) {
|
||||
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 (gpointer arg, gint source, PurpleInputCondition cond) {
|
||||
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) {
|
||||
purple_input_remove (c->write_ev);
|
||||
c->write_ev = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void net_on_connected (gpointer arg, gint fd, const gchar *error_message) {
|
||||
struct connection *c = arg;
|
||||
struct tgl_state *TLS = c->TLS;
|
||||
vlogprintf (E_DEBUG - 2, "connect result: %d\n", fd);
|
||||
|
||||
if (fd == -1) {
|
||||
fail_connection (c);
|
||||
return;
|
||||
}
|
||||
|
||||
c->fd = fd;
|
||||
c->read_ev = purple_input_add (fd, PURPLE_INPUT_READ, conn_try_read, c);
|
||||
|
||||
char byte = 0xef;
|
||||
assert (tgln_write_out (c, &byte, 1) == 1);
|
||||
|
||||
c->last_receive_time = tglt_get_double_time ();
|
||||
start_ping_timer (c);
|
||||
}
|
||||
|
||||
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 = malloc (sizeof (*c));
|
||||
memset (c, 0, sizeof (*c));
|
||||
c->TLS = TLS;
|
||||
|
||||
|
||||
c->fd = -1;
|
||||
c->state = conn_connecting;
|
||||
|
||||
c->last_receive_time = tglt_get_double_time ();
|
||||
c->ip = strdup (host);
|
||||
c->flags = 0;
|
||||
c->port = port;
|
||||
|
||||
c->ping_ev = -1;
|
||||
c->fail_ev = -1;
|
||||
c->write_ev = -1;
|
||||
c->read_ev = -1;
|
||||
|
||||
c->dc = dc;
|
||||
c->session = session;
|
||||
c->methods = methods;
|
||||
|
||||
telegram_conn *conn = TLS->ev_base;
|
||||
c->prpl_data = purple_proxy_connect (conn->gc, conn->pa, host, port, net_on_connected, 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;
|
||||
}
|
||||
|
||||
telegram_conn *conn = TLS->ev_base;
|
||||
c->prpl_data = purple_proxy_connect (conn->gc, conn->pa, c->ip, c->port, net_on_connected, c);
|
||||
}
|
||||
|
||||
static void fail_connection (struct connection *c) {
|
||||
struct tgl_state *TLS = c->TLS;
|
||||
if (c->state == conn_ready) {
|
||||
stop_ping_timer (c);
|
||||
}
|
||||
if (c->write_ev >= 0) {
|
||||
purple_input_remove (c->write_ev);
|
||||
c->write_ev = -1;
|
||||
}
|
||||
if (c->read_ev >= 0) {
|
||||
purple_input_remove (c->write_ev);
|
||||
c->read_ev = -1;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (c->state == conn_ready) {
|
||||
telegram_conn *conn = TLS->ev_base;
|
||||
purple_connection_error_reason(conn->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, "connection fail");
|
||||
}
|
||||
c->prpl_data = NULL; // Did not find any destroy code. What should be done here?
|
||||
|
||||
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) { free (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 >= 0) {
|
||||
purple_timeout_remove (c->ping_ev);
|
||||
c->ping_ev = -1;
|
||||
}
|
||||
if (c->fail_ev >= 0) {
|
||||
purple_timeout_remove (c->fail_ev);
|
||||
c->fail_ev = -1;
|
||||
}
|
||||
|
||||
if (c->read_ev >= 0) {
|
||||
purple_input_remove (c->read_ev);
|
||||
}
|
||||
if (c->write_ev >= 0) {
|
||||
purple_input_remove (c->write_ev);
|
||||
}
|
||||
|
||||
c->fd = -1;
|
||||
}
|
||||
|
||||
struct tgl_net_methods tgp_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
|
||||
};
|
88
tgp-net.h
Normal file
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
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;
|
||||
int ping_ev;
|
||||
int fail_ev;
|
||||
int read_ev;
|
||||
int write_ev;
|
||||
double last_receive_time;
|
||||
void *prpl_data;
|
||||
};
|
||||
|
||||
//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 tgp_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
|
75
tgp-timers.c
Normal file
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
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 <tgl.h>
|
||||
#include <stdlib.h>
|
||||
#include <glib.h>
|
||||
#include <eventloop.h>
|
||||
|
||||
struct tgl_timer {
|
||||
struct tgl_state *TLS;
|
||||
void (*cb)(struct tgl_state *, void *);
|
||||
void *arg;
|
||||
int fd;
|
||||
};
|
||||
|
||||
static int timer_alarm (gpointer arg) {
|
||||
struct tgl_timer *t = arg;
|
||||
t->cb (t->TLS, t->arg);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static struct tgl_timer *tgl_timer_alloc (struct tgl_state *TLS, void (*cb)(struct tgl_state *TLS, void *arg), void *arg) {
|
||||
struct tgl_timer *t = malloc (sizeof (*t));
|
||||
t->TLS = TLS;
|
||||
t->cb = cb;
|
||||
t->arg = arg;
|
||||
t->fd = -1;
|
||||
return t;
|
||||
}
|
||||
|
||||
static void tgl_timer_insert (struct tgl_timer *t, double p) {
|
||||
if (p < 0) { p = 0; }
|
||||
if (p < 1) {
|
||||
t->fd = purple_timeout_add (1000 * p, timer_alarm, t);
|
||||
} else {
|
||||
t->fd = purple_timeout_add_seconds (p, timer_alarm, t);
|
||||
}
|
||||
}
|
||||
|
||||
static void tgl_timer_delete (struct tgl_timer *t) {
|
||||
if (t->fd >= 0) {
|
||||
purple_timeout_remove (t->fd);
|
||||
t->fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void tgl_timer_free (struct tgl_timer *t) {
|
||||
if (t->fd >= 0) {
|
||||
tgl_timer_delete (t);
|
||||
}
|
||||
free (t);
|
||||
}
|
||||
|
||||
struct tgl_timer_methods tgp_timers = {
|
||||
.alloc = tgl_timer_alloc,
|
||||
.insert = tgl_timer_insert,
|
||||
.delete = tgl_timer_delete,
|
||||
.free = tgl_timer_free
|
||||
};
|
27
tgp-timers.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
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 __TGL_TIMERS_H__
|
||||
#define __TGL_TIMERS_H__
|
||||
|
||||
#include "tgl.h"
|
||||
extern struct tgl_timer_methods tgp_timers;
|
||||
|
||||
#endif
|
259
tools.c
|
@ -1,259 +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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright Vitaly Valtman 2013
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <openssl/err.h>
|
||||
#include <zlib.h>
|
||||
|
||||
#include "tools.h"
|
||||
#include "msglog.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#define RES_PRE 8
|
||||
#define RES_AFTER 8
|
||||
#define MAX_BLOCKS 1000000
|
||||
void *blocks[MAX_BLOCKS];
|
||||
void *free_blocks[MAX_BLOCKS];
|
||||
int used_blocks;
|
||||
int free_blocks_cnt;
|
||||
#endif
|
||||
|
||||
extern int verbosity;
|
||||
|
||||
long long total_allocated_bytes;
|
||||
|
||||
static void out_of_memory (void) {
|
||||
fprintf (stderr, "Out of memory\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
int tsnprintf (char *buf, int len, const char *format, ...) {
|
||||
va_list ap;
|
||||
va_start (ap, format);
|
||||
int r = vsnprintf (buf, len, format, ap);
|
||||
va_end (ap);
|
||||
assert (r <= len && "tsnprintf buffer overflow");
|
||||
return r;
|
||||
}
|
||||
|
||||
int tasprintf (char **res, const char *format, ...) {
|
||||
va_list ap;
|
||||
va_start (ap, format);
|
||||
int r = vasprintf (res, format, ap);
|
||||
assert (r >= 0);
|
||||
va_end (ap);
|
||||
void *rs = talloc (strlen (*res) + 1);
|
||||
memcpy (rs, *res, strlen (*res) + 1);
|
||||
free (*res);
|
||||
*res = rs;
|
||||
return r;
|
||||
}
|
||||
|
||||
void print_backtrace (void);
|
||||
void tfree (void *ptr, int size __attribute__ ((unused))) {
|
||||
#ifdef DEBUG
|
||||
total_allocated_bytes -= size;
|
||||
ptr -= RES_PRE;
|
||||
if (size != (int)((*(int *)ptr) ^ 0xbedabeda)) {
|
||||
debug ("size = %d, ptr = %d\n", size, (*(int *)ptr) ^ 0xbedabeda);
|
||||
}
|
||||
assert (*(int *)ptr == (int)((size) ^ 0xbedabeda));
|
||||
assert (*(int *)(ptr + RES_PRE + size) == (int)((size) ^ 0x7bed7bed));
|
||||
assert (*(int *)(ptr + 4) == size);
|
||||
int block_num = *(int *)(ptr + 4 + RES_PRE + size);
|
||||
if (block_num >= used_blocks) {
|
||||
debug ("block_num = %d, used = %d\n", block_num, used_blocks);
|
||||
}
|
||||
assert (block_num < used_blocks);
|
||||
if (block_num < used_blocks - 1) {
|
||||
void *p = blocks[used_blocks - 1];
|
||||
int s = (*(int *)p) ^ 0xbedabeda;
|
||||
*(int *)(p + 4 + RES_PRE + s) = block_num;
|
||||
blocks[block_num] = p;
|
||||
}
|
||||
blocks[--used_blocks] = 0;
|
||||
memset (ptr, 0, size + RES_PRE + RES_AFTER);
|
||||
*(int *)ptr = size + 12;
|
||||
free_blocks[free_blocks_cnt ++] = ptr;
|
||||
#else
|
||||
free (ptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
void tfree_str (void *ptr) {
|
||||
if (!ptr) { return; }
|
||||
tfree (ptr, strlen (ptr) + 1);
|
||||
}
|
||||
|
||||
void tfree_secure (void *ptr, int size) {
|
||||
memset (ptr, 0, size);
|
||||
tfree (ptr, size);
|
||||
}
|
||||
|
||||
void *trealloc (void *ptr, size_t old_size __attribute__ ((unused)), size_t size) {
|
||||
#ifdef DEBUG
|
||||
void *p = talloc (size);
|
||||
memcpy (p, ptr, size >= old_size ? old_size : size);
|
||||
tfree (ptr, old_size);
|
||||
return p;
|
||||
#else
|
||||
void *p = realloc (ptr, size);
|
||||
ensure_ptr (p);
|
||||
return p;
|
||||
#endif
|
||||
}
|
||||
|
||||
void *talloc (size_t size) {
|
||||
#ifdef DEBUG
|
||||
total_allocated_bytes += size;
|
||||
void *p = malloc (size + RES_PRE + RES_AFTER);
|
||||
ensure_ptr (p);
|
||||
*(int *)p = size ^ 0xbedabeda;
|
||||
*(int *)(p + 4) = size;
|
||||
*(int *)(p + RES_PRE + size) = size ^ 0x7bed7bed;
|
||||
*(int *)(p + RES_AFTER + 4 + size) = used_blocks;
|
||||
blocks[used_blocks ++] = p;
|
||||
return p + 8;
|
||||
#else
|
||||
void *p = malloc (size);
|
||||
ensure_ptr (p);
|
||||
return p;
|
||||
#endif
|
||||
}
|
||||
|
||||
void *talloc0 (size_t size) {
|
||||
void *p = talloc (size);
|
||||
memset (p, 0, size);
|
||||
return p;
|
||||
}
|
||||
|
||||
char *tstrdup (const char *s) {
|
||||
#ifdef DEBUG
|
||||
int l = strlen (s);
|
||||
char *p = talloc (l + 1);
|
||||
memcpy (p, s, l + 1);
|
||||
return p;
|
||||
#else
|
||||
char *p = strdup (s);
|
||||
if (p == NULL) {
|
||||
out_of_memory ();
|
||||
}
|
||||
return p;
|
||||
#endif
|
||||
}
|
||||
|
||||
char *tstrndup (const char *s, size_t n) {
|
||||
#ifdef DEBUG
|
||||
size_t l = 0;
|
||||
for (l = 0; l < n && s[l]; l++) { }
|
||||
char *p = talloc (l + 1);
|
||||
memcpy (p, s, l);
|
||||
p[l] = 0;
|
||||
return p;
|
||||
#else
|
||||
char *p = strndup (s, n);
|
||||
if (p == NULL) {
|
||||
out_of_memory ();
|
||||
}
|
||||
return p;
|
||||
#endif
|
||||
}
|
||||
|
||||
void ensure (int r) {
|
||||
if (!r) {
|
||||
debug ("Open SSL error\n");
|
||||
ERR_print_errors_fp (stderr);
|
||||
assert (0);
|
||||
}
|
||||
}
|
||||
|
||||
void ensure_ptr (void *p) {
|
||||
if (p == NULL) {
|
||||
out_of_memory ();
|
||||
}
|
||||
}
|
||||
|
||||
int tinflate (void *input, int ilen, void *output, int olen) {
|
||||
z_stream strm;
|
||||
memset (&strm, 0, sizeof (strm));
|
||||
assert (inflateInit2 (&strm, 16 + MAX_WBITS) == Z_OK);
|
||||
strm.avail_in = ilen;
|
||||
strm.next_in = input;
|
||||
strm.avail_out = olen ;
|
||||
strm.next_out = output;
|
||||
int err = inflate (&strm, Z_FINISH), total_out = 0;
|
||||
if (err == Z_OK || err == Z_STREAM_END) {
|
||||
total_out = (int) strm.total_out;
|
||||
if (err == Z_STREAM_END && verbosity >= 2) {
|
||||
debug ( "inflated %d bytes\n", (int) strm.total_out);
|
||||
}
|
||||
}
|
||||
if (err != Z_STREAM_END) {
|
||||
debug ( "inflate error = %d\n", err);
|
||||
debug ( "inflated %d bytes\n", (int) strm.total_out);
|
||||
}
|
||||
inflateEnd (&strm);
|
||||
return total_out;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void tcheck (void) {
|
||||
int i;
|
||||
for (i = 0; i < used_blocks; i++) {
|
||||
void *ptr = blocks[i];
|
||||
int size = (*(int *)ptr) ^ 0xbedabeda;
|
||||
assert (*(int *)(ptr + 4) == size);
|
||||
assert (*(int *)(ptr + RES_PRE + size) == (size ^ 0x7bed7bed));
|
||||
assert (*(int *)(ptr + RES_PRE + 4 + size) == i);
|
||||
}
|
||||
for (i = 0; i < free_blocks_cnt; i++) {
|
||||
void *ptr = free_blocks[i];
|
||||
int l = *(int *)ptr;
|
||||
int j = 0;
|
||||
for (j = 0; j < l; j++) {
|
||||
if (*(char *)(ptr + 4 + j)) {
|
||||
hexdump (ptr + 8, ptr + 8 + l + ((-l) & 3));
|
||||
debug ("Used freed memory size = %d. ptr = %p\n", l + 4 - RES_PRE - RES_AFTER, ptr);
|
||||
assert (0);
|
||||
}
|
||||
}
|
||||
}
|
||||
debug ("ok. Used_blocks = %d. Free blocks = %d\n", used_blocks, free_blocks_cnt);
|
||||
}
|
||||
|
||||
void texists (void *ptr, int size) {
|
||||
ptr -= RES_PRE;
|
||||
if (size != (int)((*(int *)ptr) ^ 0xbedabeda)) {
|
||||
debug ("size = %d, ptr = %d\n", size, (*(int *)ptr) ^ 0xbedabeda);
|
||||
}
|
||||
assert (*(int *)ptr == (int)((size) ^ 0xbedabeda));
|
||||
assert (*(int *)(ptr + RES_PRE + size) == (int)((size) ^ 0x7bed7bed));
|
||||
assert (*(int *)(ptr + 4) == size);
|
||||
int block_num = *(int *)(ptr + 4 + RES_PRE + size);
|
||||
if (block_num >= used_blocks) {
|
||||
debug ("block_num = %d, used = %d\n", block_num, used_blocks);
|
||||
}
|
||||
assert (block_num < used_blocks);
|
||||
}
|
||||
#endif
|
43
tools.h
|
@ -1,43 +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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright Vitaly Valtman 2013
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
void *talloc (size_t size);
|
||||
void *trealloc (void *ptr, size_t old_size, size_t size);
|
||||
void *talloc0 (size_t size);
|
||||
char *tstrdup (const char *s);
|
||||
char *tstrndup (const char *s, size_t n);
|
||||
//char *stradd(const char *, ...);
|
||||
int tinflate (void *input, int ilen, void *output, int olen);
|
||||
void ensure (int r);
|
||||
void ensure_ptr (void *p);
|
||||
|
||||
void tfree (void *ptr, int size);
|
||||
void tfree_str (void *ptr);
|
||||
void tfree_secure (void *ptr, int size);
|
||||
|
||||
|
||||
int tsnprintf (char *buf, int len, const char *format, ...) __attribute__ ((format (printf, 3, 4)));
|
||||
int tasprintf (char **res, const char *format, ...) __attribute__ ((format (printf, 2, 3)));
|
||||
|
||||
#ifdef DEBUG
|
||||
void tcheck (void);
|
||||
void texists (void *ptr, int size);
|
||||
#endif
|
157
tree.h
|
@ -1,157 +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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright Vitaly Valtman 2013
|
||||
*/
|
||||
#ifndef __TREE_H__
|
||||
#define __TREE_H__
|
||||
#include <stdio.h>
|
||||
|
||||
#include <memory.h>
|
||||
#include <tools.h>
|
||||
#include <assert.h>
|
||||
|
||||
#pragma pack(push,4)
|
||||
#define DEFINE_TREE(X_NAME, X_TYPE, X_CMP, X_UNSET) \
|
||||
struct tree_ ## X_NAME { \
|
||||
struct tree_ ## X_NAME *left, *right;\
|
||||
X_TYPE x;\
|
||||
int y;\
|
||||
};\
|
||||
\
|
||||
struct tree_ ## X_NAME *new_tree_node_ ## X_NAME (X_TYPE x, int y) {\
|
||||
struct tree_ ## X_NAME *T = talloc (sizeof (*T));\
|
||||
T->x = x;\
|
||||
T->y = y;\
|
||||
T->left = T->right = 0;\
|
||||
return T;\
|
||||
}\
|
||||
\
|
||||
void delete_tree_node_ ## X_NAME (struct tree_ ## X_NAME *T) {\
|
||||
tfree (T, sizeof (*T));\
|
||||
}\
|
||||
\
|
||||
void tree_split_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x, struct tree_ ## X_NAME **L, struct tree_ ## X_NAME **R) {\
|
||||
if (!T) {\
|
||||
*L = *R = 0;\
|
||||
} else {\
|
||||
int c = X_CMP (x, T->x);\
|
||||
if (c < 0) {\
|
||||
tree_split_ ## X_NAME (T->left, x, L, &T->left);\
|
||||
*R = T;\
|
||||
} else {\
|
||||
tree_split_ ## X_NAME (T->right, x, &T->right, R);\
|
||||
*L = T;\
|
||||
}\
|
||||
}\
|
||||
}\
|
||||
\
|
||||
struct tree_ ## X_NAME *tree_insert_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x, int y) __attribute__ ((warn_unused_result));\
|
||||
struct tree_ ## X_NAME *tree_insert_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x, int y) {\
|
||||
if (!T) {\
|
||||
return new_tree_node_ ## X_NAME (x, y);\
|
||||
} else {\
|
||||
if (y > T->y) {\
|
||||
struct tree_ ## X_NAME *N = new_tree_node_ ## X_NAME (x, y);\
|
||||
tree_split_ ## X_NAME (T, x, &N->left, &N->right);\
|
||||
return N;\
|
||||
} else {\
|
||||
int c = X_CMP (x, T->x);\
|
||||
assert (c);\
|
||||
if (c < 0) { \
|
||||
T->left = tree_insert_ ## X_NAME (T->left, x, y);\
|
||||
} else { \
|
||||
T->right = tree_insert_ ## X_NAME (T->right, x, y);\
|
||||
} \
|
||||
return T; \
|
||||
}\
|
||||
}\
|
||||
}\
|
||||
\
|
||||
struct tree_ ## X_NAME *tree_merge_ ## X_NAME (struct tree_ ## X_NAME *L, struct tree_ ## X_NAME *R) {\
|
||||
if (!L || !R) {\
|
||||
return L ? L : R;\
|
||||
} else {\
|
||||
if (L->y > R->y) {\
|
||||
L->right = tree_merge_ ## X_NAME (L->right, R);\
|
||||
return L;\
|
||||
} else {\
|
||||
R->left = tree_merge_ ## X_NAME (L, R->left);\
|
||||
return R;\
|
||||
}\
|
||||
}\
|
||||
}\
|
||||
\
|
||||
struct tree_ ## X_NAME *tree_delete_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x) __attribute__ ((warn_unused_result));\
|
||||
struct tree_ ## X_NAME *tree_delete_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x) {\
|
||||
assert (T);\
|
||||
int c = X_CMP (x, T->x);\
|
||||
if (!c) {\
|
||||
struct tree_ ## X_NAME *N = tree_merge_ ## X_NAME (T->left, T->right);\
|
||||
delete_tree_node_ ## X_NAME (T);\
|
||||
return N;\
|
||||
} else {\
|
||||
if (c < 0) { \
|
||||
T->left = tree_delete_ ## X_NAME (T->left, x); \
|
||||
} else { \
|
||||
T->right = tree_delete_ ## X_NAME (T->right, x); \
|
||||
} \
|
||||
return T; \
|
||||
}\
|
||||
}\
|
||||
\
|
||||
X_TYPE tree_get_min_ ## X_NAME (struct tree_ ## X_NAME *T) {\
|
||||
if (!T) { return X_UNSET; } \
|
||||
while (T->left) { T = T->left; }\
|
||||
return T->x; \
|
||||
} \
|
||||
\
|
||||
X_TYPE tree_lookup_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x) {\
|
||||
int c;\
|
||||
while (T && (c = X_CMP (x, T->x))) {\
|
||||
T = (c < 0 ? T->left : T->right);\
|
||||
}\
|
||||
return T ? T->x : X_UNSET;\
|
||||
}\
|
||||
\
|
||||
void tree_act_ ## X_NAME (struct tree_ ## X_NAME *T, void (*act)(X_TYPE)) {\
|
||||
if (!T) { return; } \
|
||||
tree_act_ ## X_NAME (T->left, act); \
|
||||
act (T->x); \
|
||||
tree_act_ ## X_NAME (T->right, act); \
|
||||
}\
|
||||
\
|
||||
int tree_count_ ## X_NAME (struct tree_ ## X_NAME *T) { \
|
||||
if (!T) { return 0; }\
|
||||
return 1 + tree_count_ ## X_NAME (T->left) + tree_count_ ## X_NAME (T->right); \
|
||||
}\
|
||||
void tree_check_ ## X_NAME (struct tree_ ## X_NAME *T) { \
|
||||
if (!T) { return; }\
|
||||
if (T->left) { \
|
||||
assert (T->left->y <= T->y);\
|
||||
assert (X_CMP (T->left->x, T->x) < 0); \
|
||||
}\
|
||||
if (T->right) { \
|
||||
assert (T->right->y <= T->y);\
|
||||
assert (X_CMP (T->right->x, T->x) > 0); \
|
||||
}\
|
||||
tree_check_ ## X_NAME (T->left); \
|
||||
tree_check_ ## X_NAME (T->right); \
|
||||
}\
|
||||
|
||||
#define int_cmp(a,b) ((a) - (b))
|
||||
#pragma pack(pop)
|
||||
#endif
|