diff options
Diffstat (limited to 'kopete/protocols')
150 files changed, 9466 insertions, 9096 deletions
diff --git a/kopete/protocols/CMakeLists.txt b/kopete/protocols/CMakeLists.txt new file mode 100644 index 00000000..14127078 --- /dev/null +++ b/kopete/protocols/CMakeLists.txt @@ -0,0 +1,22 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +tde_conditional_add_subdirectory( BUILD_KOPETE_PROTOCOL_TESTBED testbed ) +tde_conditional_add_subdirectory( BUILD_KOPETE_PROTOCOL_GROUPWISE groupwise ) +tde_conditional_add_subdirectory( BUILD_KOPETE_PROTOCOL_MSN msn ) +tde_conditional_add_subdirectory( BUILD_KOPETE_PROTOCOL_IRC irc ) +tde_conditional_add_subdirectory( BUILD_KOPETE_PROTOCOL_OSCAR oscar ) +tde_conditional_add_subdirectory( BUILD_KOPETE_PROTOCOL_YAHOO yahoo ) +tde_conditional_add_subdirectory( BUILD_KOPETE_PROTOCOL_WINPOPUP winpopup ) +tde_conditional_add_subdirectory( BUILD_KOPETE_PROTOCOL_SMS sms ) +tde_conditional_add_subdirectory( BUILD_KOPETE_PROTOCOL_JABBER jabber ) +tde_conditional_add_subdirectory( BUILD_KOPETE_PROTOCOL_GADU gadu ) +tde_conditional_add_subdirectory( BUILD_KOPETE_PROTOCOL_MEANWHILE meanwhile ) diff --git a/kopete/protocols/gadu/CMakeLists.txt b/kopete/protocols/gadu/CMakeLists.txt new file mode 100644 index 00000000..bb5326d4 --- /dev/null +++ b/kopete/protocols/gadu/CMakeLists.txt @@ -0,0 +1,50 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include( ConfigureChecks.cmake ) + +add_subdirectory( ui ) +add_subdirectory( icons ) + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/ui + ${CMAKE_BINARY_DIR}/kopete/libkopete/ui + ${CMAKE_SOURCE_DIR}/kopete/libkopete + ${CMAKE_SOURCE_DIR}/kopete/libkopete/ui + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} + ${GADU_INCLUDE_DIRS} +) + +link_directories( + ${TQT_LIBRARY_DIRS} +) + + +##### other data ################################ + +install( FILES kopete_gadu.desktop DESTINATION ${SERVICES_INSTALL_DIR} ) + + +##### kopete_gadu (module) ###################### + +tde_add_kpart( kopete_gadu AUTOMOC + SOURCES + gaduaway.cpp gadueditcontact.cpp gaducommands.cpp + gadueditaccount.cpp gadusession.cpp gaducontact.cpp + gaduaddcontactpage.cpp gaduprotocol.cpp gaduaccount.cpp + gadupubdir.cpp gaduregisteraccount.cpp gaducontactlist.cpp + gadurichtextformat.cpp gadudccserver.cpp gadudcctransaction.cpp + gadudcc.cpp + LINK gaduui-static kopete-shared ${GADU_LIBRARIES} + DESTINATION ${PLUGIN_INSTALL_DIR} +) diff --git a/kopete/protocols/gadu/ConfigureChecks.cmake b/kopete/protocols/gadu/ConfigureChecks.cmake new file mode 100644 index 00000000..1511e879 --- /dev/null +++ b/kopete/protocols/gadu/ConfigureChecks.cmake @@ -0,0 +1,15 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +pkg_search_module( GADU libgadu ) +if( NOT GADU_FOUND ) + tde_message_fatal( "libgadu is required, but was not found on your system" ) +endif( ) diff --git a/kopete/protocols/gadu/gadueditcontact.h b/kopete/protocols/gadu/gadueditcontact.h index e9413a2b..f135d55a 100644 --- a/kopete/protocols/gadu/gadueditcontact.h +++ b/kopete/protocols/gadu/gadueditcontact.h @@ -31,7 +31,6 @@ class TQLabel; class TQString; class TQWidget; class GaduContact; -class GaduContactsList::ContactLine; class TQListViewItem; class GaduEditContact : public KDialogBase diff --git a/kopete/protocols/gadu/icons/CMakeLists.txt b/kopete/protocols/gadu/icons/CMakeLists.txt new file mode 100644 index 00000000..ba51467b --- /dev/null +++ b/kopete/protocols/gadu/icons/CMakeLists.txt @@ -0,0 +1,12 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +tde_install_icons( DESTINATION ${DATA_INSTALL_DIR}/kopete/icons ) diff --git a/kopete/protocols/gadu/libgadu/COPYING b/kopete/protocols/gadu/libgadu/COPYING deleted file mode 100644 index 071eee49..00000000 --- a/kopete/protocols/gadu/libgadu/COPYING +++ /dev/null @@ -1,504 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 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. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -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 and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, 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 library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete 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 distribute a copy of this License along with the -Library. - - 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 Library or any portion -of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -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 Library, 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 Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you 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. - - If distribution of 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 satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be 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. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library 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. - - 9. 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 Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -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 with -this License. - - 11. 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 Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library 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 Library. - -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. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library 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. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser 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 Library -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 Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -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 - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "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 -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. 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 LIBRARY 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 -LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), 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 Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. 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 library's name and a brief idea of what it does.> - Copyright (C) <year> <name of author> - - 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 - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - <signature of Ty Coon>, 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - diff --git a/kopete/protocols/gadu/libgadu/Makefile.am b/kopete/protocols/gadu/libgadu/Makefile.am deleted file mode 100644 index 94693d38..00000000 --- a/kopete/protocols/gadu/libgadu/Makefile.am +++ /dev/null @@ -1,12 +0,0 @@ -METASOURCES = AUTO -noinst_LTLIBRARIES = libgadu_copy.la -INCLUDES = $(SSL_INCLUDES) $(all_includes) -libgadu_copy_la_LDFLAGS = $(SSL_LDFLAGS) $(all_libraries) -libgadu_copy_la_LIBADD = $(LIBSSL) $(LIBPTHREAD) -libgadu_copy_la_SOURCES = common.c \ - dcc.c \ - events.c \ - http.c \ - libgadu.c \ - pubdir50.c \ - pubdir.c diff --git a/kopete/protocols/gadu/libgadu/common.c b/kopete/protocols/gadu/libgadu/common.c deleted file mode 100644 index 9e20422a..00000000 --- a/kopete/protocols/gadu/libgadu/common.c +++ /dev/null @@ -1,827 +0,0 @@ -/* $Id$ */ - -/* - * (C) Copyright 2001-2002 Wojtek Kaniewski <wojtekka@irc.pl> - * Robert J. Wo�ny <speedy@ziew.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License Version - * 2.1 as published by the Free Software Foundation. - * - * 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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. - */ - -#include <sys/types.h> -#include <sys/ioctl.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#ifdef sun -# include <sys/filio.h> -#endif - -#include <errno.h> -#include <fcntl.h> -#include <netdb.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include "libgadu.h" - -FILE *gg_debug_file = NULL; - -#ifndef GG_DEBUG_DISABLE - -/* - * gg_debug() // funkcja wewn�trzna - * - * wy�wietla komunikat o danym poziomie, o ile u�ytkownik sobie tego �yczy. - * - * - level - poziom wiadomo�ci - * - format... - tre�� wiadomo�ci (kompatybilna z printf()) - */ -void gg_debug(int level, const char *format, ...) -{ - va_list ap; - int old_errno = errno; - - if (gg_debug_handler) { - va_start(ap, format); - (*gg_debug_handler)(level, format, ap); - va_end(ap); - - goto cleanup; - } - - if ((gg_debug_level & level)) { - va_start(ap, format); - vfprintf((gg_debug_file) ? gg_debug_file : stderr, format, ap); - va_end(ap); - } - -cleanup: - errno = old_errno; -} - -#endif - -/* - * gg_vsaprintf() // funkcja pomocnicza - * - * robi dok�adnie to samo, co vsprintf(), tyle �e alokuje sobie wcze�niej - * miejsce na dane. powinno dzia�a� na tych maszynach, kt�re maj� funkcj� - * vsnprintf() zgodn� z C99, jak i na wcze�niejszych. - * - * - format - opis wy�wietlanego tekstu jak dla printf() - * - ap - lista argument�w dla printf() - * - * zaalokowany bufor, kt�ry nale�y p��niej zwolni�, lub NULL - * je�li nie uda�o si� wykona� zadania. - */ -char *gg_vsaprintf(const char *format, va_list ap) -{ - int size = 0; - const char *start; - char *buf = NULL; - -#ifdef __GG_LIBGADU_HAVE_VA_COPY - va_list aq; - - va_copy(aq, ap); -#else -# ifdef __GG_LIBGADU_HAVE___VA_COPY - va_list aq; - - __va_copy(aq, ap); -# endif -#endif - - start = format; - -#ifndef __GG_LIBGADU_HAVE_C99_VSNPRINTF - { - int res; - char *tmp; - - size = 128; - do { - size *= 2; - if (!(tmp = realloc(buf, size))) { - free(buf); - return NULL; - } - buf = tmp; - res = vsnprintf(buf, size, format, ap); - } while (res == size - 1 || res == -1); - } -#else - { - char tmp[2]; - - /* libce Solarisa przy buforze NULL zawsze zwracaj� -1, wi�c - * musimy poda� co� istniej�cego jako cel printf()owania. */ - size = vsnprintf(tmp, sizeof(tmp), format, ap); - if (!(buf = malloc(size + 1))) - return NULL; - } -#endif - - format = start; - -#ifdef __GG_LIBGADU_HAVE_VA_COPY - vsnprintf(buf, size + 1, format, aq); - va_end(aq); -#else -# ifdef __GG_LIBGADU_HAVE___VA_COPY - vsnprintf(buf, size + 1, format, aq); - va_end(aq); -# else - vsnprintf(buf, size + 1, format, ap); -# endif -#endif - - return buf; -} - -/* - * gg_saprintf() // funkcja pomocnicza - * - * robi dok�adnie to samo, co sprintf(), tyle �e alokuje sobie wcze�niej - * miejsce na dane. powinno dzia�a� na tych maszynach, kt�re maj� funkcj� - * vsnprintf() zgodn� z C99, jak i na wcze�niejszych. - * - * - format... - tre�� taka sama jak w funkcji printf() - * - * zaalokowany bufor, kt�ry nale�y p��niej zwolni�, lub NULL - * je�li nie uda�o si� wykona� zadania. - */ -char *gg_saprintf(const char *format, ...) -{ - va_list ap; - char *res; - - va_start(ap, format); - res = gg_vsaprintf(format, ap); - va_end(ap); - - return res; -} - -/* - * gg_get_line() // funkcja pomocnicza - * - * podaje kolejn� lini� z bufora tekstowego. niszczy go bezpowrotnie, dziel�c - * na kolejne stringi. zdarza si�, nie ma potrzeby pisania funkcji dubluj�cej - * bufor �eby tylko mie� nieruszone dane wej�ciowe, skoro i tak nie b�d� nam - * po�niej potrzebne. obcina `\r\n'. - * - * - ptr - wska�nik do zmiennej, kt�ra przechowuje aktualn� pozycj� - * w przemiatanym buforze - * - * wska�nik do kolejnej linii tekstu lub NULL, je�li to ju� koniec bufora. - */ -char *gg_get_line(char **ptr) -{ - const char *foo; - char *res; - - if (!ptr || !*ptr || !strcmp(*ptr, "")) - return NULL; - - res = *ptr; - - if (!(foo = strchr(*ptr, '\n'))) - *ptr += strlen(*ptr); - else { - *ptr = foo + 1; - if (strlen(res) > 1 && res[strlen(res) - 1] == '\r') - res[strlen(res) - 1] = 0; - } - - return res; -} - -/* - * gg_connect() // funkcja pomocnicza - * - * ��czy si� z serwerem. pierwszy argument jest typu (void *), �eby nie - * musie� niczego inkludowa� w libgadu.h i nie psu� jaki� g�upich zale�no�ci - * na dziwnych systemach. - * - * - addr - adres serwera (struct in_addr *) - * - port - port serwera - * - async - asynchroniczne po��czenie - * - * deskryptor gniazda lub -1 w przypadku b��du (kod b��du w zmiennej errno). - */ -int gg_connect(void *addr, int port, int async) -{ - int sock, one = 1, errno2; - struct sockaddr_in sin; - struct in_addr *a = addr; - struct sockaddr_in myaddr; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_connect(%s, %d, %d);\n", inet_ntoa(*a), port, async); - - if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_connect() socket() failed (errno=%d, %s)\n", errno, strerror(errno)); - return -1; - } - - memset(&myaddr, 0, sizeof(myaddr)); - myaddr.sin_family = AF_INET; - - myaddr.sin_addr.s_addr = gg_local_ip; - - if (bind(sock, (struct sockaddr *) &myaddr, sizeof(myaddr)) == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_connect() bind() failed (errno=%d, %s)\n", errno, strerror(errno)); - return -1; - } - -#ifdef ASSIGN_SOCKETS_TO_THREADS - gg_win32_thread_socket(0, sock); -#endif - - if (async) { -#ifdef FIONBIO - if (ioctl(sock, FIONBIO, &one) == -1) { -#else - if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1) { -#endif - gg_debug(GG_DEBUG_MISC, "// gg_connect() ioctl() failed (errno=%d, %s)\n", errno, strerror(errno)); - errno2 = errno; - close(sock); - errno = errno2; - return -1; - } - } - - sin.sin_port = htons(port); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = a->s_addr; - - if (connect(sock, (struct sockaddr*) &sin, sizeof(sin)) == -1) { - if (errno && (!async || errno != EINPROGRESS)) { - gg_debug(GG_DEBUG_MISC, "// gg_connect() connect() failed (errno=%d, %s)\n", errno, strerror(errno)); - errno2 = errno; - close(sock); - errno = errno2; - return -1; - } - gg_debug(GG_DEBUG_MISC, "// gg_connect() connect() in progress\n"); - } - - return sock; -} - -/* - * gg_read_line() // funkcja pomocnicza - * - * czyta jedn� lini� tekstu z gniazda. - * - * - sock - deskryptor gniazda - * - buf - wska�nik do bufora - * - length - d�ugo�� bufora - * - * je�li trafi na b��d odczytu lub podano nieprawid�owe parametry, zwraca NULL. - * inaczej zwraca buf. - */ -char *gg_read_line(int sock, char *buf, int length) -{ - int ret; - - if (!buf || length < 0) - return NULL; - - for (; length > 1; buf++, length--) { - do { - if ((ret = read(sock, buf, 1)) == -1 && errno != EINTR) { - gg_debug(GG_DEBUG_MISC, "// gg_read_line() error on read (errno=%d, %s)\n", errno, strerror(errno)); - *buf = 0; - return NULL; - } else if (ret == 0) { - gg_debug(GG_DEBUG_MISC, "// gg_read_line() eof reached\n"); - *buf = 0; - return NULL; - } - } while (ret == -1 && errno == EINTR); - - if (*buf == '\n') { - buf++; - break; - } - } - - *buf = 0; - return buf; -} - -/* - * gg_chomp() // funkcja pomocnicza - * - * ucina "\r\n" lub "\n" z ko�ca linii. - * - * - line - linia do przyci�cia - */ -void gg_chomp(char *line) -{ - int len; - - if (!line) - return; - - len = strlen(line); - - if (len > 0 && line[len - 1] == '\n') - line[--len] = 0; - if (len > 0 && line[len - 1] == '\r') - line[--len] = 0; -} - -/* - * gg_urlencode() // funkcja wewn�trzna - * - * zamienia podany tekst na ci�g znak�w do formularza http. przydaje si� - * przy r��nych us�ugach katalogu publicznego. - * - * - str - ci�g znak�w do zakodowania - * - * zaalokowany bufor, kt�ry nale�y p��niej zwolni� albo NULL - * w przypadku b��du. - */ -char *gg_urlencode(const char *str) -{ - char *q, *buf, hex[] = "0123456789abcdef"; - const char *p; - unsigned int size = 0; - - if (!str) - str = ""; - - for (p = str; *p; p++, size++) { - if (!((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9') || *p == ' ') || (*p == '@') || (*p == '.') || (*p == '-')) - size += 2; - } - - if (!(buf = malloc(size + 1))) - return NULL; - - for (p = str, q = buf; *p; p++, q++) { - if ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9') || (*p == '@') || (*p == '.') || (*p == '-')) - *q = *p; - else { - if (*p == ' ') - *q = '+'; - else { - *q++ = '%'; - *q++ = hex[*p >> 4 & 15]; - *q = hex[*p & 15]; - } - } - } - - *q = 0; - - return buf; -} - -/* - * gg_http_hash() // funkcja wewn�trzna - * - * funkcja licz�ca hash dla adresu e-mail, has�a i paru innych. - * - * - format... - format kolejnych parametr�w ('s' je�li dany parametr jest - * ci�giem znak�w lub 'u' je�li numerem GG) - * - * hash wykorzystywany przy rejestracji i wszelkich manipulacjach w�asnego - * wpisu w katalogu publicznym. - */ -int gg_http_hash(const char *format, ...) -{ - unsigned int a, c, i, j; - va_list ap; - int b = -1; - - va_start(ap, format); - - for (j = 0; j < strlen(format); j++) { - char *arg, buf[16]; - - if (format[j] == 'u') { - snprintf(buf, sizeof(buf), "%d", va_arg(ap, uin_t)); - arg = buf; - } else { - if (!(arg = va_arg(ap, char*))) - arg = ""; - } - - i = 0; - while ((c = (unsigned char) arg[i++]) != 0) { - a = (c ^ b) + (c << 8); - b = (a >> 24) | (a << 8); - } - } - - va_end(ap); - - return (b < 0 ? -b : b); -} - -/* - * gg_gethostbyname() // funkcja pomocnicza - * - * odpowiednik gethostbyname() troszcz�cy si� o wsp��bie�no��, gdy mamy do - * dyspozycji funkcj� gethostbyname_r(). - * - * - hostname - nazwa serwera - * - * zwraca wska�nik na struktur� in_addr, kt�r� nale�y zwolni�. - */ -struct in_addr *gg_gethostbyname(const char *hostname) -{ - struct in_addr *addr = NULL; - -#ifdef HAVE_GETHOSTBYNAME_R - char *tmpbuf = NULL, *buf = NULL; - struct hostent *hp = NULL, *hp2 = NULL; - int h_errnop, ret; - size_t buflen = 1024; - int new_errno; - - new_errno = ENOMEM; - - if (!(addr = malloc(sizeof(struct in_addr)))) - goto cleanup; - - if (!(hp = calloc(1, sizeof(*hp)))) - goto cleanup; - - if (!(buf = malloc(buflen))) - goto cleanup; - - tmpbuf = buf; - - while ((ret = gethostbyname_r(hostname, hp, buf, buflen, &hp2, &h_errnop)) == ERANGE) { - buflen *= 2; - - if (!(tmpbuf = realloc(buf, buflen))) - break; - - buf = tmpbuf; - } - - if (ret) - new_errno = h_errnop; - - if (ret || !hp2 || !tmpbuf) - goto cleanup; - - memcpy(addr, hp->h_addr, sizeof(struct in_addr)); - - free(buf); - free(hp); - - return addr; - -cleanup: - errno = new_errno; - - if (addr) - free(addr); - if (hp) - free(hp); - if (buf) - free(buf); - - return NULL; -#else - struct hostent *hp; - - if (!(addr = malloc(sizeof(struct in_addr)))) { - goto cleanup; - } - - if (!(hp = gethostbyname(hostname))) - goto cleanup; - - memcpy(addr, hp->h_addr, sizeof(struct in_addr)); - - return addr; - -cleanup: - if (addr) - free(addr); - - return NULL; -#endif -} - -#ifdef ASSIGN_SOCKETS_TO_THREADS - -typedef struct gg_win32_thread { - int id; - int socket; - struct gg_win32_thread *next; -} gg_win32_thread; - -struct gg_win32_thread *gg_win32_threads = 0; - -/* - * gg_win32_thread_socket() // funkcja pomocnicza, tylko dla win32 - * - * zwraca deskryptor gniazda, kt�re by�o ostatnio tworzone dla w�tku - * o podanym identyfikatorze. - * - * je�li na win32 przy po��czeniach synchronicznych zapami�tamy w jakim - * w�tku uruchomili�my funkcj�, kt�ra si� z czymkolwiek ��czy, to z osobnego - * w�tku mo�emy anulowa� po��czenie poprzez gg_win32_thread_socket(watek, -1); - * - * - thread_id - id w�tku. je�li jest r�wne 0, brany jest aktualny w�tek, - * je�li r�wne -1, usuwa wpis o podanym sockecie. - * - socket - deskryptor gniazda. je�li r�wne 0, zwraca deskryptor gniazda - * dla podanego w�tku, je�li r�wne -1, usuwa wpis, je�li co� - * innego, ustawia dla podanego w�tku dany numer deskryptora. - * - * je�li socket jest r�wne 0, zwraca deskryptor gniazda dla podanego w�tku. - */ -int gg_win32_thread_socket(int thread_id, int socket) -{ - char close = (thread_id == -1) || socket == -1; - gg_win32_thread *wsk = gg_win32_threads; - gg_win32_thread **p_wsk = &gg_win32_threads; - - if (!thread_id) - thread_id = GetCurrentThreadId(); - - while (wsk) { - if ((thread_id == -1 && wsk->socket == socket) || wsk->id == thread_id) { - if (close) { - /* socket zostaje usuniety */ - closesocket(wsk->socket); - *p_wsk = wsk->next; - free(wsk); - return 1; - } else if (!socket) { - /* socket zostaje zwrocony */ - return wsk->socket; - } else { - /* socket zostaje ustawiony */ - wsk->socket = socket; - return socket; - } - } - p_wsk = &(wsk->next); - wsk = wsk->next; - } - - if (close && socket != -1) - closesocket(socket); - if (close || !socket) - return 0; - - /* Dodaje nowy element */ - wsk = malloc(sizeof(gg_win32_thread)); - wsk->id = thread_id; - wsk->socket = socket; - wsk->next = 0; - *p_wsk = wsk; - - return socket; -} - -#endif /* ASSIGN_SOCKETS_TO_THREADS */ - -static char gg_base64_charset[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -/* - * gg_base64_encode() - * - * zapisuje ci�g znak�w w base64. - * - * - buf - ci�g znak�w. - * - * zaalokowany bufor. - */ -char *gg_base64_encode(const char *buf) -{ - char *out, *res; - unsigned int i = 0, j = 0, k = 0, len = strlen(buf); - - res = out = malloc((len / 3 + 1) * 4 + 2); - - if (!res) - return NULL; - - while (j <= len) { - switch (i % 4) { - case 0: - k = (buf[j] & 252) >> 2; - break; - case 1: - if (j < len) - k = ((buf[j] & 3) << 4) | ((buf[j + 1] & 240) >> 4); - else - k = (buf[j] & 3) << 4; - - j++; - break; - case 2: - if (j < len) - k = ((buf[j] & 15) << 2) | ((buf[j + 1] & 192) >> 6); - else - k = (buf[j] & 15) << 2; - - j++; - break; - case 3: - k = buf[j++] & 63; - break; - } - *out++ = gg_base64_charset[k]; - i++; - } - - if (i % 4) - for (j = 0; j < 4 - (i % 4); j++, out++) - *out = '='; - - *out = 0; - - return res; -} - -/* - * gg_base64_decode() - * - * dekoduje ci�g znak�w z base64. - * - * - buf - ci�g znak�w. - * - * zaalokowany bufor. - */ -char *gg_base64_decode(const char *buf) -{ - const char *foo2; - char *res, *save, *foo, val; - const char *end; - unsigned int index = 0; - - if (!buf) - return NULL; - - save = res = calloc(1, (strlen(buf) / 4 + 1) * 3 + 2); - - if (!save) - return NULL; - - end = buf + strlen(buf); - - while (*buf && buf < end) { - if (*buf == '\r' || *buf == '\n') { - buf++; - continue; - } - if (!(foo2 = strchr(gg_base64_charset, *buf))) { - foo = gg_base64_charset; - } - else { - foo = foo2; - } - val = (int)(foo - gg_base64_charset); - buf++; - switch (index) { - case 0: - *res |= val << 2; - break; - case 1: - *res++ |= val >> 4; - *res |= val << 4; - break; - case 2: - *res++ |= val >> 2; - *res |= val << 6; - break; - case 3: - *res++ |= val; - break; - } - index++; - index %= 4; - } - *res = 0; - - return save; -} - -/* - * gg_proxy_auth() // funkcja wewn�trzna - * - * tworzy nag��wek autoryzacji dla proxy. - * - * zaalokowany tekst lub NULL, je�li proxy nie jest w��czone lub nie wymaga - * autoryzacji. - */ -char *gg_proxy_auth() -{ - char *tmp, *enc, *out; - unsigned int tmp_size; - - if (!gg_proxy_enabled || !gg_proxy_username || !gg_proxy_password) - return NULL; - - if (!(tmp = malloc((tmp_size = strlen(gg_proxy_username) + strlen(gg_proxy_password) + 2)))) - return NULL; - - snprintf(tmp, tmp_size, "%s:%s", gg_proxy_username, gg_proxy_password); - - if (!(enc = gg_base64_encode(tmp))) { - free(tmp); - return NULL; - } - - free(tmp); - - if (!(out = malloc(strlen(enc) + 40))) { - free(enc); - return NULL; - } - - snprintf(out, strlen(enc) + 40, "Proxy-Authorization: Basic %s\r\n", enc); - - free(enc); - - return out; -} - -static uint32_t gg_crc32_table[256]; -static int gg_crc32_initialized = 0; - -/* - * gg_crc32_make_table() // funkcja wewn�trzna - */ -static void gg_crc32_make_table() -{ - uint32_t h = 1; - unsigned int i, j; - - memset(gg_crc32_table, 0, sizeof(gg_crc32_table)); - - for (i = 128; i; i >>= 1) { - h = (h >> 1) ^ ((h & 1) ? 0xedb88320L : 0); - - for (j = 0; j < 256; j += 2 * i) - gg_crc32_table[i + j] = gg_crc32_table[j] ^ h; - } - - gg_crc32_initialized = 1; -} - -/* - * gg_crc32() - * - * wyznacza sum� kontroln� CRC32 danego bloku danych. - * - * - crc - suma kontrola poprzedniego bloku danych lub 0 je�li pierwszy - * - buf - bufor danych - * - size - ilo�� danych - * - * suma kontrolna CRC32. - */ -uint32_t gg_crc32(uint32_t crc, const unsigned char *buf, int len) -{ - if (!gg_crc32_initialized) - gg_crc32_make_table(); - - if (!buf || len < 0) - return crc; - - crc ^= 0xffffffffL; - - while (len--) - crc = (crc >> 8) ^ gg_crc32_table[(crc ^ *buf++) & 0xff]; - - return crc ^ 0xffffffffL; -} - - -/* - * Local variables: - * c-indentation-style: k&r - * c-basic-offset: 8 - * indent-tabs-mode: notnil - * End: - * - * vim: shiftwidth=8: - */ diff --git a/kopete/protocols/gadu/libgadu/compat.h b/kopete/protocols/gadu/libgadu/compat.h deleted file mode 100644 index 8b9098fe..00000000 --- a/kopete/protocols/gadu/libgadu/compat.h +++ /dev/null @@ -1,29 +0,0 @@ -/* $Id$ */ - -/* - * (C) Copyright 2001-2002 Wojtek Kaniewski <wojtekka@irc.pl> - * Robert J. Wo¼ny <speedy@ziew.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License Version - * 2.1 as published by the Free Software Foundation. - * - * 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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. - */ - -#ifndef __COMPAT_H -#define __COMPAT_H - -#ifdef sun -# define INADDR_NONE ((in_addr_t) 0xffffffff) -#endif - -#endif diff --git a/kopete/protocols/gadu/libgadu/dcc.c b/kopete/protocols/gadu/libgadu/dcc.c deleted file mode 100644 index d6b3c7cc..00000000 --- a/kopete/protocols/gadu/libgadu/dcc.c +++ /dev/null @@ -1,1298 +0,0 @@ -/* $Id$ */ - -/* - * (C) Copyright 2001-2006 Wojtek Kaniewski <wojtekka@irc.pl> - * Tomasz Chiliñski <chilek@chilan.com> - * Adam Wysocki <gophi@ekg.chmurka.net> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License Version - * 2.1 as published by the Free Software Foundation. - * - * 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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. - */ - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#ifdef sun -# include <sys/filio.h> -#endif - -#include <ctype.h> -#include <errno.h> -#include <fcntl.h> -#include <stdarg.h> -#include <string.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -#include "compat.h" -#include "libgadu.h" - -#ifndef GG_DEBUG_DISABLE -/* - * gg_dcc_debug_data() // funkcja wewnêtrzna - * - * wy¶wietla zrzut pakietu w hexie. - * - * - prefix - prefiks zrzutu pakietu - * - fd - deskryptor gniazda - * - buf - bufor z danymi - * - size - rozmiar danych - */ -static void gg_dcc_debug_data(const char *prefix, int fd, const void *buf, unsigned int size) -{ - unsigned int i; - - gg_debug(GG_DEBUG_MISC, "++ gg_dcc %s (fd=%d,len=%d)", prefix, fd, size); - - for (i = 0; i < size; i++) - gg_debug(GG_DEBUG_MISC, " %.2x", ((unsigned char*) buf)[i]); - - gg_debug(GG_DEBUG_MISC, "\n"); -} -#else -#define gg_dcc_debug_data(a,b,c,d) do { } while (0) -#endif - -/* - * gg_dcc_request() - * - * wysy³a informacjê o tym, ¿e dany klient powinien siê z nami po³±czyæ. - * wykorzystywane, kiedy druga strona, której chcemy co¶ wys³aæ jest za - * maskarad±. - * - * - sess - struktura opisuj±ca sesjê GG - * - uin - numerek odbiorcy - * - * patrz gg_send_message_ctcp(). - */ -int gg_dcc_request(struct gg_session *sess, uin_t uin) -{ - return gg_send_message_ctcp(sess, GG_CLASS_CTCP, uin, "\002", 1); -} - -/* - * gg_dcc_fill_filetime() // funkcja wewnêtrzna - * - * zamienia czas w postaci unixowej na windowsowy. - * - * - unix - czas w postaci unixowej - * - filetime - czas w postaci windowsowej - */ -static void gg_dcc_fill_filetime(uint32_t ut, uint32_t *ft) -{ -#ifdef __GG_LIBGADU_HAVE_LONG_LONG - unsigned long long tmp; - - tmp = ut; - tmp += 11644473600LL; - tmp *= 10000000LL; - -#ifndef __GG_LIBGADU_BIGENDIAN - ft[0] = (uint32_t) tmp; - ft[1] = (uint32_t) (tmp >> 32); -#else - ft[0] = gg_fix32((uint32_t) (tmp >> 32)); - ft[1] = gg_fix32((uint32_t) tmp); -#endif - -#endif -} - -/* - * gg_dcc_fill_file_info() - * - * wype³nia pola struct gg_dcc niezbêdne do wys³ania pliku. - * - * - d - struktura opisuj±ca po³±czenie DCC - * - filename - nazwa pliku - * - * 0, -1. - */ -int gg_dcc_fill_file_info(struct gg_dcc *d, const char *filename) -{ - return gg_dcc_fill_file_info2(d, filename, filename); -} - -/* - * gg_dcc_fill_file_info2() - * - * wype³nia pola struct gg_dcc niezbêdne do wys³ania pliku. - * - * - d - struktura opisuj±ca po³±czenie DCC - * - filename - nazwa pliku - * - local_filename - nazwa na lokalnym systemie plików - * - * 0, -1. - */ -int gg_dcc_fill_file_info2(struct gg_dcc *d, const char *filename, const char *local_filename) -{ - struct stat st; - const char *name, *ext, *p; - unsigned char *q; - int i, j; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_dcc_fill_file_info2(%p, \"%s\", \"%s\");\n", d, filename, local_filename); - - if (!d || d->type != GG_SESSION_DCC_SEND) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info2() invalid arguments\n"); - errno = EINVAL; - return -1; - } - - if (stat(local_filename, &st) == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info2() stat() failed (%s)\n", strerror(errno)); - return -1; - } - - if ((st.st_mode & S_IFDIR)) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info2() that's a directory\n"); - errno = EINVAL; - return -1; - } - - if ((d->file_fd = open(local_filename, O_RDONLY)) == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info2() open() failed (%s)\n", strerror(errno)); - return -1; - } - - memset(&d->file_info, 0, sizeof(d->file_info)); - - if (!(st.st_mode & S_IWUSR)) - d->file_info.mode |= gg_fix32(GG_DCC_FILEATTR_READONLY); - - gg_dcc_fill_filetime(st.st_atime, d->file_info.atime); - gg_dcc_fill_filetime(st.st_mtime, d->file_info.mtime); - gg_dcc_fill_filetime(st.st_ctime, d->file_info.ctime); - - d->file_info.size = gg_fix32(st.st_size); - d->file_info.mode = gg_fix32(0x20); /* FILE_ATTRIBUTE_ARCHIVE */ - - if (!(name = strrchr(filename, '/'))) - name = filename; - else - name++; - - if (!(ext = strrchr(name, '.'))) - ext = name + strlen(name); - - for (i = 0, p = name; i < 8 && p < ext; i++, p++) - d->file_info.short_filename[i] = toupper(name[i]); - - if (i == 8 && p < ext) { - d->file_info.short_filename[6] = '~'; - d->file_info.short_filename[7] = '1'; - } - - if (strlen(ext) > 0) { - for (j = 0; *ext && j < 4; j++, p++) - d->file_info.short_filename[i + j] = toupper(ext[j]); - } - - for (q = d->file_info.short_filename; *q; q++) { - if (*q == 185) { - *q = 165; - } else if (*q == 230) { - *q = 198; - } else if (*q == 234) { - *q = 202; - } else if (*q == 179) { - *q = 163; - } else if (*q == 241) { - *q = 209; - } else if (*q == 243) { - *q = 211; - } else if (*q == 156) { - *q = 140; - } else if (*q == 159) { - *q = 143; - } else if (*q == 191) { - *q = 175; - } - } - - gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info2() short name \"%s\", dos name \"%s\"\n", name, d->file_info.short_filename); - strncpy(d->file_info.filename, name, sizeof(d->file_info.filename) - 1); - - return 0; -} - -/* - * gg_dcc_transfer() // funkcja wewnêtrzna - * - * inicjuje proces wymiany pliku z danym klientem. - * - * - ip - adres ip odbiorcy - * - port - port odbiorcy - * - my_uin - w³asny numer - * - peer_uin - numer obiorcy - * - type - rodzaj wymiany (GG_SESSION_DCC_SEND lub GG_SESSION_DCC_GET) - * - * zaalokowana struct gg_dcc lub NULL je¶li wyst±pi³ b³±d. - */ -static struct gg_dcc *gg_dcc_transfer(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin, int type) -{ - struct gg_dcc *d = NULL; - struct in_addr addr; - - addr.s_addr = ip; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_dcc_transfer(%s, %d, %ld, %ld, %s);\n", inet_ntoa(addr), port, my_uin, peer_uin, (type == GG_SESSION_DCC_SEND) ? "SEND" : "GET"); - - if (!ip || ip == INADDR_NONE || !port || !my_uin || !peer_uin) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_transfer() invalid arguments\n"); - errno = EINVAL; - return NULL; - } - - if (!(d = (void*) calloc(1, sizeof(*d)))) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_transfer() not enough memory\n"); - return NULL; - } - - d->check = GG_CHECK_WRITE; - d->state = GG_STATE_CONNECTING; - d->type = type; - d->timeout = GG_DEFAULT_TIMEOUT; - d->file_fd = -1; - d->active = 1; - d->fd = -1; - d->uin = my_uin; - d->peer_uin = peer_uin; - - if ((d->fd = gg_connect(&addr, port, 1)) == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_transfer() connection failed\n"); - free(d); - return NULL; - } - - return d; -} - -/* - * gg_dcc_get_file() - * - * inicjuje proces odbierania pliku od danego klienta, gdy ten wys³a³ do - * nas ¿±danie po³±czenia. - * - * - ip - adres ip odbiorcy - * - port - port odbiorcy - * - my_uin - w³asny numer - * - peer_uin - numer obiorcy - * - * zaalokowana struct gg_dcc lub NULL je¶li wyst±pi³ b³±d. - */ -struct gg_dcc *gg_dcc_get_file(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin) -{ - gg_debug(GG_DEBUG_MISC, "// gg_dcc_get_file() handing over to gg_dcc_transfer()\n"); - - return gg_dcc_transfer(ip, port, my_uin, peer_uin, GG_SESSION_DCC_GET); -} - -/* - * gg_dcc_send_file() - * - * inicjuje proces wysy³ania pliku do danego klienta. - * - * - ip - adres ip odbiorcy - * - port - port odbiorcy - * - my_uin - w³asny numer - * - peer_uin - numer obiorcy - * - * zaalokowana struct gg_dcc lub NULL je¶li wyst±pi³ b³±d. - */ -struct gg_dcc *gg_dcc_send_file(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin) -{ - gg_debug(GG_DEBUG_MISC, "// gg_dcc_send_file() handing over to gg_dcc_transfer()\n"); - - return gg_dcc_transfer(ip, port, my_uin, peer_uin, GG_SESSION_DCC_SEND); -} - -/* - * gg_dcc_voice_chat() - * - * próbuje nawi±zaæ po³±czenie g³osowe. - * - * - ip - adres ip odbiorcy - * - port - port odbiorcy - * - my_uin - w³asny numer - * - peer_uin - numer obiorcy - * - * zaalokowana struct gg_dcc lub NULL je¶li wyst±pi³ b³±d. - */ -struct gg_dcc *gg_dcc_voice_chat(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin) -{ - gg_debug(GG_DEBUG_MISC, "// gg_dcc_voice_chat() handing over to gg_dcc_transfer()\n"); - - return gg_dcc_transfer(ip, port, my_uin, peer_uin, GG_SESSION_DCC_VOICE); -} - -/* - * gg_dcc_set_type() - * - * po zdarzeniu GG_EVENT_DCC_CALLBACK nale¿y ustawiæ typ po³±czenia za - * pomoc± tej funkcji. - * - * - d - struktura opisuj±ca po³±czenie - * - type - typ po³±czenia (GG_SESSION_DCC_SEND lub GG_SESSION_DCC_VOICE) - */ -void gg_dcc_set_type(struct gg_dcc *d, int type) -{ - d->type = type; - d->state = (type == GG_SESSION_DCC_SEND) ? GG_STATE_SENDING_FILE_INFO : GG_STATE_SENDING_VOICE_REQUEST; -} - -/* - * gg_dcc_callback() // funkcja wewnêtrzna - * - * wywo³ywana z struct gg_dcc->callback, odpala gg_dcc_watch_fd i umieszcza - * rezultat w struct gg_dcc->event. - * - * - d - structura opisuj±ca po³±czenie - * - * 0, -1. - */ -static int gg_dcc_callback(struct gg_dcc *d) -{ - struct gg_event *e = gg_dcc_watch_fd(d); - - d->event = e; - - return (e != NULL) ? 0 : -1; -} - -/* - * gg_dcc_socket_create() - * - * tworzy gniazdo dla bezpo¶redniej komunikacji miêdzy klientami. - * - * - uin - w³asny numer - * - port - preferowany port, je¶li równy 0 lub -1, próbuje domy¶lnego - * - * zaalokowana struct gg_dcc, któr± po¼niej nale¿y zwolniæ funkcj± - * gg_dcc_free(), albo NULL je¶li wyst±pi³ b³±d. - */ -struct gg_dcc *gg_dcc_socket_create(uin_t uin, uint16_t port) -{ - struct gg_dcc *c; - struct sockaddr_in sin; - int sock, bound = 0, errno2; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_create_dcc_socket(%d, %d);\n", uin, port); - - if (!uin) { - gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() invalid arguments\n"); - errno = EINVAL; - return NULL; - } - - if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() can't create socket (%s)\n", strerror(errno)); - return NULL; - } - - if (!port) - port = GG_DEFAULT_DCC_PORT; - - while (!bound) { - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = INADDR_ANY; - sin.sin_port = htons(port); - - gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() trying port %d\n", port); - if (!bind(sock, (struct sockaddr*) &sin, sizeof(sin))) - bound = 1; - else { - if (++port == 65535) { - gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() no free port found\n"); - close(sock); - return NULL; - } - } - } - - if (listen(sock, 10)) { - gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() unable to listen (%s)\n", strerror(errno)); - errno2 = errno; - close(sock); - errno = errno2; - return NULL; - } - - gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() bound to port %d\n", port); - - if (!(c = malloc(sizeof(*c)))) { - gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() not enough memory for struct\n"); - close(sock); - return NULL; - } - memset(c, 0, sizeof(*c)); - - c->port = c->id = port; - c->fd = sock; - c->type = GG_SESSION_DCC_SOCKET; - c->uin = uin; - c->timeout = -1; - c->state = GG_STATE_LISTENING; - c->check = GG_CHECK_READ; - c->callback = gg_dcc_callback; - c->destroy = gg_dcc_free; - - return c; -} - -/* - * gg_dcc_voice_send() - * - * wysy³a ramkê danych dla rozmowy g³osowej. - * - * - d - struktura opisuj±ca po³±czenie dcc - * - buf - bufor z danymi - * - length - rozmiar ramki - * - * 0, -1. - */ -int gg_dcc_voice_send(struct gg_dcc *d, char *buf, int length) -{ - struct packet_s { - uint8_t type; - uint32_t length; - } GG_PACKED; - struct packet_s packet; - - gg_debug(GG_DEBUG_FUNCTION, "++ gg_dcc_voice_send(%p, %p, %d);\n", d, buf, length); - if (!d || !buf || length < 0 || d->type != GG_SESSION_DCC_VOICE) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_voice_send() invalid argument\n"); - errno = EINVAL; - return -1; - } - - packet.type = 0x03; /* XXX */ - packet.length = gg_fix32(length); - - if (write(d->fd, &packet, sizeof(packet)) < (signed)sizeof(packet)) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_voice_send() write() failed\n"); - return -1; - } - gg_dcc_debug_data("write", d->fd, &packet, sizeof(packet)); - - if (write(d->fd, buf, length) < length) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_voice_send() write() failed\n"); - return -1; - } - gg_dcc_debug_data("write", d->fd, buf, length); - - return 0; -} - -#define gg_read(fd, buf, size) \ -{ \ - int tmp = read(fd, buf, size); \ - \ - if (tmp < (int) size) { \ - if (tmp == -1) { \ - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() failed (errno=%d, %s)\n", errno, strerror(errno)); \ - } else if (tmp == 0) { \ - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() failed, connection broken\n"); \ - } else { \ - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() failed (%d bytes, %d needed)\n", tmp, size); \ - } \ - e->type = GG_EVENT_DCC_ERROR; \ - e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE; \ - return e; \ - } \ - gg_dcc_debug_data("read", fd, buf, size); \ -} - -#define gg_write(fd, buf, size) \ -{ \ - int tmp; \ - gg_dcc_debug_data("write", fd, buf, size); \ - tmp = write(fd, buf, size); \ - if (tmp < (int) size) { \ - if (tmp == -1) { \ - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() write() failed (errno=%d, %s)\n", errno, strerror(errno)); \ - } else { \ - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() write() failed (%d needed, %d done)\n", size, tmp); \ - } \ - e->type = GG_EVENT_DCC_ERROR; \ - e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE; \ - return e; \ - } \ -} - -/* - * gg_dcc_watch_fd() - * - * funkcja, któr± nale¿y wywo³aæ, gdy co¶ siê zmieni na gg_dcc->fd. - * - * - h - struktura zwrócona przez gg_create_dcc_socket() - * - * zaalokowana struct gg_event lub NULL, je¶li zabrak³o pamiêci na ni±. - */ -struct gg_event *gg_dcc_watch_fd(struct gg_dcc *h) -{ - struct gg_event *e; - int foo; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_dcc_watch_fd(%p);\n", h); - - if (!h || (h->type != GG_SESSION_DCC && h->type != GG_SESSION_DCC_SOCKET && h->type != GG_SESSION_DCC_SEND && h->type != GG_SESSION_DCC_GET && h->type != GG_SESSION_DCC_VOICE)) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() invalid argument\n"); - errno = EINVAL; - return NULL; - } - - if (!(e = (void*) calloc(1, sizeof(*e)))) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() not enough memory\n"); - return NULL; - } - - e->type = GG_EVENT_NONE; - - if (h->type == GG_SESSION_DCC_SOCKET) { - struct sockaddr_in sin; - struct gg_dcc *c; - int fd, sin_len = sizeof(sin), one = 1; - - if ((fd = accept(h->fd, (struct sockaddr*) &sin, &sin_len)) == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() can't accept() new connection (errno=%d, %s)\n", errno, strerror(errno)); - return e; - } - - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() new direct connection from %s:%d\n", inet_ntoa(sin.sin_addr), htons(sin.sin_port)); - -#ifdef FIONBIO - if (ioctl(fd, FIONBIO, &one) == -1) { -#else - if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) { -#endif - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() can't set nonblocking (errno=%d, %s)\n", errno, strerror(errno)); - close(fd); - e->type = GG_EVENT_DCC_ERROR; - e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE; - return e; - } - - if (!(c = (void*) calloc(1, sizeof(*c)))) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() not enough memory for client data\n"); - - free(e); - close(fd); - return NULL; - } - - c->fd = fd; - c->check = GG_CHECK_READ; - c->state = GG_STATE_READING_UIN_1; - c->type = GG_SESSION_DCC; - c->timeout = GG_DEFAULT_TIMEOUT; - c->file_fd = -1; - c->remote_addr = sin.sin_addr.s_addr; - c->remote_port = ntohs(sin.sin_port); - - e->type = GG_EVENT_DCC_NEW; - e->event.dcc_new = c; - - return e; - } else { - struct gg_dcc_tiny_packet tiny; - struct gg_dcc_small_packet small; - struct gg_dcc_big_packet big; - int size, tmp, res, res_size = sizeof(res); - unsigned int utmp; - char buf[1024], ack[] = "UDAG"; - - struct gg_dcc_file_info_packet { - struct gg_dcc_big_packet big; - struct gg_file_info file_info; - } GG_PACKED; - struct gg_dcc_file_info_packet file_info_packet; - - switch (h->state) { - case GG_STATE_READING_UIN_1: - case GG_STATE_READING_UIN_2: - { - uin_t uin; - - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_READING_UIN_%d\n", (h->state == GG_STATE_READING_UIN_1) ? 1 : 2); - - gg_read(h->fd, &uin, sizeof(uin)); - - if (h->state == GG_STATE_READING_UIN_1) { - h->state = GG_STATE_READING_UIN_2; - h->check = GG_CHECK_READ; - h->timeout = GG_DEFAULT_TIMEOUT; - h->peer_uin = gg_fix32(uin); - } else { - h->state = GG_STATE_SENDING_ACK; - h->check = GG_CHECK_WRITE; - h->timeout = GG_DEFAULT_TIMEOUT; - h->uin = gg_fix32(uin); - e->type = GG_EVENT_DCC_CLIENT_ACCEPT; - } - - return e; - } - - case GG_STATE_SENDING_ACK: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_SENDING_ACK\n"); - - gg_write(h->fd, ack, 4); - - h->state = GG_STATE_READING_TYPE; - h->check = GG_CHECK_READ; - h->timeout = GG_DEFAULT_TIMEOUT; - - return e; - - case GG_STATE_READING_TYPE: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_TYPE\n"); - - gg_read(h->fd, &small, sizeof(small)); - - small.type = gg_fix32(small.type); - - switch (small.type) { - case 0x0003: /* XXX */ - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() callback\n"); - h->type = GG_SESSION_DCC_SEND; - h->state = GG_STATE_SENDING_FILE_INFO; - h->check = GG_CHECK_WRITE; - h->timeout = GG_DEFAULT_TIMEOUT; - - e->type = GG_EVENT_DCC_CALLBACK; - - break; - - case 0x0002: /* XXX */ - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() dialin\n"); - h->type = GG_SESSION_DCC_GET; - h->state = GG_STATE_READING_REQUEST; - h->check = GG_CHECK_READ; - h->timeout = GG_DEFAULT_TIMEOUT; - h->incoming = 1; - - break; - - default: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() unknown dcc type (%.4x) from %ld\n", small.type, h->peer_uin); - e->type = GG_EVENT_DCC_ERROR; - e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE; - } - - return e; - - case GG_STATE_READING_REQUEST: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_REQUEST\n"); - - gg_read(h->fd, &small, sizeof(small)); - - small.type = gg_fix32(small.type); - - switch (small.type) { - case 0x0001: /* XXX */ - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() file transfer request\n"); - h->state = GG_STATE_READING_FILE_INFO; - h->check = GG_CHECK_READ; - h->timeout = GG_DEFAULT_TIMEOUT; - break; - - case 0x0003: /* XXX */ - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() voice chat request\n"); - h->state = GG_STATE_SENDING_VOICE_ACK; - h->check = GG_CHECK_WRITE; - h->timeout = GG_DCC_TIMEOUT_VOICE_ACK; - h->type = GG_SESSION_DCC_VOICE; - e->type = GG_EVENT_DCC_NEED_VOICE_ACK; - - break; - - default: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() unknown dcc request (%.4x) from %ld\n", small.type, h->peer_uin); - e->type = GG_EVENT_DCC_ERROR; - e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE; - } - - return e; - - case GG_STATE_READING_FILE_INFO: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_FILE_INFO\n"); - - gg_read(h->fd, &file_info_packet, sizeof(file_info_packet)); - - memcpy(&h->file_info, &file_info_packet.file_info, sizeof(h->file_info)); - - h->file_info.mode = gg_fix32(h->file_info.mode); - h->file_info.size = gg_fix32(h->file_info.size); - - h->state = GG_STATE_SENDING_FILE_ACK; - h->check = GG_CHECK_WRITE; - h->timeout = GG_DCC_TIMEOUT_FILE_ACK; - - e->type = GG_EVENT_DCC_NEED_FILE_ACK; - - return e; - - case GG_STATE_SENDING_FILE_ACK: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_SENDING_FILE_ACK\n"); - - big.type = gg_fix32(0x0006); /* XXX */ - big.dunno1 = gg_fix32(h->offset); - big.dunno2 = 0; - - gg_write(h->fd, &big, sizeof(big)); - - h->state = GG_STATE_READING_FILE_HEADER; - h->chunk_size = sizeof(big); - h->chunk_offset = 0; - if (!(h->chunk_buf = malloc(sizeof(big)))) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() out of memory\n"); - free(e); - return NULL; - } - h->check = GG_CHECK_READ; - h->timeout = GG_DEFAULT_TIMEOUT; - - return e; - - case GG_STATE_SENDING_VOICE_ACK: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_SENDING_VOICE_ACK\n"); - - tiny.type = 0x01; /* XXX */ - - gg_write(h->fd, &tiny, sizeof(tiny)); - - h->state = GG_STATE_READING_VOICE_HEADER; - h->check = GG_CHECK_READ; - h->timeout = GG_DEFAULT_TIMEOUT; - - h->offset = 0; - - return e; - - case GG_STATE_READING_FILE_HEADER: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_FILE_HEADER\n"); - - tmp = read(h->fd, h->chunk_buf + h->chunk_offset, h->chunk_size - h->chunk_offset); - - if (tmp == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() read() failed (errno=%d, %s)\n", errno, strerror(errno)); - e->type = GG_EVENT_DCC_ERROR; - e->event.dcc_error = GG_ERROR_DCC_NET; - return e; - } - - gg_dcc_debug_data("read", h->fd, h->chunk_buf + h->chunk_offset, h->chunk_size - h->chunk_offset); - - h->chunk_offset += tmp; - - if (h->chunk_offset < h->chunk_size) - return e; - - memcpy(&big, h->chunk_buf, sizeof(big)); - free(h->chunk_buf); - h->chunk_buf = NULL; - - big.type = gg_fix32(big.type); - h->chunk_size = gg_fix32(big.dunno1); - h->chunk_offset = 0; - - if (big.type == 0x0005) { /* XXX */ - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() transfer refused\n"); - e->type = GG_EVENT_DCC_ERROR; - e->event.dcc_error = GG_ERROR_DCC_REFUSED; - return e; - } - - if (h->chunk_size == 0) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() empty chunk, EOF\n"); - e->type = GG_EVENT_DCC_DONE; - return e; - } - - h->state = GG_STATE_GETTING_FILE; - h->check = GG_CHECK_READ; - h->timeout = GG_DEFAULT_TIMEOUT; - h->established = 1; - - return e; - - case GG_STATE_READING_VOICE_HEADER: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_VOICE_HEADER\n"); - - gg_read(h->fd, &tiny, sizeof(tiny)); - - switch (tiny.type) { - case 0x03: /* XXX */ - h->state = GG_STATE_READING_VOICE_SIZE; - h->check = GG_CHECK_READ; - h->timeout = GG_DEFAULT_TIMEOUT; - h->established = 1; - break; - case 0x04: /* XXX */ - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() peer breaking connection\n"); - /* XXX zwracaæ odpowiedni event */ - default: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() unknown request (%.2x)\n", tiny.type); - e->type = GG_EVENT_DCC_ERROR; - e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE; - } - - return e; - - case GG_STATE_READING_VOICE_SIZE: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_VOICE_SIZE\n"); - - gg_read(h->fd, &small, sizeof(small)); - - small.type = gg_fix32(small.type); - - if (small.type < 16 || small.type > sizeof(buf)) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() invalid voice frame size (%d)\n", small.type); - e->type = GG_EVENT_DCC_ERROR; - e->event.dcc_error = GG_ERROR_DCC_NET; - - return e; - } - - h->chunk_size = small.type; - h->chunk_offset = 0; - - if (!(h->voice_buf = malloc(h->chunk_size))) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() out of memory for voice frame\n"); - free(e); - return NULL; - } - - h->state = GG_STATE_READING_VOICE_DATA; - h->check = GG_CHECK_READ; - h->timeout = GG_DEFAULT_TIMEOUT; - - return e; - - case GG_STATE_READING_VOICE_DATA: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_VOICE_DATA\n"); - - tmp = read(h->fd, h->voice_buf + h->chunk_offset, h->chunk_size - h->chunk_offset); - if (tmp < 1) { - if (tmp == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() failed (errno=%d, %s)\n", errno, strerror(errno)); - } else { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() failed, connection broken\n"); - } - e->type = GG_EVENT_DCC_ERROR; - e->event.dcc_error = GG_ERROR_DCC_NET; - return e; - } - - gg_dcc_debug_data("read", h->fd, h->voice_buf + h->chunk_offset, tmp); - - h->chunk_offset += tmp; - - if (h->chunk_offset >= h->chunk_size) { - e->type = GG_EVENT_DCC_VOICE_DATA; - e->event.dcc_voice_data.data = h->voice_buf; - e->event.dcc_voice_data.length = h->chunk_size; - h->state = GG_STATE_READING_VOICE_HEADER; - h->voice_buf = NULL; - } - - h->check = GG_CHECK_READ; - h->timeout = GG_DEFAULT_TIMEOUT; - - return e; - - case GG_STATE_CONNECTING: - { - uin_t uins[2]; - - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_CONNECTING\n"); - - res = 0; - if ((foo = getsockopt(h->fd, SOL_SOCKET, SO_ERROR, &res, &res_size)) || res) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() connection failed (fd=%d,errno=%d(%s),foo=%d,res=%d(%s))\n", h->fd, errno, strerror(errno), foo, res, strerror(res)); - e->type = GG_EVENT_DCC_ERROR; - e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE; - return e; - } - - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() connected, sending uins\n"); - - uins[0] = gg_fix32(h->uin); - uins[1] = gg_fix32(h->peer_uin); - - gg_write(h->fd, uins, sizeof(uins)); - - h->state = GG_STATE_READING_ACK; - h->check = GG_CHECK_READ; - h->timeout = GG_DEFAULT_TIMEOUT; - - return e; - } - - case GG_STATE_READING_ACK: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_ACK\n"); - - gg_read(h->fd, buf, 4); - - if (strncmp(buf, ack, 4)) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() did't get ack\n"); - - e->type = GG_EVENT_DCC_ERROR; - e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE; - return e; - } - - h->check = GG_CHECK_WRITE; - h->timeout = GG_DEFAULT_TIMEOUT; - h->state = GG_STATE_SENDING_REQUEST; - - return e; - - case GG_STATE_SENDING_VOICE_REQUEST: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_SENDING_VOICE_REQUEST\n"); - - small.type = gg_fix32(0x0003); - - gg_write(h->fd, &small, sizeof(small)); - - h->state = GG_STATE_READING_VOICE_ACK; - h->check = GG_CHECK_READ; - h->timeout = GG_DEFAULT_TIMEOUT; - - return e; - - case GG_STATE_SENDING_REQUEST: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_SENDING_REQUEST\n"); - - small.type = (h->type == GG_SESSION_DCC_GET) ? gg_fix32(0x0003) : gg_fix32(0x0002); /* XXX */ - - gg_write(h->fd, &small, sizeof(small)); - - switch (h->type) { - case GG_SESSION_DCC_GET: - h->state = GG_STATE_READING_REQUEST; - h->check = GG_CHECK_READ; - h->timeout = GG_DEFAULT_TIMEOUT; - break; - - case GG_SESSION_DCC_SEND: - h->state = GG_STATE_SENDING_FILE_INFO; - h->check = GG_CHECK_WRITE; - h->timeout = GG_DEFAULT_TIMEOUT; - - if (h->file_fd == -1) - e->type = GG_EVENT_DCC_NEED_FILE_INFO; - break; - - case GG_SESSION_DCC_VOICE: - h->state = GG_STATE_SENDING_VOICE_REQUEST; - h->check = GG_CHECK_WRITE; - h->timeout = GG_DEFAULT_TIMEOUT; - break; - } - - return e; - - case GG_STATE_SENDING_FILE_INFO: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_SENDING_FILE_INFO\n"); - - if (h->file_fd == -1) { - e->type = GG_EVENT_DCC_NEED_FILE_INFO; - return e; - } - - small.type = gg_fix32(0x0001); /* XXX */ - - gg_write(h->fd, &small, sizeof(small)); - - file_info_packet.big.type = gg_fix32(0x0003); /* XXX */ - file_info_packet.big.dunno1 = 0; - file_info_packet.big.dunno2 = 0; - - memcpy(&file_info_packet.file_info, &h->file_info, sizeof(h->file_info)); - - /* zostaj± teraz u nas, wiêc odwracamy z powrotem */ - h->file_info.size = gg_fix32(h->file_info.size); - h->file_info.mode = gg_fix32(h->file_info.mode); - - gg_write(h->fd, &file_info_packet, sizeof(file_info_packet)); - - h->state = GG_STATE_READING_FILE_ACK; - h->check = GG_CHECK_READ; - h->timeout = GG_DCC_TIMEOUT_FILE_ACK; - - return e; - - case GG_STATE_READING_FILE_ACK: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_FILE_ACK\n"); - - gg_read(h->fd, &big, sizeof(big)); - - /* XXX sprawdzaæ wynik */ - h->offset = gg_fix32(big.dunno1); - - h->state = GG_STATE_SENDING_FILE_HEADER; - h->check = GG_CHECK_WRITE; - h->timeout = GG_DEFAULT_TIMEOUT; - - e->type = GG_EVENT_DCC_ACK; - - return e; - - case GG_STATE_READING_VOICE_ACK: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_VOICE_ACK\n"); - - gg_read(h->fd, &tiny, sizeof(tiny)); - - if (tiny.type != 0x01) { - gg_debug(GG_DEBUG_MISC, "// invalid reply (%.2x), connection refused\n", tiny.type); - e->type = GG_EVENT_DCC_ERROR; - e->event.dcc_error = GG_ERROR_DCC_REFUSED; - return e; - } - - h->state = GG_STATE_READING_VOICE_HEADER; - h->check = GG_CHECK_READ; - h->timeout = GG_DEFAULT_TIMEOUT; - - e->type = GG_EVENT_DCC_ACK; - - return e; - - case GG_STATE_SENDING_FILE_HEADER: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_SENDING_FILE_HEADER\n"); - - h->chunk_offset = 0; - - if ((h->chunk_size = h->file_info.size - h->offset) > 4096) { - h->chunk_size = 4096; - big.type = gg_fix32(0x0003); /* XXX */ - } else - big.type = gg_fix32(0x0002); /* XXX */ - - big.dunno1 = gg_fix32(h->chunk_size); - big.dunno2 = 0; - - gg_write(h->fd, &big, sizeof(big)); - - h->state = GG_STATE_SENDING_FILE; - h->check = GG_CHECK_WRITE; - h->timeout = GG_DEFAULT_TIMEOUT; - h->established = 1; - - return e; - - case GG_STATE_SENDING_FILE: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_SENDING_FILE\n"); - - if ((utmp = h->chunk_size - h->chunk_offset) > sizeof(buf)) - utmp = sizeof(buf); - - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() offset=%d, size=%d\n", h->offset, h->file_info.size); - - /* koniec pliku? */ - if (h->file_info.size == 0) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() reached eof on empty file\n"); - e->type = GG_EVENT_DCC_DONE; - - return e; - } - - lseek(h->file_fd, h->offset, SEEK_SET); - - size = read(h->file_fd, buf, utmp); - - /* b³±d */ - if (size == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() failed. (errno=%d, %s)\n", errno, strerror(errno)); - - e->type = GG_EVENT_DCC_ERROR; - e->event.dcc_error = GG_ERROR_DCC_FILE; - - return e; - } - - /* koniec pliku? */ - if (size == 0) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() reached eof\n"); - e->type = GG_EVENT_DCC_ERROR; - e->event.dcc_error = GG_ERROR_DCC_EOF; - - return e; - } - - /* je¶li wczytali¶my wiêcej, utnijmy. */ - if (h->offset + size > h->file_info.size) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() too much (read=%d, ofs=%d, size=%d)\n", size, h->offset, h->file_info.size); - size = h->file_info.size - h->offset; - - if (size < 1) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() reached EOF after cutting\n"); - e->type = GG_EVENT_DCC_DONE; - return e; - } - } - - tmp = write(h->fd, buf, size); - - if (tmp == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() write() failed (%s)\n", strerror(errno)); - e->type = GG_EVENT_DCC_ERROR; - e->event.dcc_error = GG_ERROR_DCC_NET; - return e; - } - - h->offset += size; - - if (h->offset >= h->file_info.size) { - e->type = GG_EVENT_DCC_DONE; - return e; - } - - h->chunk_offset += size; - - if (h->chunk_offset >= h->chunk_size) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() chunk finished\n"); - h->state = GG_STATE_SENDING_FILE_HEADER; - h->timeout = GG_DEFAULT_TIMEOUT; - } else { - h->state = GG_STATE_SENDING_FILE; - h->timeout = GG_DCC_TIMEOUT_SEND; - } - - h->check = GG_CHECK_WRITE; - - return e; - - case GG_STATE_GETTING_FILE: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_GETTING_FILE\n"); - - if ((utmp = h->chunk_size - h->chunk_offset) > sizeof(buf)) - utmp = sizeof(buf); - - size = read(h->fd, buf, utmp); - - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() ofs=%d, size=%d, read()=%d\n", h->offset, h->file_info.size, size); - - /* b³±d */ - if (size == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() failed. (errno=%d, %s)\n", errno, strerror(errno)); - - e->type = GG_EVENT_DCC_ERROR; - e->event.dcc_error = GG_ERROR_DCC_NET; - - return e; - } - - /* koniec? */ - if (size == 0) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() reached eof\n"); - e->type = GG_EVENT_DCC_ERROR; - e->event.dcc_error = GG_ERROR_DCC_EOF; - - return e; - } - - tmp = write(h->file_fd, buf, size); - - if (tmp == -1 || tmp < size) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() write() failed (%d:fd=%d:res=%d:%s)\n", tmp, h->file_fd, size, strerror(errno)); - e->type = GG_EVENT_DCC_ERROR; - e->event.dcc_error = GG_ERROR_DCC_NET; - return e; - } - - h->offset += size; - - if (h->offset >= h->file_info.size) { - e->type = GG_EVENT_DCC_DONE; - return e; - } - - h->chunk_offset += size; - - if (h->chunk_offset >= h->chunk_size) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() chunk finished\n"); - h->state = GG_STATE_READING_FILE_HEADER; - h->timeout = GG_DEFAULT_TIMEOUT; - h->chunk_offset = 0; - h->chunk_size = sizeof(big); - if (!(h->chunk_buf = malloc(sizeof(big)))) { - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() out of memory\n"); - free(e); - return NULL; - } - } else { - h->state = GG_STATE_GETTING_FILE; - h->timeout = GG_DCC_TIMEOUT_GET; - } - - h->check = GG_CHECK_READ; - - return e; - - default: - gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_???\n"); - e->type = GG_EVENT_DCC_ERROR; - e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE; - - return e; - } - } - - return e; -} - -#undef gg_read -#undef gg_write - -/* - * gg_dcc_free() - * - * zwalnia pamiêæ po strukturze po³±czenia dcc. - * - * - d - zwalniana struktura - */ -void gg_dcc_free(struct gg_dcc *d) -{ - gg_debug(GG_DEBUG_FUNCTION, "** gg_dcc_free(%p);\n", d); - - if (!d) - return; - - if (d->fd != -1) - close(d->fd); - - if (d->chunk_buf) { - free(d->chunk_buf); - d->chunk_buf = NULL; - } - - free(d); -} - -/* - * Local variables: - * c-indentation-style: k&r - * c-basic-offset: 8 - * indent-tabs-mode: notnil - * End: - * - * vim: shiftwidth=8: - */ diff --git a/kopete/protocols/gadu/libgadu/events.c b/kopete/protocols/gadu/libgadu/events.c deleted file mode 100644 index 1bf67690..00000000 --- a/kopete/protocols/gadu/libgadu/events.c +++ /dev/null @@ -1,1580 +0,0 @@ -/* $Id$ */ - -/* - * (C) Copyright 2001-2006 Wojtek Kaniewski <wojtekka@irc.pl> - * Robert J. Wo�ny <speedy@ziew.org> - * Arkadiusz Mi�kiewicz <arekm@pld-linux.org> - * Adam Wysocki <gophi@ekg.chmurka.net> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License Version - * 2.1 as published by the Free Software Foundation. - * - * 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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. - */ - -#include <sys/types.h> -#include <sys/wait.h> -#include <sys/ioctl.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> - -#include "libgadu-config.h" - -#include <errno.h> -#ifdef __GG_LIBGADU_HAVE_PTHREAD -# include <pthread.h> -#endif -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <time.h> -#include <unistd.h> -#ifdef __GG_LIBGADU_HAVE_OPENSSL -# include <openssl/err.h> -# include <openssl/x509.h> -#endif - -#include "compat.h" -#include "libgadu.h" - -/* - * gg_event_free() - * - * zwalnia pami�� zajmowan� przez informacj� o zdarzeniu. - * - * - e - wska�nik do informacji o zdarzeniu - */ -void gg_event_free(struct gg_event *e) -{ - gg_debug(GG_DEBUG_FUNCTION, "** gg_event_free(%p);\n", e); - - if (!e) - return; - - switch (e->type) { - case GG_EVENT_MSG: - free(e->event.msg.message); - free(e->event.msg.formats); - free(e->event.msg.recipients); - break; - - case GG_EVENT_NOTIFY: - free(e->event.notify); - break; - - case GG_EVENT_NOTIFY60: - { - int i; - - for (i = 0; e->event.notify60[i].uin; i++) - free(e->event.notify60[i].descr); - - free(e->event.notify60); - - break; - } - - case GG_EVENT_STATUS60: - free(e->event.status60.descr); - break; - - case GG_EVENT_STATUS: - free(e->event.status.descr); - break; - - case GG_EVENT_NOTIFY_DESCR: - free(e->event.notify_descr.notify); - free(e->event.notify_descr.descr); - break; - - case GG_EVENT_DCC_VOICE_DATA: - free(e->event.dcc_voice_data.data); - break; - - case GG_EVENT_PUBDIR50_SEARCH_REPLY: - case GG_EVENT_PUBDIR50_READ: - case GG_EVENT_PUBDIR50_WRITE: - gg_pubdir50_free(e->event.pubdir50); - break; - - case GG_EVENT_USERLIST: - free(e->event.userlist.reply); - break; - - case GG_EVENT_IMAGE_REPLY: - free(e->event.image_reply.filename); - free(e->event.image_reply.image); - break; - } - - free(e); -} - -/* - * gg_image_queue_remove() - * - * usuwa z kolejki dany wpis. - * - * - s - sesja - * - q - kolejka - * - freeq - czy zwolni� kolejk� - * - * 0/-1 - */ -int gg_image_queue_remove(struct gg_session *s, struct gg_image_queue *q, int freeq) -{ - if (!s || !q) { - errno = EFAULT; - return -1; - } - - if (s->images == q) - s->images = q->next; - else { - struct gg_image_queue *qq; - - for (qq = s->images; qq; qq = qq->next) { - if (qq->next == q) { - qq->next = q->next; - break; - } - } - } - - if (freeq) { - free(q->image); - free(q->filename); - free(q); - } - - return 0; -} - -/* - * gg_image_queue_parse() // funkcja wewn�trzna - * - * parsuje przychodz�cy pakiet z obrazkiem. - * - * - e - opis zdarzenia - * - - */ -static void gg_image_queue_parse(struct gg_event *e, char *p, unsigned int len, struct gg_session *sess, uin_t sender) -{ - struct gg_msg_image_reply *i = (void*) p; - struct gg_image_queue *q, *qq; - - if (!p || !sess || !e) { - errno = EFAULT; - return; - } - - /* znajd� dany obrazek w kolejce danej sesji */ - - for (qq = sess->images, q = NULL; qq; qq = qq->next) { - if (sender == qq->sender && i->size == qq->size && i->crc32 == qq->crc32) { - q = qq; - break; - } - } - - if (!q) { - gg_debug(GG_DEBUG_MISC, "// gg_image_queue_parse() unknown image from %d, size=%d, crc32=%.8x\n", sender, i->size, i->crc32); - return; - } - - if (p[0] == 0x05) { - int i, ok = 0; - - q->done = 0; - - len -= sizeof(struct gg_msg_image_reply); - p += sizeof(struct gg_msg_image_reply); - - /* sprawd�, czy mamy tekst zako�czony \0 */ - - for (i = 0; i < len; i++) { - if (!p[i]) { - ok = 1; - break; - } - } - - if (!ok) { - gg_debug(GG_DEBUG_MISC, "// gg_image_queue_parse() malformed packet from %d, unlimited filename\n", sender); - return; - } - - if (!(q->filename = strdup(p))) { - gg_debug(GG_DEBUG_MISC, "// gg_image_queue_parse() not enough memory for filename\n"); - return; - } - - len -= strlen(p) + 1; - p += strlen(p) + 1; - } else { - len -= sizeof(struct gg_msg_image_reply); - p += sizeof(struct gg_msg_image_reply); - } - - if (q->done + len > q->size) - len = q->size - q->done; - - memcpy(q->image + q->done, p, len); - q->done += len; - - /* je�li sko�czono odbiera� obrazek, wygeneruj zdarzenie */ - - if (q->done >= q->size) { - e->type = GG_EVENT_IMAGE_REPLY; - e->event.image_reply.sender = sender; - e->event.image_reply.size = q->size; - e->event.image_reply.crc32 = q->crc32; - e->event.image_reply.filename = q->filename; - e->event.image_reply.image = q->image; - - gg_image_queue_remove(sess, q, 0); - - free(q); - } -} - -/* - * gg_handle_recv_msg() // funkcja wewn�trzna - * - * obs�uguje pakiet z przychodz�c� wiadomo�ci�, rozbijaj�c go na dodatkowe - * struktury (konferencje, kolorki) w razie potrzeby. - * - * - h - nag��wek pakietu - * - e - opis zdarzenia - * - * 0, -1. - */ -static int gg_handle_recv_msg(struct gg_header *h, struct gg_event *e, struct gg_session *sess) -{ - struct gg_recv_msg *r = (struct gg_recv_msg*) ((char*) h + sizeof(struct gg_header)); - char *p, *packet_end = (char*) r + h->length; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_handle_recv_msg(%p, %p);\n", h, e); - - if (!r->seq && !r->msgclass) { - gg_debug(GG_DEBUG_MISC, "// gg_handle_recv_msg() oops, silently ignoring the bait\n"); - e->type = GG_EVENT_NONE; - return 0; - } - - for (p = (char*) r + sizeof(*r); *p; p++) { - if (*p == 0x02 && p == packet_end - 1) { - gg_debug(GG_DEBUG_MISC, "// gg_handle_recv_msg() received ctcp packet\n"); - break; - } - if (p >= packet_end) { - gg_debug(GG_DEBUG_MISC, "// gg_handle_recv_msg() malformed packet, message out of bounds (0)\n"); - goto malformed; - } - } - - p++; - - /* przeanalizuj dodatkowe opcje */ - while (p < packet_end) { - switch (*p) { - case 0x01: /* konferencja */ - { - struct gg_msg_recipients *m = (void*) p; - uint32_t i, count; - - p += sizeof(*m); - - if (p > packet_end) { - gg_debug(GG_DEBUG_MISC, "// gg_handle_recv_msg() packet out of bounds (1)\n"); - goto malformed; - } - - count = gg_fix32(m->count); - - if (p + count * sizeof(uin_t) > packet_end || p + count * sizeof(uin_t) < p || count > 0xffff) { - gg_debug(GG_DEBUG_MISC, "// gg_handle_recv_msg() packet out of bounds (1.5)\n"); - goto malformed; - } - - if (!(e->event.msg.recipients = (void*) malloc(count * sizeof(uin_t)))) { - gg_debug(GG_DEBUG_MISC, "// gg_handle_recv_msg() not enough memory for recipients data\n"); - goto fail; - } - - for (i = 0; i < count; i++, p += sizeof(uint32_t)) { - uint32_t u; - memcpy(&u, p, sizeof(uint32_t)); - e->event.msg.recipients[i] = gg_fix32(u); - } - - e->event.msg.recipients_count = count; - - break; - } - - case 0x02: /* richtext */ - { - uint16_t len; - char *buf; - - if (p + 3 > packet_end) { - gg_debug(GG_DEBUG_MISC, "// gg_handle_recv_msg() packet out of bounds (2)\n"); - goto malformed; - } - - memcpy(&len, p + 1, sizeof(uint16_t)); - len = gg_fix16(len); - - if (!(buf = malloc(len))) { - gg_debug(GG_DEBUG_MISC, "// gg_handle_recv_msg() not enough memory for richtext data\n"); - goto fail; - } - - p += 3; - - if (p + len > packet_end) { - gg_debug(GG_DEBUG_MISC, "// gg_handle_recv_msg() packet out of bounds (3)\n"); - free(buf); - goto malformed; - } - - memcpy(buf, p, len); - - e->event.msg.formats = buf; - e->event.msg.formats_length = len; - - p += len; - - break; - } - - case 0x04: /* image_request */ - { - struct gg_msg_image_request *i = (void*) p; - - if (p + sizeof(*i) > packet_end) { - gg_debug(GG_DEBUG_MISC, "// gg_handle_recv_msg() packet out of bounds (3)\n"); - goto malformed; - } - - e->event.image_request.sender = gg_fix32(r->sender); - e->event.image_request.size = gg_fix32(i->size); - e->event.image_request.crc32 = gg_fix32(i->crc32); - - e->type = GG_EVENT_IMAGE_REQUEST; - - return 0; - } - - case 0x05: /* image_reply */ - case 0x06: - { - struct gg_msg_image_reply *rep = (void*) p; - - if (p + sizeof(struct gg_msg_image_reply) == packet_end) { - - /* pusta odpowied� - klient po drugiej stronie nie ma ��danego obrazka */ - - e->type = GG_EVENT_IMAGE_REPLY; - e->event.image_reply.sender = gg_fix32(r->sender); - e->event.image_reply.size = 0; - e->event.image_reply.crc32 = gg_fix32(rep->crc32); - e->event.image_reply.filename = NULL; - e->event.image_reply.image = NULL; - return 0; - - } else if (p + sizeof(struct gg_msg_image_reply) + 1 > packet_end) { - - gg_debug(GG_DEBUG_MISC, "// gg_handle_recv_msg() packet out of bounds (4)\n"); - goto malformed; - } - - rep->size = gg_fix32(rep->size); - rep->crc32 = gg_fix32(rep->crc32); - gg_image_queue_parse(e, p, (unsigned int)(packet_end - p), sess, gg_fix32(r->sender)); - - return 0; - } - - default: - { - gg_debug(GG_DEBUG_MISC, "// gg_handle_recv_msg() unknown payload 0x%.2x\n", *p); - p = packet_end; - } - } - } - - e->type = GG_EVENT_MSG; - e->event.msg.msgclass = gg_fix32(r->msgclass); - e->event.msg.sender = gg_fix32(r->sender); - e->event.msg.time = gg_fix32(r->time); - e->event.msg.message = strdup((char*) r + sizeof(*r)); - - return 0; - -malformed: - e->type = GG_EVENT_NONE; - - free(e->event.msg.recipients); - free(e->event.msg.formats); - - return 0; - -fail: - free(e->event.msg.recipients); - free(e->event.msg.formats); - return -1; -} - -/* - * gg_watch_fd_connected() // funkcja wewn�trzna - * - * patrzy na gniazdo, odbiera pakiet i wype�nia struktur� zdarzenia. - * - * - sess - struktura opisuj�ca sesj� - * - e - opis zdarzenia - * - * 0, -1. - */ -static int gg_watch_fd_connected(struct gg_session *sess, struct gg_event *e) -{ - struct gg_header *h = NULL; - char *p; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_watch_fd_connected(%p, %p);\n", sess, e); - - if (!sess) { - errno = EFAULT; - return -1; - } - - if (!(h = gg_recv_packet(sess))) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() gg_recv_packet failed (errno=%d, %s)\n", errno, strerror(errno)); - goto fail; - } - - p = (char*) h + sizeof(struct gg_header); - - switch (h->type) { - case GG_RECV_MSG: - { - if (h->length >= sizeof(struct gg_recv_msg)) - if (gg_handle_recv_msg(h, e, sess)) - goto fail; - - break; - } - - case GG_NOTIFY_REPLY: - { - struct gg_notify_reply *n = (void*) p; - unsigned int count, i; - char *tmp; - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() received a notify reply\n"); - - if (h->length < sizeof(*n)) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() incomplete packet\n"); - errno = EINVAL; - goto fail; - } - - if (gg_fix32(n->status) == GG_STATUS_BUSY_DESCR || gg_fix32(n->status) == GG_STATUS_NOT_AVAIL_DESCR || gg_fix32(n->status) == GG_STATUS_AVAIL_DESCR) { - e->type = GG_EVENT_NOTIFY_DESCR; - - if (!(e->event.notify_descr.notify = (void*) malloc(sizeof(*n) * 2))) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() not enough memory for notify data\n"); - goto fail; - } - e->event.notify_descr.notify[1].uin = 0; - memcpy(e->event.notify_descr.notify, p, sizeof(*n)); - e->event.notify_descr.notify[0].uin = gg_fix32(e->event.notify_descr.notify[0].uin); - e->event.notify_descr.notify[0].status = gg_fix32(e->event.notify_descr.notify[0].status); - e->event.notify_descr.notify[0].remote_port = gg_fix16(e->event.notify_descr.notify[0].remote_port); - - count = h->length - sizeof(*n); - if (!(tmp = malloc(count + 1))) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() not enough memory for notify data\n"); - goto fail; - } - memcpy(tmp, p + sizeof(*n), count); - tmp[count] = 0; - e->event.notify_descr.descr = tmp; - - } else { - e->type = GG_EVENT_NOTIFY; - - if (!(e->event.notify = (void*) malloc(h->length + 2 * sizeof(*n)))) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() not enough memory for notify data\n"); - goto fail; - } - - memcpy(e->event.notify, p, h->length); - count = h->length / sizeof(*n); - e->event.notify[count].uin = 0; - - for (i = 0; i < count; i++) { - e->event.notify[i].uin = gg_fix32(e->event.notify[i].uin); - e->event.notify[i].status = gg_fix32(e->event.notify[i].status); - e->event.notify[i].remote_port = gg_fix16(e->event.notify[i].remote_port); - } - } - - break; - } - - case GG_STATUS: - { - struct gg_status *s = (void*) p; - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() received a status change\n"); - - if (h->length >= sizeof(*s)) { - e->type = GG_EVENT_STATUS; - memcpy(&e->event.status, p, sizeof(*s)); - e->event.status.uin = gg_fix32(e->event.status.uin); - e->event.status.status = gg_fix32(e->event.status.status); - if (h->length > sizeof(*s)) { - int len = h->length - sizeof(*s); - char *buf = malloc(len + 1); - if (buf) { - memcpy(buf, p + sizeof(*s), len); - buf[len] = 0; - } - e->event.status.descr = buf; - } else - e->event.status.descr = NULL; - } - - break; - } - - case GG_NOTIFY_REPLY60: - { - struct gg_notify_reply60 *n = (void*) p; - unsigned int length = h->length, i = 0; - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() received a notify reply\n"); - - e->type = GG_EVENT_NOTIFY60; - e->event.notify60 = malloc(sizeof(*e->event.notify60)); - - if (!e->event.notify60) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() not enough memory for notify data\n"); - goto fail; - } - - e->event.notify60[0].uin = 0; - - while (length >= sizeof(struct gg_notify_reply60)) { - uin_t uin = gg_fix32(n->uin); - char *tmp; - - e->event.notify60[i].uin = uin & 0x00ffffff; - e->event.notify60[i].status = n->status; - e->event.notify60[i].remote_ip = n->remote_ip; - e->event.notify60[i].remote_port = gg_fix16(n->remote_port); - e->event.notify60[i].version = n->version; - e->event.notify60[i].image_size = n->image_size; - e->event.notify60[i].descr = NULL; - e->event.notify60[i].time = 0; - - if (uin & 0x40000000) - e->event.notify60[i].version |= GG_HAS_AUDIO_MASK; - if (uin & 0x08000000) - e->event.notify60[i].version |= GG_ERA_OMNIX_MASK; - - if (GG_S_D(n->status)) { - unsigned char descr_len = *((char*) n + sizeof(struct gg_notify_reply60)); - - if (descr_len < length) { - if (!(e->event.notify60[i].descr = malloc(descr_len + 1))) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() not enough memory for notify data\n"); - goto fail; - } - - memcpy(e->event.notify60[i].descr, (char*) n + sizeof(struct gg_notify_reply60) + 1, descr_len); - e->event.notify60[i].descr[descr_len] = 0; - - /* XXX czas */ - } - - length -= sizeof(struct gg_notify_reply60) + descr_len + 1; - n = (void*) ((char*) n + sizeof(struct gg_notify_reply60) + descr_len + 1); - } else { - length -= sizeof(struct gg_notify_reply60); - n = (void*) ((char*) n + sizeof(struct gg_notify_reply60)); - } - - if (!(tmp = realloc(e->event.notify60, (i + 2) * sizeof(*e->event.notify60)))) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() not enough memory for notify data\n"); - free(e->event.notify60); - goto fail; - } - - e->event.notify60 = (void*) tmp; - e->event.notify60[++i].uin = 0; - } - - break; - } - - case GG_STATUS60: - { - struct gg_status60 *s = (void*) p; - uint32_t uin; - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() received a status change\n"); - - if (h->length < sizeof(*s)) - break; - - uin = gg_fix32(s->uin); - - e->type = GG_EVENT_STATUS60; - e->event.status60.uin = uin & 0x00ffffff; - e->event.status60.status = s->status; - e->event.status60.remote_ip = s->remote_ip; - e->event.status60.remote_port = gg_fix16(s->remote_port); - e->event.status60.version = s->version; - e->event.status60.image_size = s->image_size; - e->event.status60.descr = NULL; - e->event.status60.time = 0; - - if (uin & 0x40000000) - e->event.status60.version |= GG_HAS_AUDIO_MASK; - if (uin & 0x08000000) - e->event.status60.version |= GG_ERA_OMNIX_MASK; - - if (h->length > sizeof(*s)) { - int len = h->length - sizeof(*s); - char *buf = malloc(len + 1); - - if (buf) { - memcpy(buf, (char*) p + sizeof(*s), len); - buf[len] = 0; - } - - e->event.status60.descr = buf; - - if (len > 4 && p[h->length - 5] == 0) { - uint32_t t; - memcpy(&t, p + h->length - 4, sizeof(uint32_t)); - e->event.status60.time = gg_fix32(t); - } - } - - break; - } - - case GG_SEND_MSG_ACK: - { - struct gg_send_msg_ack *s = (void*) p; - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() received a message ack\n"); - - if (h->length < sizeof(*s)) - break; - - e->type = GG_EVENT_ACK; - e->event.ack.status = gg_fix32(s->status); - e->event.ack.recipient = gg_fix32(s->recipient); - e->event.ack.seq = gg_fix32(s->seq); - - break; - } - - case GG_PONG: - { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() received a pong\n"); - - e->type = GG_EVENT_PONG; - sess->last_pong = time(NULL); - - break; - } - - case GG_DISCONNECTING: - { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() received disconnection warning\n"); - e->type = GG_EVENT_DISCONNECT; - break; - } - - case GG_PUBDIR50_REPLY: - { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() received pubdir/search reply\n"); - if (gg_pubdir50_handle_reply(e, p, h->length) == -1) - goto fail; - break; - } - - case GG_USERLIST_REPLY: - { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() received userlist reply\n"); - - if (h->length < 1) - break; - - /* je�li odpowied� na eksport, wywo�aj zdarzenie tylko - * gdy otrzymano wszystkie odpowiedzi */ - if (p[0] == GG_USERLIST_PUT_REPLY || p[0] == GG_USERLIST_PUT_MORE_REPLY) { - if (--sess->userlist_blocks) - break; - - p[0] = GG_USERLIST_PUT_REPLY; - } - - if (h->length > 1) { - char *tmp; - unsigned int len = (sess->userlist_reply) ? strlen(sess->userlist_reply) : 0; - - gg_debug(GG_DEBUG_MISC, "userlist_reply=%p, len=%d\n", sess->userlist_reply, len); - - if (!(tmp = realloc(sess->userlist_reply, len + h->length))) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() not enough memory for userlist reply\n"); - free(sess->userlist_reply); - sess->userlist_reply = NULL; - goto fail; - } - - sess->userlist_reply = tmp; - sess->userlist_reply[len + h->length - 1] = 0; - memcpy(sess->userlist_reply + len, p + 1, h->length - 1); - } - - if (p[0] == GG_USERLIST_GET_MORE_REPLY) - break; - - e->type = GG_EVENT_USERLIST; - e->event.userlist.type = p[0]; - e->event.userlist.reply = sess->userlist_reply; - sess->userlist_reply = NULL; - - break; - } - - default: - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd_connected() received unknown packet 0x%.2x\n", h->type); - } - - free(h); - return 0; - -fail: - free(h); - return -1; -} - -/* - * gg_watch_fd() - * - * funkcja, kt�r� nale�y wywo�a�, gdy co� si� stanie z obserwowanym - * deskryptorem. zwraca klientowi informacj� o tym, co si� dzieje. - * - * - sess - opis sesji - * - * wska�nik do struktury gg_event, kt�r� trzeba zwolni� p��niej - * za pomoc� gg_event_free(). jesli rodzaj zdarzenia jest r�wny - * GG_EVENT_NONE, nale�y je zignorowa�. je�li zwr�ci�o NULL, - * sta�o si� co� niedobrego -- albo zabrak�o pami�ci albo zerwa�o - * po��czenie. - */ -struct gg_event *gg_watch_fd(struct gg_session *sess) -{ - struct gg_event *e; - int res = 0; - int port = 0; - int errno2 = 0; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_watch_fd(%p);\n", sess); - - if (!sess) { - errno = EFAULT; - return NULL; - } - - if (!(e = (void*) calloc(1, sizeof(*e)))) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() not enough memory for event data\n"); - return NULL; - } - - e->type = GG_EVENT_NONE; - - switch (sess->state) { - case GG_STATE_RESOLVING: - { - struct in_addr addr; - int failed = 0; - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_RESOLVING\n"); - - if (read(sess->fd, &addr, sizeof(addr)) < (signed)sizeof(addr) || addr.s_addr == INADDR_NONE) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() resolving failed\n"); - failed = 1; - errno2 = errno; - } - - close(sess->fd); - sess->fd = -1; - -#ifndef __GG_LIBGADU_HAVE_PTHREAD - waitpid(sess->pid, NULL, 0); - sess->pid = -1; -#else - if (sess->resolver) { - pthread_cancel(*((pthread_t*) sess->resolver)); - free(sess->resolver); - sess->resolver = NULL; - } -#endif - - if (failed) { - errno = errno2; - goto fail_resolving; - } - - /* je�li jeste�my w resolverze i mamy ustawiony port - * proxy, znaczy, �e resolvowali�my proxy. zatem - * wpiszmy jego adres. */ - if (sess->proxy_port) - sess->proxy_addr = addr.s_addr; - - /* zapiszmy sobie adres huba i adres serwera (do - * bezpo�redniego po��czenia, je�li hub le�y) - * z resolvera. */ - if (sess->proxy_addr && sess->proxy_port) - port = sess->proxy_port; - else { - sess->server_addr = sess->hub_addr = addr.s_addr; - port = GG_APPMSG_PORT; - } - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() resolved, connecting to %s:%d\n", inet_ntoa(addr), port); - - /* ��czymy si� albo z hubem, albo z proxy, zale�nie - * od tego, co resolvowali�my. */ - if ((sess->fd = gg_connect(&addr, port, sess->async)) == -1) { - /* je�li w trybie asynchronicznym gg_connect() - * zwr�ci b��d, nie ma sensu pr�bowa� dalej. */ - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s), critical\n", errno, strerror(errno)); - goto fail_connecting; - } - - /* je�li podano serwer i ��czmy si� przez proxy, - * jest to bezpo�rednie po��czenie, inaczej jest - * do huba. */ - sess->state = (sess->proxy_addr && sess->proxy_port && sess->server_addr) ? GG_STATE_CONNECTING_GG : GG_STATE_CONNECTING_HUB; - sess->check = GG_CHECK_WRITE; - sess->timeout = GG_DEFAULT_TIMEOUT; - - break; - } - - case GG_STATE_CONNECTING_HUB: - { - char buf[1024], *client, *auth; - int res = 0, res_size = sizeof(res); - const char *host, *appmsg; - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_CONNECTING_HUB\n"); - - /* je�li asynchroniczne, sprawdzamy, czy nie wyst�pi� - * przypadkiem jaki� b��d. */ - if (sess->async && (getsockopt(sess->fd, SOL_SOCKET, SO_ERROR, &res, &res_size) || res)) { - /* no tak, nie uda�o si� po��czy� z proxy. nawet - * nie pr�bujemy dalej. */ - if (sess->proxy_addr && sess->proxy_port) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() connection to proxy failed (errno=%d, %s)\n", res, strerror(res)); - goto fail_connecting; - } - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() connection to hub failed (errno=%d, %s), trying direct connection\n", res, strerror(res)); - close(sess->fd); - - if ((sess->fd = gg_connect(&sess->hub_addr, GG_DEFAULT_PORT, sess->async)) == -1) { - /* przy asynchronicznych, gg_connect() - * zwraca -1 przy b��dach socket(), - * ioctl(), braku routingu itd. dlatego - * nawet nie pr�bujemy dalej. */ - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() direct connection failed (errno=%d, %s), critical\n", errno, strerror(errno)); - goto fail_connecting; - } - - sess->state = GG_STATE_CONNECTING_GG; - sess->check = GG_CHECK_WRITE; - sess->timeout = GG_DEFAULT_TIMEOUT; - break; - } - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() connected to hub, sending query\n"); - - if (!(client = gg_urlencode((sess->client_version) ? sess->client_version : GG_DEFAULT_CLIENT_VERSION))) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() out of memory for client version\n"); - goto fail_connecting; - } - - if (!gg_proxy_http_only && sess->proxy_addr && sess->proxy_port) - host = "http://" GG_APPMSG_HOST; - else - host = ""; - -#ifdef __GG_LIBGADU_HAVE_OPENSSL - if (sess->ssl) - appmsg = "appmsg3.asp"; - else -#endif - appmsg = "appmsg2.asp"; - - auth = gg_proxy_auth(); - - snprintf(buf, sizeof(buf) - 1, - "GET %s/appsvc/%s?fmnumber=%u&version=%s&lastmsg=%d HTTP/1.0\r\n" - "Host: " GG_APPMSG_HOST "\r\n" - "User-Agent: " GG_HTTP_USERAGENT "\r\n" - "Pragma: no-cache\r\n" - "%s" - "\r\n", host, appmsg, sess->uin, client, sess->last_sysmsg, (auth) ? auth : ""); - - if (auth) - free(auth); - - free(client); - - /* zwolnij pami�� po wersji klienta. */ - if (sess->client_version) { - free(sess->client_version); - sess->client_version = NULL; - } - - gg_debug(GG_DEBUG_MISC, "=> -----BEGIN-HTTP-QUERY-----\n%s\n=> -----END-HTTP-QUERY-----\n", buf); - - /* zapytanie jest kr�tkie, wi�c zawsze zmie�ci si� - * do bufora gniazda. je�li write() zwr�ci mniej, - * sta�o si� co� z�ego. */ - if (write(sess->fd, buf, strlen(buf)) < (signed)strlen(buf)) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() sending query failed\n"); - - e->type = GG_EVENT_CONN_FAILED; - e->event.failure = GG_FAILURE_WRITING; - sess->state = GG_STATE_IDLE; - close(sess->fd); - sess->fd = -1; - break; - } - - sess->state = GG_STATE_READING_DATA; - sess->check = GG_CHECK_READ; - sess->timeout = GG_DEFAULT_TIMEOUT; - - break; - } - - case GG_STATE_READING_DATA: - { - char buf[1024], *tmp, *host; - int port = GG_DEFAULT_PORT; - struct in_addr addr; - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_READING_DATA\n"); - - /* czytamy lini� z gniazda i obcinamy \r\n. */ - gg_read_line(sess->fd, buf, sizeof(buf) - 1); - gg_chomp(buf); - gg_debug(GG_DEBUG_TRAFFIC, "// gg_watch_fd() received http header (%s)\n", buf); - - /* sprawdzamy, czy wszystko w porz�dku. */ - if (strncmp(buf, "HTTP/1.", 7) || strncmp(buf + 9, "200", 3)) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() that's not what we've expected, trying direct connection\n"); - - close(sess->fd); - - /* je�li otrzymali�my jakie� dziwne informacje, - * pr�bujemy si� ��czy� z pomini�ciem huba. */ - if (sess->proxy_addr && sess->proxy_port) { - if ((sess->fd = gg_connect(&sess->proxy_addr, sess->proxy_port, sess->async)) == -1) { - /* trudno. nie wysz�o. */ - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() connection to proxy failed (errno=%d, %s)\n", errno, strerror(errno)); - goto fail_connecting; - } - - sess->state = GG_STATE_CONNECTING_GG; - sess->check = GG_CHECK_WRITE; - sess->timeout = GG_DEFAULT_TIMEOUT; - break; - } - - sess->port = GG_DEFAULT_PORT; - - /* ��czymy si� na port 8074 huba. */ - if ((sess->fd = gg_connect(&sess->hub_addr, sess->port, sess->async)) == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s), trying https\n", errno, strerror(errno)); - - sess->port = GG_HTTPS_PORT; - - /* ��czymy si� na port 443. */ - if ((sess->fd = gg_connect(&sess->hub_addr, sess->port, sess->async)) == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s)\n", errno, strerror(errno)); - goto fail_connecting; - } - } - - sess->state = GG_STATE_CONNECTING_GG; - sess->check = GG_CHECK_WRITE; - sess->timeout = GG_DEFAULT_TIMEOUT; - break; - } - - /* ignorujemy reszt� nag��wka. */ - while (strcmp(buf, "\r\n") && strcmp(buf, "")) - gg_read_line(sess->fd, buf, sizeof(buf) - 1); - - /* czytamy pierwsz� lini� danych. */ - gg_read_line(sess->fd, buf, sizeof(buf) - 1); - gg_chomp(buf); - - /* je�li pierwsza liczba w linii nie jest r�wna zeru, - * oznacza to, �e mamy wiadomo�� systemow�. */ - if (atoi(buf)) { - char tmp[1024], *foo, *sysmsg_buf = NULL; - int len = 0; - - while (gg_read_line(sess->fd, tmp, sizeof(tmp) - 1)) { - if (!(foo = realloc(sysmsg_buf, len + strlen(tmp) + 2))) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() out of memory for system message, ignoring\n"); - break; - } - - sysmsg_buf = foo; - - if (!len) - strcpy(sysmsg_buf, tmp); - else - strcat(sysmsg_buf, tmp); - - len += strlen(tmp); - } - - e->type = GG_EVENT_MSG; - e->event.msg.msgclass = atoi(buf); - e->event.msg.sender = 0; - e->event.msg.message = sysmsg_buf; - } - - close(sess->fd); - - gg_debug(GG_DEBUG_TRAFFIC, "// gg_watch_fd() received http data (%s)\n", buf); - - /* analizujemy otrzymane dane. */ - tmp = buf; - - while (*tmp && *tmp != ' ') - tmp++; - while (*tmp && *tmp == ' ') - tmp++; - host = tmp; - while (*tmp && *tmp != ' ') - tmp++; - *tmp = 0; - - if ((tmp = (char*)strchr(host, ':'))) { - *tmp = 0; - port = atoi(tmp + 1); - } - - if (!strcmp(host, "notoperating")) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() service unavailable\n", errno, strerror(errno)); - sess->fd = -1; - goto fail_unavailable; - } - - addr.s_addr = inet_addr(host); - sess->server_addr = addr.s_addr; - - if (!gg_proxy_http_only && sess->proxy_addr && sess->proxy_port) { - /* je�li mamy proxy, ��czymy si� z nim. */ - if ((sess->fd = gg_connect(&sess->proxy_addr, sess->proxy_port, sess->async)) == -1) { - /* nie wysz�o? trudno. */ - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() connection to proxy failed (errno=%d, %s)\n", errno, strerror(errno)); - goto fail_connecting; - } - - sess->state = GG_STATE_CONNECTING_GG; - sess->check = GG_CHECK_WRITE; - sess->timeout = GG_DEFAULT_TIMEOUT; - break; - } - - sess->port = port; - - /* ��czymy si� z w�a�ciwym serwerem. */ - if ((sess->fd = gg_connect(&addr, sess->port, sess->async)) == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s), trying https\n", errno, strerror(errno)); - - sess->port = GG_HTTPS_PORT; - - /* nie wysz�o? pr�bujemy portu 443. */ - if ((sess->fd = gg_connect(&addr, GG_HTTPS_PORT, sess->async)) == -1) { - /* ostatnia deska ratunku zawiod�a? - * w takim razie zwijamy manatki. */ - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s)\n", errno, strerror(errno)); - goto fail_connecting; - } - } - - sess->state = GG_STATE_CONNECTING_GG; - sess->check = GG_CHECK_WRITE; - sess->timeout = GG_DEFAULT_TIMEOUT; - - break; - } - - case GG_STATE_CONNECTING_GG: - { - int res = 0, res_size = sizeof(res); - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_CONNECTING_GG\n"); - - /* je�li wyst�pi� b��d podczas ��czenia si�... */ - if (sess->async && (sess->timeout == 0 || getsockopt(sess->fd, SOL_SOCKET, SO_ERROR, &res, &res_size) || res)) { - /* je�li nie uda�o si� po��czenie z proxy, - * nie mamy czego pr�bowa� wi�cej. */ - if (sess->proxy_addr && sess->proxy_port) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() connection to proxy failed (errno=%d, %s)\n", res, strerror(res)); - goto fail_connecting; - } - - close(sess->fd); - sess->fd = -1; - -#ifdef ETIMEDOUT - if (sess->timeout == 0) - errno = ETIMEDOUT; -#endif - -#ifdef __GG_LIBGADU_HAVE_OPENSSL - /* je�li logujemy si� po TLS, nie pr�bujemy - * si� ��czy� ju� z niczym innym w przypadku - * b��du. nie do��, �e nie ma sensu, to i - * trzeba by si� bawi� w tworzenie na nowo - * SSL i SSL_CTX. */ - - if (sess->ssl) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s)\n", res, strerror(res)); - goto fail_connecting; - } -#endif - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s), trying https\n", res, strerror(res)); - - sess->port = GG_HTTPS_PORT; - - /* pr�bujemy na port 443. */ - if ((sess->fd = gg_connect(&sess->server_addr, sess->port, sess->async)) == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s)\n", errno, strerror(errno)); - goto fail_connecting; - } - } - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() connected\n"); - - if (gg_proxy_http_only) - sess->proxy_port = 0; - - /* je�li mamy proxy, wy�lijmy zapytanie. */ - if (sess->proxy_addr && sess->proxy_port) { - char buf[100], *auth = gg_proxy_auth(); - struct in_addr addr; - - if (sess->server_addr) - addr.s_addr = sess->server_addr; - else - addr.s_addr = sess->hub_addr; - - snprintf(buf, sizeof(buf), "CONNECT %s:%d HTTP/1.0\r\n", inet_ntoa(addr), sess->port); - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() proxy request:\n// %s", buf); - - /* wysy�amy zapytanie. jest ono na tyle kr�tkie, - * �e musi si� zmie�ci� w buforze gniazda. je�li - * write() zawiedzie, sta�o si� co� z�ego. */ - if (write(sess->fd, buf, strlen(buf)) < (signed)strlen(buf)) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() can't send proxy request\n"); - if (auth) - free(auth); - goto fail_connecting; - } - - if (auth) { - gg_debug(GG_DEBUG_MISC, "// %s", auth); - if (write(sess->fd, auth, strlen(auth)) < (signed)strlen(auth)) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() can't send proxy request\n"); - free(auth); - goto fail_connecting; - } - - free(auth); - } - - if (write(sess->fd, "\r\n", 2) < 2) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() can't send proxy request\n"); - goto fail_connecting; - } - } - -#ifdef __GG_LIBGADU_HAVE_OPENSSL - if (sess->ssl) { - SSL_set_fd(sess->ssl, sess->fd); - - sess->state = GG_STATE_TLS_NEGOTIATION; - sess->check = GG_CHECK_WRITE; - sess->timeout = GG_DEFAULT_TIMEOUT; - - break; - } -#endif - - sess->state = GG_STATE_READING_KEY; - sess->check = GG_CHECK_READ; - sess->timeout = GG_DEFAULT_TIMEOUT; - - break; - } - -#ifdef __GG_LIBGADU_HAVE_OPENSSL - case GG_STATE_TLS_NEGOTIATION: - { - int res; - X509 *peer; - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_TLS_NEGOTIATION\n"); - - if ((res = SSL_connect(sess->ssl)) <= 0) { - int err = SSL_get_error(sess->ssl, res); - - if (res == 0) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() disconnected during TLS negotiation\n"); - - e->type = GG_EVENT_CONN_FAILED; - e->event.failure = GG_FAILURE_TLS; - sess->state = GG_STATE_IDLE; - close(sess->fd); - sess->fd = -1; - break; - } - - if (err == SSL_ERROR_WANT_READ) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() SSL_connect() wants to read\n"); - - sess->state = GG_STATE_TLS_NEGOTIATION; - sess->check = GG_CHECK_READ; - sess->timeout = GG_DEFAULT_TIMEOUT; - - break; - } else if (err == SSL_ERROR_WANT_WRITE) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() SSL_connect() wants to write\n"); - - sess->state = GG_STATE_TLS_NEGOTIATION; - sess->check = GG_CHECK_WRITE; - sess->timeout = GG_DEFAULT_TIMEOUT; - - break; - } else { - char buf[1024]; - - ERR_error_string_n(ERR_get_error(), buf, sizeof(buf)); - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() SSL_connect() bailed out: %s\n", buf); - - e->type = GG_EVENT_CONN_FAILED; - e->event.failure = GG_FAILURE_TLS; - sess->state = GG_STATE_IDLE; - close(sess->fd); - sess->fd = -1; - break; - } - } - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() TLS negotiation succeded:\n// cipher: %s\n", SSL_get_cipher_name(sess->ssl)); - - peer = SSL_get_peer_certificate(sess->ssl); - - if (!peer) - gg_debug(GG_DEBUG_MISC, "// WARNING! unable to get peer certificate!\n"); - else { - char buf[1024]; - - X509_NAME_oneline(X509_get_subject_name(peer), buf, sizeof(buf)); - gg_debug(GG_DEBUG_MISC, "// cert subject: %s\n", buf); - - X509_NAME_oneline(X509_get_issuer_name(peer), buf, sizeof(buf)); - gg_debug(GG_DEBUG_MISC, "// cert issuer: %s\n", buf); - } - - sess->state = GG_STATE_READING_KEY; - sess->check = GG_CHECK_READ; - sess->timeout = GG_DEFAULT_TIMEOUT; - - break; - } -#endif - - case GG_STATE_READING_KEY: - { - struct gg_header *h; - struct gg_welcome *w; - struct gg_login60 l; - unsigned int hash; - unsigned char *password = sess->password; - int ret; - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_READING_KEY\n"); - - memset(&l, 0, sizeof(l)); - l.dunno2 = 0xbe; - - /* XXX bardzo, bardzo, bardzo g�upi pomys� na pozbycie - * si� tekstu wrzucanego przez proxy. */ - if (sess->proxy_addr && sess->proxy_port) { - char buf[100]; - - strcpy(buf, ""); - gg_read_line(sess->fd, buf, sizeof(buf) - 1); - gg_chomp(buf); - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() proxy response:\n// %s\n", buf); - - while (strcmp(buf, "")) { - gg_read_line(sess->fd, buf, sizeof(buf) - 1); - gg_chomp(buf); - if (strcmp(buf, "")) - gg_debug(GG_DEBUG_MISC, "// %s\n", buf); - } - - /* XXX niech czeka jeszcze raz w tej samej - * fazie. g�upio, ale dzia�a. */ - sess->proxy_port = 0; - - break; - } - - /* czytaj pierwszy pakiet. */ - if (!(h = gg_recv_packet(sess))) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() didn't receive packet (errno=%d, %s)\n", errno, strerror(errno)); - - e->type = GG_EVENT_CONN_FAILED; - e->event.failure = GG_FAILURE_READING; - sess->state = GG_STATE_IDLE; - errno2 = errno; - close(sess->fd); - errno = errno2; - sess->fd = -1; - break; - } - - if (h->type != GG_WELCOME) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() invalid packet received\n"); - free(h); - close(sess->fd); - sess->fd = -1; - errno = EINVAL; - e->type = GG_EVENT_CONN_FAILED; - e->event.failure = GG_FAILURE_INVALID; - sess->state = GG_STATE_IDLE; - break; - } - - w = (struct gg_welcome*) ((char*) h + sizeof(struct gg_header)); - w->key = gg_fix32(w->key); - - hash = gg_login_hash(password, w->key); - - gg_debug(GG_DEBUG_DUMP, "// gg_watch_fd() challenge %.4x --> hash %.8x\n", w->key, hash); - - free(h); - - free(sess->password); - sess->password = NULL; - - { - struct in_addr dcc_ip; - dcc_ip.s_addr = gg_dcc_ip; - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() gg_dcc_ip = %s\n", inet_ntoa(dcc_ip)); - } - - if (gg_dcc_ip == (unsigned long) inet_addr("255.255.255.255")) { - struct sockaddr_in sin; - int sin_len = sizeof(sin); - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() detecting address\n"); - - if (!getsockname(sess->fd, (struct sockaddr*) &sin, &sin_len)) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() detected address to %s\n", inet_ntoa(sin.sin_addr)); - l.local_ip = sin.sin_addr.s_addr; - } else { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() unable to detect address\n"); - l.local_ip = 0; - } - } else - l.local_ip = gg_dcc_ip; - - l.uin = gg_fix32(sess->uin); - l.hash = gg_fix32(hash); - l.status = gg_fix32(sess->initial_status ? sess->initial_status : GG_STATUS_AVAIL); - l.version = gg_fix32(sess->protocol_version); - l.local_port = gg_fix16(gg_dcc_port); - l.image_size = sess->image_size; - - if (sess->external_addr && sess->external_port > 1023) { - l.external_ip = sess->external_addr; - l.external_port = gg_fix16(sess->external_port); - } - - gg_debug(GG_DEBUG_TRAFFIC, "// gg_watch_fd() sending GG_LOGIN60 packet\n"); - ret = gg_send_packet(sess, GG_LOGIN60, &l, sizeof(l), sess->initial_descr, (sess->initial_descr) ? strlen(sess->initial_descr) : 0, NULL); - - free(sess->initial_descr); - sess->initial_descr = NULL; - - if (ret == -1) { - gg_debug(GG_DEBUG_TRAFFIC, "// gg_watch_fd() sending packet failed. (errno=%d, %s)\n", errno, strerror(errno)); - errno2 = errno; - close(sess->fd); - errno = errno2; - sess->fd = -1; - e->type = GG_EVENT_CONN_FAILED; - e->event.failure = GG_FAILURE_WRITING; - sess->state = GG_STATE_IDLE; - break; - } - - sess->state = GG_STATE_READING_REPLY; - - break; - } - - case GG_STATE_READING_REPLY: - { - struct gg_header *h; - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_READING_REPLY\n"); - - if (!(h = gg_recv_packet(sess))) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() didn't receive packet (errno=%d, %s)\n", errno, strerror(errno)); - e->type = GG_EVENT_CONN_FAILED; - e->event.failure = GG_FAILURE_READING; - sess->state = GG_STATE_IDLE; - errno2 = errno; - close(sess->fd); - errno = errno2; - sess->fd = -1; - break; - } - - if (h->type == GG_LOGIN_OK || h->type == GG_NEED_EMAIL) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() login succeded\n"); - e->type = GG_EVENT_CONN_SUCCESS; - sess->state = GG_STATE_CONNECTED; - sess->timeout = -1; - sess->status = (sess->initial_status) ? sess->initial_status : GG_STATUS_AVAIL; - free(h); - break; - } - - if (h->type == GG_LOGIN_FAILED) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() login failed\n"); - e->event.failure = GG_FAILURE_PASSWORD; - errno = EACCES; - } else if (h->type == GG_DISCONNECTING) { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() too many incorrect password attempts\n"); - e->event.failure = GG_FAILURE_INTRUDER; - errno = EACCES; - } else { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() invalid packet\n"); - e->event.failure = GG_FAILURE_INVALID; - errno = EINVAL; - } - - e->type = GG_EVENT_CONN_FAILED; - sess->state = GG_STATE_IDLE; - errno2 = errno; - close(sess->fd); - errno = errno2; - sess->fd = -1; - free(h); - - break; - } - - case GG_STATE_CONNECTED: - { - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_CONNECTED\n"); - - sess->last_event = time(NULL); - - if ((res = gg_watch_fd_connected(sess, e)) == -1) { - - gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() watch_fd_connected failed (errno=%d, %s)\n", errno, strerror(errno)); - - if (errno == EAGAIN) { - e->type = GG_EVENT_NONE; - res = 0; - } else - res = -1; - } - break; - } - } - -done: - if (res == -1) { - free(e); - e = NULL; - } - - return e; - -fail_connecting: - if (sess->fd != -1) { - errno2 = errno; - close(sess->fd); - errno = errno2; - sess->fd = -1; - } - e->type = GG_EVENT_CONN_FAILED; - e->event.failure = GG_FAILURE_CONNECTING; - sess->state = GG_STATE_IDLE; - goto done; - -fail_resolving: - e->type = GG_EVENT_CONN_FAILED; - e->event.failure = GG_FAILURE_RESOLVING; - sess->state = GG_STATE_IDLE; - goto done; - -fail_unavailable: - e->type = GG_EVENT_CONN_FAILED; - e->event.failure = GG_FAILURE_UNAVAILABLE; - sess->state = GG_STATE_IDLE; - goto done; -} - -/* - * Local variables: - * c-indentation-style: k&r - * c-basic-offset: 8 - * indent-tabs-mode: notnil - * End: - * - * vim: shiftwidth=8: - */ diff --git a/kopete/protocols/gadu/libgadu/http.c b/kopete/protocols/gadu/libgadu/http.c deleted file mode 100644 index 9f7369c5..00000000 --- a/kopete/protocols/gadu/libgadu/http.c +++ /dev/null @@ -1,522 +0,0 @@ -/* $Id$ */ - -/* - * (C) Copyright 2001-2002 Wojtek Kaniewski <wojtekka@irc.pl> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License Version - * 2.1 as published by the Free Software Foundation. - * - * 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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. - */ - -#include <sys/types.h> -#include <sys/wait.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> - -#include "libgadu-config.h" - -#include <ctype.h> -#include <errno.h> -#include <netdb.h> -#ifdef __GG_LIBGADU_HAVE_PTHREAD -# include <pthread.h> -#endif -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include "compat.h" -#include "libgadu.h" - -/* - * gg_http_connect() // funkcja pomocnicza - * - * rozpoczyna po��czenie po http. - * - * - hostname - adres serwera - * - port - port serwera - * - async - asynchroniczne po��czenie - * - method - metoda http (GET, POST, cokolwiek) - * - path - �cie�ka do zasobu (musi by� poprzedzona ,,/'') - * - header - nag��wek zapytania plus ewentualne dane dla POST - * - * zaalokowana struct gg_http, kt�r� po�niej nale�y - * zwolni� funkcj� gg_http_free(), albo NULL je�li wyst�pi� b��d. - */ -struct gg_http *gg_http_connect(const char *hostname, int port, int async, const char *method, const char *path, const char *header) -{ - struct gg_http *h; - - if (!hostname || !port || !method || !path || !header) { - gg_debug(GG_DEBUG_MISC, "// gg_http_connect() invalid arguments\n"); - errno = EFAULT; - return NULL; - } - - if (!(h = malloc(sizeof(*h)))) - return NULL; - memset(h, 0, sizeof(*h)); - - h->async = async; - h->port = port; - h->fd = -1; - h->type = GG_SESSION_HTTP; - - if (gg_proxy_enabled) { - char *auth = gg_proxy_auth(); - - h->query = gg_saprintf("%s http://%s:%d%s HTTP/1.0\r\n%s%s", - method, hostname, port, path, (auth) ? auth : - "", header); - hostname = gg_proxy_host; - h->port = port = gg_proxy_port; - - if (auth) - free(auth); - } else { - h->query = gg_saprintf("%s %s HTTP/1.0\r\n%s", - method, path, header); - } - - if (!h->query) { - gg_debug(GG_DEBUG_MISC, "// gg_http_connect() not enough memory for query\n"); - free(h); - errno = ENOMEM; - return NULL; - } - - gg_debug(GG_DEBUG_MISC, "=> -----BEGIN-HTTP-QUERY-----\n%s\n=> -----END-HTTP-QUERY-----\n", h->query); - - if (async) { -#ifndef __GG_LIBGADU_HAVE_PTHREAD - if (gg_resolve(&h->fd, &h->pid, hostname)) { -#else - if (gg_resolve_pthread(&h->fd, &h->resolver, hostname)) { -#endif - gg_debug(GG_DEBUG_MISC, "// gg_http_connect() resolver failed\n"); - gg_http_free(h); - errno = ENOENT; - return NULL; - } - - gg_debug(GG_DEBUG_MISC, "// gg_http_connect() resolver = %p\n", h->resolver); - - h->state = GG_STATE_RESOLVING; - h->check = GG_CHECK_READ; - h->timeout = GG_DEFAULT_TIMEOUT; - } else { - struct in_addr *hn, a; - - if (!(hn = gg_gethostbyname(hostname))) { - gg_debug(GG_DEBUG_MISC, "// gg_http_connect() host not found\n"); - gg_http_free(h); - errno = ENOENT; - return NULL; - } else { - a.s_addr = hn->s_addr; - free(hn); - } - - if (!(h->fd = gg_connect(&a, port, 0)) == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_http_connect() connection failed (errno=%d, %s)\n", errno, strerror(errno)); - gg_http_free(h); - return NULL; - } - - h->state = GG_STATE_CONNECTING; - - while (h->state != GG_STATE_ERROR && h->state != GG_STATE_PARSING) { - if (gg_http_watch_fd(h) == -1) - break; - } - - if (h->state != GG_STATE_PARSING) { - gg_debug(GG_DEBUG_MISC, "// gg_http_connect() some strange error\n"); - gg_http_free(h); - return NULL; - } - } - - h->callback = gg_http_watch_fd; - h->destroy = gg_http_free; - - return h; -} - -#define gg_http_error(x) \ - close(h->fd); \ - h->fd = -1; \ - h->state = GG_STATE_ERROR; \ - h->error = x; \ - return 0; - -/* - * gg_http_watch_fd() - * - * przy asynchronicznej obs�udze HTTP funkcj� t� nale�y wywo�a�, je�li - * zmieni�o si� co� na obserwowanym deskryptorze. - * - * - h - struktura opisuj�ca po��czenie - * - * je�li wszystko posz�o dobrze to 0, inaczej -1. po��czenie b�dzie - * zako�czone, je�li h->state == GG_STATE_PARSING. je�li wyst�pi jaki� - * b��d, to b�dzie tam GG_STATE_ERROR i odpowiedni kod b��du w h->error. - */ -int gg_http_watch_fd(struct gg_http *h) -{ - gg_debug(GG_DEBUG_FUNCTION, "** gg_http_watch_fd(%p);\n", h); - - if (!h) { - gg_debug(GG_DEBUG_MISC, "// gg_http_watch_fd() invalid arguments\n"); - errno = EFAULT; - return -1; - } - - if (h->state == GG_STATE_RESOLVING) { - struct in_addr a; - - gg_debug(GG_DEBUG_MISC, "=> http, resolving done\n"); - - if (read(h->fd, &a, sizeof(a)) < (signed)sizeof(a) || a.s_addr == INADDR_NONE) { - gg_debug(GG_DEBUG_MISC, "=> http, resolver thread failed\n"); - gg_http_error(GG_ERROR_RESOLVING); - } - - close(h->fd); - h->fd = -1; - -#ifndef __GG_LIBGADU_HAVE_PTHREAD - waitpid(h->pid, NULL, 0); -#else - if (h->resolver) { - pthread_cancel(*((pthread_t *) h->resolver)); - free(h->resolver); - h->resolver = NULL; - } -#endif - - gg_debug(GG_DEBUG_MISC, "=> http, connecting to %s:%d\n", inet_ntoa(a), h->port); - - if ((h->fd = gg_connect(&a, h->port, h->async)) == -1) { - gg_debug(GG_DEBUG_MISC, "=> http, connection failed (errno=%d, %s)\n", errno, strerror(errno)); - gg_http_error(GG_ERROR_CONNECTING); - } - - h->state = GG_STATE_CONNECTING; - h->check = GG_CHECK_WRITE; - h->timeout = GG_DEFAULT_TIMEOUT; - - return 0; - } - - if (h->state == GG_STATE_CONNECTING) { - int res = 0; - unsigned int res_size = sizeof(res); - - if (h->async && (getsockopt(h->fd, SOL_SOCKET, SO_ERROR, &res, &res_size) || res)) { - gg_debug(GG_DEBUG_MISC, "=> http, async connection failed (errno=%d, %s)\n", (res) ? res : errno , strerror((res) ? res : errno)); - close(h->fd); - h->fd = -1; - h->state = GG_STATE_ERROR; - h->error = GG_ERROR_CONNECTING; - if (res) - errno = res; - return 0; - } - - gg_debug(GG_DEBUG_MISC, "=> http, connected, sending request\n"); - - h->state = GG_STATE_SENDING_QUERY; - } - - if (h->state == GG_STATE_SENDING_QUERY) { - int res; - - if ((res = write(h->fd, h->query, strlen(h->query))) < 1) { - gg_debug(GG_DEBUG_MISC, "=> http, write() failed (len=%d, res=%d, errno=%d)\n", strlen(h->query), res, errno); - gg_http_error(GG_ERROR_WRITING); - } - - if (res < strlen(h->query)) { - gg_debug(GG_DEBUG_MISC, "=> http, partial header sent (led=%d, sent=%d)\n", strlen(h->query), res); - - memmove(h->query, h->query + res, strlen(h->query) - res + 1); - h->state = GG_STATE_SENDING_QUERY; - h->check = GG_CHECK_WRITE; - h->timeout = GG_DEFAULT_TIMEOUT; - } else { - gg_debug(GG_DEBUG_MISC, "=> http, request sent (len=%d)\n", strlen(h->query)); - free(h->query); - h->query = NULL; - - h->state = GG_STATE_READING_HEADER; - h->check = GG_CHECK_READ; - h->timeout = GG_DEFAULT_TIMEOUT; - } - - return 0; - } - - if (h->state == GG_STATE_READING_HEADER) { - char buf[1024], *tmp; - int res; - - if ((res = read(h->fd, buf, sizeof(buf))) == -1) { - gg_debug(GG_DEBUG_MISC, "=> http, reading header failed (errno=%d)\n", errno); - if (h->header) { - free(h->header); - h->header = NULL; - } - gg_http_error(GG_ERROR_READING); - } - - if (!res) { - gg_debug(GG_DEBUG_MISC, "=> http, connection reset by peer\n"); - if (h->header) { - free(h->header); - h->header = NULL; - } - gg_http_error(GG_ERROR_READING); - } - - gg_debug(GG_DEBUG_MISC, "=> http, read %d bytes of header\n", res); - - if (!(tmp = realloc(h->header, h->header_size + res + 1))) { - gg_debug(GG_DEBUG_MISC, "=> http, not enough memory for header\n"); - free(h->header); - h->header = NULL; - gg_http_error(GG_ERROR_READING); - } - - h->header = tmp; - - memcpy(h->header + h->header_size, buf, res); - h->header_size += res; - - gg_debug(GG_DEBUG_MISC, "=> http, header_buf=%p, header_size=%d\n", h->header, h->header_size); - - h->header[h->header_size] = 0; - - if ((tmp = strstr(h->header, "\r\n\r\n")) || (tmp = strstr(h->header, "\n\n"))) { - int sep_len = (*tmp == '\r') ? 4 : 2; - unsigned int left; - char *line; - - left = h->header_size - ((long)(tmp) - (long)(h->header) + sep_len); - - gg_debug(GG_DEBUG_MISC, "=> http, got all header (%d bytes, %d left)\n", h->header_size - left, left); - - /* HTTP/1.1 200 OK */ - if (strlen(h->header) < 16 || strncmp(h->header + 9, "200", 3)) { - gg_debug(GG_DEBUG_MISC, "=> -----BEGIN-HTTP-HEADER-----\n%s\n=> -----END-HTTP-HEADER-----\n", h->header); - - gg_debug(GG_DEBUG_MISC, "=> http, didn't get 200 OK -- no results\n"); - free(h->header); - h->header = NULL; - gg_http_error(GG_ERROR_CONNECTING); - } - - h->body_size = 0; - line = h->header; - *tmp = 0; - - gg_debug(GG_DEBUG_MISC, "=> -----BEGIN-HTTP-HEADER-----\n%s\n=> -----END-HTTP-HEADER-----\n", h->header); - - while (line) { - if (!strncasecmp(line, "Content-length: ", 16)) { - h->body_size = atoi(line + 16); - } - line = (char*)strchr(line, '\n'); - if (line) - line++; - } - - if (h->body_size <= 0) { - gg_debug(GG_DEBUG_MISC, "=> http, content-length not found\n"); - h->body_size = left; - } - - if (left > h->body_size) { - gg_debug(GG_DEBUG_MISC, "=> http, oversized reply (%d bytes needed, %d bytes left)\n", h->body_size, left); - h->body_size = left; - } - - gg_debug(GG_DEBUG_MISC, "=> http, body_size=%d\n", h->body_size); - - if (!(h->body = malloc(h->body_size + 1))) { - gg_debug(GG_DEBUG_MISC, "=> http, not enough memory (%d bytes for body_buf)\n", h->body_size + 1); - free(h->header); - h->header = NULL; - gg_http_error(GG_ERROR_READING); - } - - if (left) { - memcpy(h->body, tmp + sep_len, left); - h->body_done = left; - } - - h->body[left] = 0; - - h->state = GG_STATE_READING_DATA; - h->check = GG_CHECK_READ; - h->timeout = GG_DEFAULT_TIMEOUT; - } - - return 0; - } - - if (h->state == GG_STATE_READING_DATA) { - char buf[1024]; - int res; - - if ((res = read(h->fd, buf, sizeof(buf))) == -1) { - gg_debug(GG_DEBUG_MISC, "=> http, reading body failed (errno=%d)\n", errno); - if (h->body) { - free(h->body); - h->body = NULL; - } - gg_http_error(GG_ERROR_READING); - } - - if (!res) { - if (h->body_done >= h->body_size) { - gg_debug(GG_DEBUG_MISC, "=> http, we're done, closing socket\n"); - h->state = GG_STATE_PARSING; - close(h->fd); - h->fd = -1; - } else { - gg_debug(GG_DEBUG_MISC, "=> http, connection closed while reading (have %d, need %d)\n", h->body_done, h->body_size); - if (h->body) { - free(h->body); - h->body = NULL; - } - gg_http_error(GG_ERROR_READING); - } - - return 0; - } - - gg_debug(GG_DEBUG_MISC, "=> http, read %d bytes of body\n", res); - - if (h->body_done + res > h->body_size) { - char *tmp; - - gg_debug(GG_DEBUG_MISC, "=> http, too much data (%d bytes, %d needed), enlarging buffer\n", h->body_done + res, h->body_size); - - if (!(tmp = realloc(h->body, h->body_done + res + 1))) { - gg_debug(GG_DEBUG_MISC, "=> http, not enough memory for data (%d needed)\n", h->body_done + res + 1); - free(h->body); - h->body = NULL; - gg_http_error(GG_ERROR_READING); - } - - h->body = tmp; - h->body_size = h->body_done + res; - } - - h->body[h->body_done + res] = 0; - memcpy(h->body + h->body_done, buf, res); - h->body_done += res; - - gg_debug(GG_DEBUG_MISC, "=> body_done=%d, body_size=%d\n", h->body_done, h->body_size); - - return 0; - } - - if (h->fd != -1) - close(h->fd); - - h->fd = -1; - h->state = GG_STATE_ERROR; - h->error = 0; - - return -1; -} - -#undef gg_http_error - -/* - * gg_http_stop() - * - * je�li po��czenie jest w trakcie, przerywa je. nie zwalnia h->data. - * - * - h - struktura opisuj�ca po��czenie - */ -void gg_http_stop(struct gg_http *h) -{ - if (!h) - return; - - if (h->state == GG_STATE_ERROR || h->state == GG_STATE_DONE) - return; - - if (h->fd != -1) - close(h->fd); - h->fd = -1; -} - -/* - * gg_http_free_fields() // funkcja wewn�trzna - * - * zwalnia pola struct gg_http, ale nie zwalnia samej struktury. - */ -void gg_http_free_fields(struct gg_http *h) -{ - if (!h) - return; - - if (h->body) { - free(h->body); - h->body = NULL; - } - - if (h->query) { - free(h->query); - h->query = NULL; - } - - if (h->header) { - free(h->header); - h->header = NULL; - } -} - -/* - * gg_http_free() - * - * pr�buje zamkn�� po��czenie i zwalnia pami�� po nim. - * - * - h - struktura, kt�r� nale�y zlikwidowa� - */ -void gg_http_free(struct gg_http *h) -{ - if (!h) - return; - - gg_http_stop(h); - gg_http_free_fields(h); - free(h); -} - -/* - * Local variables: - * c-indentation-style: k&r - * c-basic-offset: 8 - * indent-tabs-mode: notnil - * End: - * - * vim: shiftwidth=8: - */ diff --git a/kopete/protocols/gadu/libgadu/libgadu-config.h.in b/kopete/protocols/gadu/libgadu/libgadu-config.h.in deleted file mode 100644 index dc4fb435..00000000 --- a/kopete/protocols/gadu/libgadu/libgadu-config.h.in +++ /dev/null @@ -1,30 +0,0 @@ -/* Local libgadu configuration. */ - -#ifndef __GG_LIBGADU_CONFIG_H -#define __GG_LIBGADU_CONFIG_H - -/* Defined if libgadu was compiled for bigendian machine. */ -#undef __GG_LIBGADU_BIGENDIAN - -/* Defined if libgadu was compiled and linked with pthread support. */ -#define __GG_LIBGADU_HAVE_PTHREAD - -/* Defined if this machine has C99-compiliant vsnprintf(). */ -#undef __GG_LIBGADU_HAVE_C99_VSNPRINTF - -/* Defined if this machine has va_copy(). */ -#undef __GG_LIBGADU_HAVE_VA_COPY - -/* Defined if this machine has __va_copy(). */ -#undef __GG_LIBGADU_HAVE___VA_COPY - -/* Defined if this machine supports long long. */ -#undef __GG_LIBGADU_HAVE_LONG_LONG - -/* Defined if libgadu was compiled and linked with TLS support. */ -#undef __GG_LIBGADU_HAVE_OPENSSL - -/* Include file containing uintXX_t declarations. */ -#include <inttypes.h> - -#endif /* __GG_LIBGADU_CONFIG_H */ diff --git a/kopete/protocols/gadu/libgadu/libgadu.c b/kopete/protocols/gadu/libgadu/libgadu.c deleted file mode 100644 index 79f0a170..00000000 --- a/kopete/protocols/gadu/libgadu/libgadu.c +++ /dev/null @@ -1,1818 +0,0 @@ -/* $Id$ */ - -/* - * (C) Copyright 2001-2006 Wojtek Kaniewski <wojtekka@irc.pl> - * Robert J. Wo¼ny <speedy@ziew.org> - * Arkadiusz Mi¶kiewicz <arekm@pld-linux.org> - * Tomasz Chiliñski <chilek@chilan.com> - * Adam Wysocki <gophi@ekg.chmurka.net> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License Version - * 2.1 as published by the Free Software Foundation. - * - * 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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. - */ - -#include <sys/types.h> -#include <sys/wait.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#ifdef sun -# include <sys/filio.h> -#endif - -#include "libgadu-config.h" - -#include <errno.h> -#include <netdb.h> -#ifdef __GG_LIBGADU_HAVE_PTHREAD -# include <pthread.h> -#endif -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <signal.h> -#include <unistd.h> -#ifdef __GG_LIBGADU_HAVE_OPENSSL -# include <openssl/err.h> -# include <openssl/rand.h> -#endif - -#include "compat.h" -#include "libgadu.h" - -int gg_debug_level = 0; -void (*gg_debug_handler)(int level, const char *format, va_list ap) = NULL; - -int gg_dcc_port = 0; -unsigned long gg_dcc_ip = 0; - -unsigned long gg_local_ip = 0; -/* - * zmienne opisuj±ce parametry proxy http. - */ -char *gg_proxy_host = NULL; -int gg_proxy_port = 0; -int gg_proxy_enabled = 0; -int gg_proxy_http_only = 0; -char *gg_proxy_username = NULL; -char *gg_proxy_password = NULL; - -#ifndef lint -static char rcsid[] -#ifdef __GNUC__ -__attribute__ ((unused)) -#endif -= "$Id$"; -#endif - -/* - * gg_libgadu_version() - * - * zwraca wersjê libgadu. - * - * - brak - * - * wersja libgadu. - */ -const char *gg_libgadu_version() -{ - return GG_LIBGADU_VERSION; -} - -/* - * gg_fix32() - * - * zamienia kolejno¶æ bajtów w liczbie 32-bitowej tak, by odpowiada³a - * kolejno¶ci bajtów w protokole GG. ze wzglêdu na LE-owo¶æ serwera, - * zamienia tylko na maszynach BE-wych. - * - * - x - liczba do zamiany - * - * liczba z odpowiedni± kolejno¶ci± bajtów. - */ -uint32_t gg_fix32(uint32_t x) -{ -#ifndef __GG_LIBGADU_BIGENDIAN - return x; -#else - return (uint32_t) - (((x & (uint32_t) 0x000000ffU) << 24) | - ((x & (uint32_t) 0x0000ff00U) << 8) | - ((x & (uint32_t) 0x00ff0000U) >> 8) | - ((x & (uint32_t) 0xff000000U) >> 24)); -#endif -} - -/* - * gg_fix16() - * - * zamienia kolejno¶æ bajtów w liczbie 16-bitowej tak, by odpowiada³a - * kolejno¶ci bajtów w protokole GG. ze wzglêdu na LE-owo¶æ serwera, - * zamienia tylko na maszynach BE-wych. - * - * - x - liczba do zamiany - * - * liczba z odpowiedni± kolejno¶ci± bajtów. - */ -uint16_t gg_fix16(uint16_t x) -{ -#ifndef __GG_LIBGADU_BIGENDIAN - return x; -#else - return (uint16_t) - (((x & (uint16_t) 0x00ffU) << 8) | - ((x & (uint16_t) 0xff00U) >> 8)); -#endif -} - -/* - * gg_login_hash() // funkcja wewnêtrzna - * - * liczy hash z has³a i danego seeda. - * - * - password - has³o do hashowania - * - seed - warto¶æ podana przez serwer - * - * hash. - */ -unsigned int gg_login_hash(const unsigned char *password, unsigned int seed) -{ - unsigned int x, y, z; - - y = seed; - - for (x = 0; *password; password++) { - x = (x & 0xffffff00) | *password; - y ^= x; - y += x; - x <<= 8; - y ^= x; - x <<= 8; - y -= x; - x <<= 8; - y ^= x; - - z = y & 0x1F; - y = (y << z) | (y >> (32 - z)); - } - - return y; -} - -/* - * gg_resolve() // funkcja wewnêtrzna - * - * tworzy potok, forkuje siê i w drugim procesie zaczyna resolvowaæ - * podanego hosta. zapisuje w sesji deskryptor potoku. je¶li co¶ tam - * bêdzie gotowego, znaczy, ¿e mo¿na wczytaæ struct in_addr. je¶li - * nie znajdzie, zwraca INADDR_NONE. - * - * - fd - wska¼nik gdzie wrzuciæ deskryptor - * - pid - gdzie wrzuciæ pid procesu potomnego - * - hostname - nazwa hosta do zresolvowania - * - * 0, -1. - */ -int gg_resolve(int *fd, int *pid, const char *hostname) -{ - int pipes[2], res; - struct in_addr a; - int errno2; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_resolve(%p, %p, \"%s\");\n", fd, pid, hostname); - - if (!fd || !pid) { - errno = EFAULT; - return -1; - } - - if (pipe(pipes) == -1) - return -1; - - if ((res = fork()) == -1) { - errno2 = errno; - close(pipes[0]); - close(pipes[1]); - errno = errno2; - return -1; - } - - if (!res) { - close(pipes[0]); - - if ((a.s_addr = inet_addr(hostname)) == INADDR_NONE) { - struct in_addr *hn; - - if (!(hn = gg_gethostbyname(hostname))) - a.s_addr = INADDR_NONE; - else { - a.s_addr = hn->s_addr; - free(hn); - } - } - - write(pipes[1], &a, sizeof(a)); - - exit(0); - } - - close(pipes[1]); - - *fd = pipes[0]; - *pid = res; - - return 0; -} - -#ifdef __GG_LIBGADU_HAVE_PTHREAD - -struct gg_resolve_pthread_data { - char *hostname; - int fd; -}; - -static void *gg_resolve_pthread_thread(void *arg) -{ - struct gg_resolve_pthread_data *d = arg; - struct in_addr a; - - pthread_detach(pthread_self()); - - if ((a.s_addr = inet_addr(d->hostname)) == INADDR_NONE) { - struct in_addr *hn; - - if (!(hn = gg_gethostbyname(d->hostname))) - a.s_addr = INADDR_NONE; - else { - a.s_addr = hn->s_addr; - free(hn); - } - } - - write(d->fd, &a, sizeof(a)); - close(d->fd); - - free(d->hostname); - d->hostname = NULL; - - free(d); - - pthread_exit(NULL); - - return NULL; /* ¿eby kompilator nie marudzi³ */ -} - -/* - * gg_resolve_pthread() // funkcja wewnêtrzna - * - * tworzy potok, nowy w±tek i w nim zaczyna resolvowaæ podanego hosta. - * zapisuje w sesji deskryptor potoku. je¶li co¶ tam bêdzie gotowego, - * znaczy, ¿e mo¿na wczytaæ struct in_addr. je¶li nie znajdzie, zwraca - * INADDR_NONE. - * - * - fd - wska¼nik do zmiennej przechowuj±cej desktyptor resolvera - * - resolver - wska¼nik do wska¼nika resolvera - * - hostname - nazwa hosta do zresolvowania - * - * 0, -1. - */ -int gg_resolve_pthread(int *fd, void **resolver, const char *hostname) -{ - struct gg_resolve_pthread_data *d = NULL; - pthread_t *tmp; - int pipes[2], new_errno; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_resolve_pthread(%p, %p, \"%s\");\n", fd, resolver, hostname); - - if (!resolver || !fd || !hostname) { - gg_debug(GG_DEBUG_MISC, "// gg_resolve_pthread() invalid arguments\n"); - errno = EFAULT; - return -1; - } - - if (!(tmp = malloc(sizeof(pthread_t)))) { - gg_debug(GG_DEBUG_MISC, "// gg_resolve_pthread() out of memory for pthread id\n"); - return -1; - } - - if (pipe(pipes) == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_resolve_pthread() unable to create pipes (errno=%d, %s)\n", errno, strerror(errno)); - free(tmp); - return -1; - } - - if (!(d = malloc(sizeof(*d)))) { - gg_debug(GG_DEBUG_MISC, "// gg_resolve_pthread() out of memory\n"); - new_errno = errno; - goto cleanup; - } - - d->hostname = NULL; - - if (!(d->hostname = strdup(hostname))) { - gg_debug(GG_DEBUG_MISC, "// gg_resolve_pthread() out of memory\n"); - new_errno = errno; - goto cleanup; - } - - d->fd = pipes[1]; - - if (pthread_create(tmp, NULL, gg_resolve_pthread_thread, d)) { - gg_debug(GG_DEBUG_MISC, "// gg_resolve_phread() unable to create thread\n"); - new_errno = errno; - goto cleanup; - } - - gg_debug(GG_DEBUG_MISC, "// gg_resolve_pthread() %p\n", tmp); - - *resolver = tmp; - - *fd = pipes[0]; - - return 0; - -cleanup: - if (d) { - free(d->hostname); - free(d); - } - - close(pipes[0]); - close(pipes[1]); - - free(tmp); - - errno = new_errno; - - return -1; -} - -#endif - -/* - * gg_read() // funkcja pomocnicza - * - * czyta z gniazda okre¶lon± ilo¶æ bajtów. bierze pod uwagê, czy mamy - * po³±czenie zwyk³e czy TLS. - * - * - sess - sesja, - * - buf - bufor, - * - length - ilo¶æ bajtów, - * - * takie same warto¶ci jak read(). - */ -int gg_read(struct gg_session *sess, char *buf, int length) -{ - int res; - -#ifdef __GG_LIBGADU_HAVE_OPENSSL - if (sess->ssl) { - int err; - - res = SSL_read(sess->ssl, buf, length); - - if (res < 0) { - err = SSL_get_error(sess->ssl, res); - - if (err == SSL_ERROR_WANT_READ) - errno = EAGAIN; - - return -1; - } - } else -#endif - res = read(sess->fd, buf, length); - - return res; -} - -/* - * gg_write() // funkcja pomocnicza - * - * zapisuje do gniazda okre¶lon± ilo¶æ bajtów. bierze pod uwagê, czy mamy - * po³±czenie zwyk³e czy TLS. - * - * - sess - sesja, - * - buf - bufor, - * - length - ilo¶æ bajtów, - * - * takie same warto¶ci jak write(). - */ -int gg_write(struct gg_session *sess, const char *buf, int length) -{ - int res = 0; - -#ifdef __GG_LIBGADU_HAVE_OPENSSL - if (sess->ssl) { - int err; - - res = SSL_write(sess->ssl, buf, length); - - if (res < 0) { - err = SSL_get_error(sess->ssl, res); - - if (err == SSL_ERROR_WANT_WRITE) - errno = EAGAIN; - - return -1; - } - } else -#endif - { - int written = 0; - - while (written < length) { - res = write(sess->fd, buf + written, length - written); - - if (res == -1) { - if (errno == EAGAIN) - continue; - else - break; - } else { - written += res; - res = written; - } - } - } - - return res; -} - -/* - * gg_recv_packet() // funkcja wewnêtrzna - * - * odbiera jeden pakiet i zwraca wska¼nik do niego. pamiêæ po nim - * nale¿y zwolniæ za pomoc± free(). - * - * - sess - opis sesji - * - * w przypadku b³êdu NULL, kod b³êdu w errno. nale¿y zwróciæ uwagê, ¿e gdy - * po³±czenie jest nieblokuj±ce, a kod b³êdu wynosi EAGAIN, nie uda³o siê - * odczytaæ ca³ego pakietu i nie nale¿y tego traktowaæ jako b³±d. - */ -void *gg_recv_packet(struct gg_session *sess) -{ - struct gg_header h; - char *buf = NULL; - int ret = 0; - unsigned int offset, size = 0; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_recv_packet(%p);\n", sess); - - if (!sess) { - errno = EFAULT; - return NULL; - } - - if (sess->recv_left < 1) { - if (sess->header_buf) { - memcpy(&h, sess->header_buf, sess->header_done); - gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() header recv: resuming last read (%d bytes left)\n", sizeof(h) - sess->header_done); - free(sess->header_buf); - sess->header_buf = NULL; - } else - sess->header_done = 0; - - while (sess->header_done < sizeof(h)) { - ret = gg_read(sess, (char*) &h + sess->header_done, sizeof(h) - sess->header_done); - - gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() header recv(%d,%p,%d) = %d\n", sess->fd, &h + sess->header_done, sizeof(h) - sess->header_done, ret); - - if (!ret) { - errno = ECONNRESET; - gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() header recv() failed: connection broken\n"); - return NULL; - } - - if (ret == -1) { - if (errno == EINTR) { - gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() header recv() interrupted system call, resuming\n"); - continue; - } - - if (errno == EAGAIN) { - gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() header recv() incomplete header received\n"); - - if (!(sess->header_buf = malloc(sess->header_done))) { - gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() header recv() not enough memory\n"); - return NULL; - } - - memcpy(sess->header_buf, &h, sess->header_done); - - return NULL; - } - - gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() header recv() failed: errno=%d, %s\n", errno, strerror(errno)); - - return NULL; - } - - sess->header_done += ret; - - } - - h.type = gg_fix32(h.type); - h.length = gg_fix32(h.length); - } else - memcpy(&h, sess->recv_buf, sizeof(h)); - - /* jakie¶ sensowne limity na rozmiar pakietu */ - if (h.length > 65535) { - gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() invalid packet length (%d)\n", h.length); - errno = ERANGE; - return NULL; - } - - if (sess->recv_left > 0) { - gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() resuming last gg_recv_packet()\n"); - size = sess->recv_left; - offset = sess->recv_done; - buf = sess->recv_buf; - } else { - if (!(buf = malloc(sizeof(h) + h.length + 1))) { - gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() not enough memory for packet data\n"); - return NULL; - } - - memcpy(buf, &h, sizeof(h)); - - offset = 0; - size = h.length; - } - - while (size > 0) { - ret = gg_read(sess, buf + sizeof(h) + offset, size); - gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() body recv(%d,%p,%d) = %d\n", sess->fd, buf + sizeof(h) + offset, size, ret); - if (!ret) { - gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() body recv() failed: connection broken\n"); - errno = ECONNRESET; - return NULL; - } - if (ret > -1 && ret <= size) { - offset += ret; - size -= ret; - } else if (ret == -1) { - int errno2 = errno; - - gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() body recv() failed (errno=%d, %s)\n", errno, strerror(errno)); - errno = errno2; - - if (errno == EAGAIN) { - gg_debug(GG_DEBUG_MISC, "// gg_recv_packet() %d bytes received, %d left\n", offset, size); - sess->recv_buf = buf; - sess->recv_left = size; - sess->recv_done = offset; - return NULL; - } - if (errno != EINTR) { - free(buf); - return NULL; - } - } - } - - sess->recv_left = 0; - - if ((gg_debug_level & GG_DEBUG_DUMP)) { - unsigned int i; - - gg_debug(GG_DEBUG_DUMP, "// gg_recv_packet(%.2x)", h.type); - for (i = 0; i < sizeof(h) + h.length; i++) - gg_debug(GG_DEBUG_DUMP, " %.2x", (unsigned char) buf[i]); - gg_debug(GG_DEBUG_DUMP, "\n"); - } - - return buf; -} - -/* - * gg_send_packet() // funkcja wewnêtrzna - * - * konstruuje pakiet i wysy³a go do serwera. - * - * - sock - deskryptor gniazda - * - type - typ pakietu - * - payload_1 - pierwsza czê¶æ pakietu - * - payload_length_1 - d³ugo¶æ pierwszej czê¶ci - * - payload_2 - druga czê¶æ pakietu - * - payload_length_2 - d³ugo¶æ drugiej czê¶ci - * - ... - kolejne czê¶ci pakietu i ich d³ugo¶ci - * - NULL - koñcowym parametr (konieczny!) - * - * je¶li siê powiod³o, zwraca 0, w przypadku b³êdu -1. je¶li errno == ENOMEM, - * zabrak³o pamiêci. inaczej by³ b³±d przy wysy³aniu pakietu. dla errno == 0 - * nie wys³ano ca³ego pakietu. - */ -int gg_send_packet(struct gg_session *sess, int type, ...) -{ - struct gg_header *h; - char *tmp; - unsigned int tmp_length; - void *payload; - unsigned int payload_length; - va_list ap; - int res; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_send_packet(%p, 0x%.2x, ...)\n", sess, type); - - tmp_length = sizeof(struct gg_header); - - if (!(tmp = malloc(tmp_length))) { - gg_debug(GG_DEBUG_MISC, "// gg_send_packet() not enough memory for packet header\n"); - return -1; - } - - va_start(ap, type); - - payload = va_arg(ap, void *); - - while (payload) { - char *tmp2; - - payload_length = va_arg(ap, unsigned int); - - if (!(tmp2 = realloc(tmp, tmp_length + payload_length))) { - gg_debug(GG_DEBUG_MISC, "// gg_send_packet() not enough memory for payload\n"); - free(tmp); - va_end(ap); - return -1; - } - - tmp = tmp2; - - memcpy(tmp + tmp_length, payload, payload_length); - tmp_length += payload_length; - - payload = va_arg(ap, void *); - } - - va_end(ap); - - h = (struct gg_header*) tmp; - h->type = gg_fix32(type); - h->length = gg_fix32(tmp_length - sizeof(struct gg_header)); - - if ((gg_debug_level & GG_DEBUG_DUMP)) { - unsigned int i; - - gg_debug(GG_DEBUG_DUMP, "// gg_send_packet(0x%.2x)", gg_fix32(h->type)); - for (i = 0; i < tmp_length; ++i) - gg_debug(GG_DEBUG_DUMP, " %.2x", (unsigned char) tmp[i]); - gg_debug(GG_DEBUG_DUMP, "\n"); - } - - if ((res = gg_write(sess, tmp, tmp_length)) < tmp_length) { - gg_debug(GG_DEBUG_MISC, "// gg_send_packet() write() failed. res = %d, errno = %d (%s)\n", res, errno, strerror(errno)); - free(tmp); - return -1; - } - - free(tmp); - return 0; -} - -/* - * gg_session_callback() // funkcja wewnêtrzna - * - * wywo³ywany z gg_session->callback, wykonuje gg_watch_fd() i pakuje - * do gg_session->event jego wynik. - */ -static int gg_session_callback(struct gg_session *s) -{ - if (!s) { - errno = EFAULT; - return -1; - } - - return ((s->event = gg_watch_fd(s)) != NULL) ? 0 : -1; -} - -/* - * gg_login() - * - * rozpoczyna procedurê ³±czenia siê z serwerem. resztê obs³uguje siê przez - * gg_watch_fd(). - * - * UWAGA! program musi obs³u¿yæ SIGCHLD, je¶li ³±czy siê asynchronicznie, - * ¿eby poprawnie zamkn±æ proces resolvera. - * - * - p - struktura opisuj±ca pocz±tkowy stan. wymagane pola: uin, - * password - * - * w przypadku b³êdu NULL, je¶li idzie dobrze (async) albo posz³o - * dobrze (sync), zwróci wska¼nik do zaalokowanej struct gg_session. - */ -struct gg_session *gg_login(const struct gg_login_params *p) -{ - struct gg_session *sess = NULL; - char *hostname; - int port; - - if (!p) { - gg_debug(GG_DEBUG_FUNCTION, "** gg_login(%p);\n", p); - errno = EFAULT; - return NULL; - } - - gg_debug(GG_DEBUG_FUNCTION, "** gg_login(%p: [uin=%u, async=%d, ...]);\n", p, p->uin, p->async); - - if (!(sess = malloc(sizeof(struct gg_session)))) { - gg_debug(GG_DEBUG_MISC, "// gg_login() not enough memory for session data\n"); - goto fail; - } - - memset(sess, 0, sizeof(struct gg_session)); - - if (!p->password || !p->uin) { - gg_debug(GG_DEBUG_MISC, "// gg_login() invalid arguments. uin and password needed\n"); - errno = EFAULT; - goto fail; - } - - if (!(sess->password = strdup(p->password))) { - gg_debug(GG_DEBUG_MISC, "// gg_login() not enough memory for password\n"); - goto fail; - } - - if (p->status_descr && !(sess->initial_descr = strdup(p->status_descr))) { - gg_debug(GG_DEBUG_MISC, "// gg_login() not enough memory for status\n"); - goto fail; - } - - sess->uin = p->uin; - sess->state = GG_STATE_RESOLVING; - sess->check = GG_CHECK_READ; - sess->timeout = GG_DEFAULT_TIMEOUT; - sess->async = p->async; - sess->type = GG_SESSION_GG; - sess->initial_status = p->status; - sess->callback = gg_session_callback; - sess->destroy = gg_free_session; - sess->port = (p->server_port) ? p->server_port : ((gg_proxy_enabled) ? GG_HTTPS_PORT : GG_DEFAULT_PORT); - sess->server_addr = p->server_addr; - sess->external_port = p->external_port; - sess->external_addr = p->external_addr; - sess->protocol_version = (p->protocol_version) ? p->protocol_version : GG_DEFAULT_PROTOCOL_VERSION; - if (p->era_omnix) - sess->protocol_version |= GG_ERA_OMNIX_MASK; - if (p->has_audio) - sess->protocol_version |= GG_HAS_AUDIO_MASK; - sess->client_version = (p->client_version) ? strdup(p->client_version) : NULL; - sess->last_sysmsg = p->last_sysmsg; - sess->image_size = p->image_size; - sess->pid = -1; - - if (p->tls == 1) { -#ifdef __GG_LIBGADU_HAVE_OPENSSL - char buf[1024]; - - OpenSSL_add_ssl_algorithms(); - - if (!RAND_status()) { - char rdata[1024]; - struct { - time_t time; - void *ptr; - } rstruct; - - time(&rstruct.time); - rstruct.ptr = (void *) &rstruct; - - RAND_seed((void *) rdata, sizeof(rdata)); - RAND_seed((void *) &rstruct, sizeof(rstruct)); - } - - sess->ssl_ctx = SSL_CTX_new(TLSv1_client_method()); - - if (!sess->ssl_ctx) { - ERR_error_string_n(ERR_get_error(), buf, sizeof(buf)); - gg_debug(GG_DEBUG_MISC, "// gg_login() SSL_CTX_new() failed: %s\n", buf); - goto fail; - } - - SSL_CTX_set_verify(sess->ssl_ctx, SSL_VERIFY_NONE, NULL); - - sess->ssl = SSL_new(sess->ssl_ctx); - - if (!sess->ssl) { - ERR_error_string_n(ERR_get_error(), buf, sizeof(buf)); - gg_debug(GG_DEBUG_MISC, "// gg_login() SSL_new() failed: %s\n", buf); - goto fail; - } -#else - gg_debug(GG_DEBUG_MISC, "// gg_login() client requested TLS but no support compiled in\n"); -#endif - } - - if (gg_proxy_enabled) { - hostname = gg_proxy_host; - sess->proxy_port = port = gg_proxy_port; - } else { - hostname = GG_APPMSG_HOST; - port = GG_APPMSG_PORT; - } - - if (!p->async) { - struct in_addr a; - - if (!p->server_addr || !p->server_port) { - if ((a.s_addr = inet_addr(hostname)) == INADDR_NONE) { - struct in_addr *hn; - - if (!(hn = gg_gethostbyname(hostname))) { - gg_debug(GG_DEBUG_MISC, "// gg_login() host \"%s\" not found\n", hostname); - goto fail; - } else { - a.s_addr = hn->s_addr; - free(hn); - } - } - } else { - a.s_addr = p->server_addr; - port = p->server_port; - } - - sess->hub_addr = a.s_addr; - - if (gg_proxy_enabled) - sess->proxy_addr = a.s_addr; - - if ((sess->fd = gg_connect(&a, port, 0)) == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_login() connection failed (errno=%d, %s)\n", errno, strerror(errno)); - goto fail; - } - - if (p->server_addr && p->server_port) - sess->state = GG_STATE_CONNECTING_GG; - else - sess->state = GG_STATE_CONNECTING_HUB; - - while (sess->state != GG_STATE_CONNECTED) { - struct gg_event *e; - - if (!(e = gg_watch_fd(sess))) { - gg_debug(GG_DEBUG_MISC, "// gg_login() critical error in gg_watch_fd()\n"); - goto fail; - } - - if (e->type == GG_EVENT_CONN_FAILED) { - errno = EACCES; - gg_debug(GG_DEBUG_MISC, "// gg_login() could not login\n"); - gg_event_free(e); - goto fail; - } - - gg_event_free(e); - } - - return sess; - } - - if (!sess->server_addr || gg_proxy_enabled) { -#ifndef __GG_LIBGADU_HAVE_PTHREAD - if (gg_resolve(&sess->fd, &sess->pid, hostname)) { -#else - if (gg_resolve_pthread(&sess->fd, &sess->resolver, hostname)) { -#endif - gg_debug(GG_DEBUG_MISC, "// gg_login() resolving failed (errno=%d, %s)\n", errno, strerror(errno)); - goto fail; - } - } else { - if ((sess->fd = gg_connect(&sess->server_addr, sess->port, sess->async)) == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_login() direct connection failed (errno=%d, %s)\n", errno, strerror(errno)); - goto fail; - } - sess->state = GG_STATE_CONNECTING_GG; - sess->check = GG_CHECK_WRITE; - } - - return sess; - -fail: - if (sess) { - if (sess->password) - free(sess->password); - if (sess->initial_descr) - free(sess->initial_descr); - free(sess); - } - - return NULL; -} - -/* - * gg_free_session() - * - * próbuje zamkn±æ po³±czenia i zwalnia pamiêæ zajmowan± przez sesjê. - * - * - sess - opis sesji - */ -void gg_free_session(struct gg_session *sess) -{ - if (!sess) - return; - - /* XXX dopisaæ zwalnianie i zamykanie wszystkiego, co mog³o zostaæ */ - - if (sess->password) - free(sess->password); - - if (sess->initial_descr) - free(sess->initial_descr); - - if (sess->client_version) - free(sess->client_version); - - if (sess->header_buf) - free(sess->header_buf); - -#ifdef __GG_LIBGADU_HAVE_OPENSSL - if (sess->ssl) - SSL_free(sess->ssl); - - if (sess->ssl_ctx) - SSL_CTX_free(sess->ssl_ctx); -#endif - -#ifdef __GG_LIBGADU_HAVE_PTHREAD - if (sess->resolver) { - pthread_cancel(*((pthread_t*) sess->resolver)); - free(sess->resolver); - sess->resolver = NULL; - } -#else - if (sess->pid != -1) { - kill(sess->pid, SIGTERM); - waitpid(sess->pid, NULL, WNOHANG); - } -#endif - - if (sess->fd != -1) - close(sess->fd); - - while (sess->images) - gg_image_queue_remove(sess, sess->images, 1); - - free(sess); -} - -/* - * gg_change_status() - * - * zmienia status u¿ytkownika. przydatne do /away i /busy oraz /quit. - * - * - sess - opis sesji - * - status - nowy status u¿ytkownika - * - * 0, -1. - */ -int gg_change_status(struct gg_session *sess, int status) -{ - struct gg_new_status p; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_change_status(%p, %d);\n", sess, status); - - if (!sess) { - errno = EFAULT; - return -1; - } - - if (sess->state != GG_STATE_CONNECTED) { - errno = ENOTCONN; - return -1; - } - - p.status = gg_fix32(status); - - sess->status = status; - - return gg_send_packet(sess, GG_NEW_STATUS, &p, sizeof(p), NULL); -} - -/* - * gg_change_status_descr() - * - * zmienia status u¿ytkownika na opisowy. - * - * - sess - opis sesji - * - status - nowy status u¿ytkownika - * - descr - opis statusu - * - * 0, -1. - */ -int gg_change_status_descr(struct gg_session *sess, int status, const char *descr) -{ - struct gg_new_status p; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_change_status_descr(%p, %d, \"%s\");\n", sess, status, descr); - - if (!sess || !descr) { - errno = EFAULT; - return -1; - } - - if (sess->state != GG_STATE_CONNECTED) { - errno = ENOTCONN; - return -1; - } - - p.status = gg_fix32(status); - - sess->status = status; - - return gg_send_packet(sess, GG_NEW_STATUS, &p, sizeof(p), descr, (strlen(descr) > GG_STATUS_DESCR_MAXSIZE) ? GG_STATUS_DESCR_MAXSIZE : strlen(descr), NULL); -} - -/* - * gg_change_status_descr_time() - * - * zmienia status u¿ytkownika na opisowy z godzin± powrotu. - * - * - sess - opis sesji - * - status - nowy status u¿ytkownika - * - descr - opis statusu - * - time - czas w formacie uniksowym - * - * 0, -1. - */ -int gg_change_status_descr_time(struct gg_session *sess, int status, const char *descr, int time) -{ - struct gg_new_status p; - uint32_t newtime; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_change_status_descr_time(%p, %d, \"%s\", %d);\n", sess, status, descr, time); - - if (!sess || !descr || !time) { - errno = EFAULT; - return -1; - } - - if (sess->state != GG_STATE_CONNECTED) { - errno = ENOTCONN; - return -1; - } - - p.status = gg_fix32(status); - - sess->status = status; - - newtime = gg_fix32(time); - - return gg_send_packet(sess, GG_NEW_STATUS, &p, sizeof(p), descr, (strlen(descr) > GG_STATUS_DESCR_MAXSIZE) ? GG_STATUS_DESCR_MAXSIZE : strlen(descr), &newtime, sizeof(newtime), NULL); -} - -/* - * gg_logoff() - * - * wylogowuje u¿ytkownika i zamyka po³±czenie, ale nie zwalnia pamiêci. - * - * - sess - opis sesji - */ -void gg_logoff(struct gg_session *sess) -{ - if (!sess) - return; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_logoff(%p);\n", sess); - - if (GG_S_NA(sess->status & ~GG_STATUS_FRIENDS_MASK)) - gg_change_status(sess, GG_STATUS_NOT_AVAIL); - -#ifdef __GG_LIBGADU_HAVE_OPENSSL - if (sess->ssl) - SSL_shutdown(sess->ssl); -#endif - -#ifdef __GG_LIBGADU_HAVE_PTHREAD - if (sess->resolver) { - pthread_cancel(*((pthread_t*) sess->resolver)); - free(sess->resolver); - sess->resolver = NULL; - } -#else - if (sess->pid != -1) { - kill(sess->pid, SIGTERM); - waitpid(sess->pid, NULL, WNOHANG); - sess->pid = -1; - } -#endif - - if (sess->fd != -1) { - shutdown(sess->fd, SHUT_RDWR); - close(sess->fd); - sess->fd = -1; - } -} - -/* - * gg_image_request() - * - * wysy³a ¿±danie wys³ania obrazka o podanych parametrach. - * - * - sess - opis sesji - * - recipient - numer adresata - * - size - rozmiar obrazka - * - crc32 - suma kontrolna obrazka - * - * 0/-1 - */ -int gg_image_request(struct gg_session *sess, uin_t recipient, int size, uint32_t crc32) -{ - struct gg_send_msg s; - struct gg_msg_image_request r; - char dummy = 0; - int res; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_image_request(%p, %d, %u, 0x%.4x);\n", sess, recipient, size, crc32); - - if (!sess) { - errno = EFAULT; - return -1; - } - - if (sess->state != GG_STATE_CONNECTED) { - errno = ENOTCONN; - return -1; - } - - if (size < 0) { - errno = EINVAL; - return -1; - } - - s.recipient = gg_fix32(recipient); - s.seq = gg_fix32(0); - s.msgclass = gg_fix32(GG_CLASS_MSG); - - r.flag = 0x04; - r.size = gg_fix32(size); - r.crc32 = gg_fix32(crc32); - - res = gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), &dummy, 1, &r, sizeof(r), NULL); - - if (!res) { - struct gg_image_queue *q = malloc(sizeof(*q)); - char *buf; - - if (!q) { - gg_debug(GG_DEBUG_MISC, "// gg_image_request() not enough memory for image queue\n"); - return -1; - } - - buf = malloc(size); - if (size && !buf) - { - gg_debug(GG_DEBUG_MISC, "// gg_image_request() not enough memory for image\n"); - free(q); - return -1; - } - - memset(q, 0, sizeof(*q)); - - q->sender = recipient; - q->size = size; - q->crc32 = crc32; - q->image = buf; - - if (!sess->images) - sess->images = q; - else { - struct gg_image_queue *qq; - - for (qq = sess->images; qq->next; qq = qq->next) - ; - - qq->next = q; - } - } - - return res; -} - -/* - * gg_image_reply() - * - * wysy³a ¿±dany obrazek. - * - * - sess - opis sesji - * - recipient - numer adresata - * - filename - nazwa pliku - * - image - bufor z obrazkiem - * - size - rozmiar obrazka - * - * 0/-1 - */ -int gg_image_reply(struct gg_session *sess, uin_t recipient, const char *filename, const char *image, int size) -{ - struct gg_msg_image_reply *r; - struct gg_send_msg s; - const char *tmp; - char buf[1910]; - int res = -1; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_image_reply(%p, %d, \"%s\", %p, %d);\n", sess, recipient, filename, image, size); - - if (!sess || !filename || !image) { - errno = EFAULT; - return -1; - } - - if (sess->state != GG_STATE_CONNECTED) { - errno = ENOTCONN; - return -1; - } - - if (size < 0) { - errno = EINVAL; - return -1; - } - - /* wytnij ¶cie¿ki, zostaw tylko nazwê pliku */ - while ((tmp = strrchr(filename, '/')) || (tmp = strrchr(filename, '\\'))) - filename = tmp + 1; - - if (strlen(filename) < 1 || strlen(filename) > 1024) { - errno = EINVAL; - return -1; - } - - s.recipient = gg_fix32(recipient); - s.seq = gg_fix32(0); - s.msgclass = gg_fix32(GG_CLASS_MSG); - - buf[0] = 0; - r = (void*) &buf[1]; - - r->flag = 0x05; - r->size = gg_fix32(size); - r->crc32 = gg_fix32(gg_crc32(0, image, size)); - - while (size > 0) { - int buflen, chunklen; - - /* \0 + struct gg_msg_image_reply */ - buflen = sizeof(struct gg_msg_image_reply) + 1; - - /* w pierwszym kawa³ku jest nazwa pliku */ - if (r->flag == 0x05) { - strcpy(buf + buflen, filename); - buflen += strlen(filename) + 1; - } - - chunklen = (size >= sizeof(buf) - buflen) ? (sizeof(buf) - buflen) : size; - - memcpy(buf + buflen, image, chunklen); - size -= chunklen; - image += chunklen; - - res = gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), buf, buflen + chunklen, NULL); - - if (res == -1) - break; - - r->flag = 0x06; - } - - return res; -} - -/* - * gg_send_message_ctcp() - * - * wysy³a wiadomo¶æ do innego u¿ytkownika. zwraca losowy numer - * sekwencyjny, który mo¿na zignorowaæ albo wykorzystaæ do potwierdzenia. - * - * - sess - opis sesji - * - msgclass - rodzaj wiadomo¶ci - * - recipient - numer adresata - * - message - tre¶æ wiadomo¶ci - * - message_len - d³ugo¶æ - * - * numer sekwencyjny wiadomo¶ci lub -1 w przypadku b³êdu. - */ -int gg_send_message_ctcp(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message, int message_len) -{ - struct gg_send_msg s; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_send_message_ctcp(%p, %d, %u, ...);\n", sess, msgclass, recipient); - - if (!sess) { - errno = EFAULT; - return -1; - } - - if (sess->state != GG_STATE_CONNECTED) { - errno = ENOTCONN; - return -1; - } - - s.recipient = gg_fix32(recipient); - s.seq = gg_fix32(0); - s.msgclass = gg_fix32(msgclass); - - return gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), message, message_len, NULL); -} - -/* - * gg_send_message() - * - * wysy³a wiadomo¶æ do innego u¿ytkownika. zwraca losowy numer - * sekwencyjny, który mo¿na zignorowaæ albo wykorzystaæ do potwierdzenia. - * - * - sess - opis sesji - * - msgclass - rodzaj wiadomo¶ci - * - recipient - numer adresata - * - message - tre¶æ wiadomo¶ci - * - * numer sekwencyjny wiadomo¶ci lub -1 w przypadku b³êdu. - */ -int gg_send_message(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message) -{ - gg_debug(GG_DEBUG_FUNCTION, "** gg_send_message(%p, %d, %u, %p)\n", sess, msgclass, recipient, message); - - return gg_send_message_richtext(sess, msgclass, recipient, message, NULL, 0); -} - -/* - * gg_send_message_richtext() - * - * wysy³a kolorow± wiadomo¶æ do innego u¿ytkownika. zwraca losowy numer - * sekwencyjny, który mo¿na zignorowaæ albo wykorzystaæ do potwierdzenia. - * - * - sess - opis sesji - * - msgclass - rodzaj wiadomo¶ci - * - recipient - numer adresata - * - message - tre¶æ wiadomo¶ci - * - format - informacje o formatowaniu - * - formatlen - d³ugo¶æ informacji o formatowaniu - * - * numer sekwencyjny wiadomo¶ci lub -1 w przypadku b³êdu. - */ -int gg_send_message_richtext(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message, const unsigned char *format, int formatlen) -{ - struct gg_send_msg s; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_send_message_richtext(%p, %d, %u, %p, %p, %d);\n", sess, msgclass, recipient, message, format, formatlen); - - if (!sess) { - errno = EFAULT; - return -1; - } - - if (sess->state != GG_STATE_CONNECTED) { - errno = ENOTCONN; - return -1; - } - - if (!message) { - errno = EFAULT; - return -1; - } - - s.recipient = gg_fix32(recipient); - if (!sess->seq) - sess->seq = 0x01740000 | (rand() & 0xffff); - s.seq = gg_fix32(sess->seq); - s.msgclass = gg_fix32(msgclass); - sess->seq += (rand() % 0x300) + 0x300; - - if (gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), message, strlen(message) + 1, format, formatlen, NULL) == -1) - return -1; - - return gg_fix32(s.seq); -} - -/* - * gg_send_message_confer() - * - * wysy³a wiadomo¶æ do kilku u¿ytkownikow (konferencja). zwraca losowy numer - * sekwencyjny, który mo¿na zignorowaæ albo wykorzystaæ do potwierdzenia. - * - * - sess - opis sesji - * - msgclass - rodzaj wiadomo¶ci - * - recipients_count - ilo¶æ adresatów - * - recipients - numerki adresatów - * - message - tre¶æ wiadomo¶ci - * - * numer sekwencyjny wiadomo¶ci lub -1 w przypadku b³êdu. - */ -int gg_send_message_confer(struct gg_session *sess, int msgclass, int recipients_count, uin_t *recipients, const unsigned char *message) -{ - gg_debug(GG_DEBUG_FUNCTION, "** gg_send_message_confer(%p, %d, %d, %p, %p);\n", sess, msgclass, recipients_count, recipients, message); - - return gg_send_message_confer_richtext(sess, msgclass, recipients_count, recipients, message, NULL, 0); -} - -/* - * gg_send_message_confer_richtext() - * - * wysy³a kolorow± wiadomo¶æ do kilku u¿ytkownikow (konferencja). zwraca - * losowy numer sekwencyjny, który mo¿na zignorowaæ albo wykorzystaæ do - * potwierdzenia. - * - * - sess - opis sesji - * - msgclass - rodzaj wiadomo¶ci - * - recipients_count - ilo¶æ adresatów - * - recipients - numerki adresatów - * - message - tre¶æ wiadomo¶ci - * - format - informacje o formatowaniu - * - formatlen - d³ugo¶æ informacji o formatowaniu - * - * numer sekwencyjny wiadomo¶ci lub -1 w przypadku b³êdu. - */ -int gg_send_message_confer_richtext(struct gg_session *sess, int msgclass, int recipients_count, uin_t *recipients, const unsigned char *message, const unsigned char *format, int formatlen) -{ - struct gg_send_msg s; - struct gg_msg_recipients r; - int i, j, k; - uin_t *recps; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_send_message_confer_richtext(%p, %d, %d, %p, %p, %p, %d);\n", sess, msgclass, recipients_count, recipients, message, format, formatlen); - - if (!sess) { - errno = EFAULT; - return -1; - } - - if (sess->state != GG_STATE_CONNECTED) { - errno = ENOTCONN; - return -1; - } - - if (!message || recipients_count <= 0 || recipients_count > 0xffff || !recipients) { - errno = EINVAL; - return -1; - } - - r.flag = 0x01; - r.count = gg_fix32(recipients_count - 1); - - if (!sess->seq) - sess->seq = 0x01740000 | (rand() & 0xffff); - s.seq = gg_fix32(sess->seq); - s.msgclass = gg_fix32(msgclass); - - recps = malloc(sizeof(uin_t) * recipients_count); - if (!recps) - return -1; - - for (i = 0; i < recipients_count; i++) { - - s.recipient = gg_fix32(recipients[i]); - - for (j = 0, k = 0; j < recipients_count; j++) - if (recipients[j] != recipients[i]) { - recps[k] = gg_fix32(recipients[j]); - k++; - } - - if (!i) - sess->seq += (rand() % 0x300) + 0x300; - - if (gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), message, strlen(message) + 1, &r, sizeof(r), recps, (recipients_count - 1) * sizeof(uin_t), format, formatlen, NULL) == -1) { - free(recps); - return -1; - } - } - - free(recps); - - return gg_fix32(s.seq); -} - -/* - * gg_ping() - * - * wysy³a do serwera pakiet ping. - * - * - sess - opis sesji - * - * 0, -1. - */ -int gg_ping(struct gg_session *sess) -{ - gg_debug(GG_DEBUG_FUNCTION, "** gg_ping(%p);\n", sess); - - if (!sess) { - errno = EFAULT; - return -1; - } - - if (sess->state != GG_STATE_CONNECTED) { - errno = ENOTCONN; - return -1; - } - - return gg_send_packet(sess, GG_PING, NULL); -} - -/* - * gg_notify_ex() - * - * wysy³a serwerowi listê kontaktów (wraz z odpowiadaj±cymi im typami userów), - * dziêki czemu wie, czyj stan nas interesuje. - * - * - sess - opis sesji - * - userlist - wska¼nik do tablicy numerów - * - types - wska¼nik do tablicy typów u¿ytkowników - * - count - ilo¶æ numerków - * - * 0, -1. - */ -int gg_notify_ex(struct gg_session *sess, uin_t *userlist, char *types, int count) -{ - struct gg_notify *n; - uin_t *u; - char *t; - int i, res = 0; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_notify_ex(%p, %p, %p, %d);\n", sess, userlist, types, count); - - if (!sess) { - errno = EFAULT; - return -1; - } - - if (sess->state != GG_STATE_CONNECTED) { - errno = ENOTCONN; - return -1; - } - - if (!userlist || !count) - return gg_send_packet(sess, GG_LIST_EMPTY, NULL); - - while (count > 0) { - int part_count, packet_type; - - if (count > 400) { - part_count = 400; - packet_type = GG_NOTIFY_FIRST; - } else { - part_count = count; - packet_type = GG_NOTIFY_LAST; - } - - if (!(n = (struct gg_notify*) malloc(sizeof(*n) * part_count))) - return -1; - - for (u = userlist, t = types, i = 0; i < part_count; u++, t++, i++) { - n[i].uin = gg_fix32(*u); - n[i].dunno1 = *t; - } - - if (gg_send_packet(sess, packet_type, n, sizeof(*n) * part_count, NULL) == -1) { - free(n); - res = -1; - break; - } - - count -= part_count; - userlist += part_count; - types += part_count; - - free(n); - } - - return res; -} - -/* - * gg_notify() - * - * wysy³a serwerowi listê kontaktów, dziêki czemu wie, czyj stan nas - * interesuje. - * - * - sess - opis sesji - * - userlist - wska¼nik do tablicy numerów - * - count - ilo¶æ numerków - * - * 0, -1. - */ -int gg_notify(struct gg_session *sess, uin_t *userlist, int count) -{ - struct gg_notify *n; - uin_t *u; - int i, res = 0; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_notify(%p, %p, %d);\n", sess, userlist, count); - - if (!sess) { - errno = EFAULT; - return -1; - } - - if (sess->state != GG_STATE_CONNECTED) { - errno = ENOTCONN; - return -1; - } - - if (!userlist || !count) - return gg_send_packet(sess, GG_LIST_EMPTY, NULL); - - while (count > 0) { - int part_count, packet_type; - - if (count > 400) { - part_count = 400; - packet_type = GG_NOTIFY_FIRST; - } else { - part_count = count; - packet_type = GG_NOTIFY_LAST; - } - - if (!(n = (struct gg_notify*) malloc(sizeof(*n) * part_count))) - return -1; - - for (u = userlist, i = 0; i < part_count; u++, i++) { - n[i].uin = gg_fix32(*u); - n[i].dunno1 = GG_USER_NORMAL; - } - - if (gg_send_packet(sess, packet_type, n, sizeof(*n) * part_count, NULL) == -1) { - res = -1; - free(n); - break; - } - - free(n); - - userlist += part_count; - count -= part_count; - } - - return res; -} - -/* - * gg_add_notify_ex() - * - * dodaje do listy kontaktów dany numer w trakcie po³±czenia. - * dodawanemu u¿ytkownikowi okre¶lamy jego typ (patrz protocol.html) - * - * - sess - opis sesji - * - uin - numer - * - type - typ - * - * 0, -1. - */ -int gg_add_notify_ex(struct gg_session *sess, uin_t uin, char type) -{ - struct gg_add_remove a; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_add_notify_ex(%p, %u, %d);\n", sess, uin, type); - - if (!sess) { - errno = EFAULT; - return -1; - } - - if (sess->state != GG_STATE_CONNECTED) { - errno = ENOTCONN; - return -1; - } - - a.uin = gg_fix32(uin); - a.dunno1 = type; - - return gg_send_packet(sess, GG_ADD_NOTIFY, &a, sizeof(a), NULL); -} - -/* - * gg_add_notify() - * - * dodaje do listy kontaktów dany numer w trakcie po³±czenia. - * - * - sess - opis sesji - * - uin - numer - * - * 0, -1. - */ -int gg_add_notify(struct gg_session *sess, uin_t uin) -{ - return gg_add_notify_ex(sess, uin, GG_USER_NORMAL); -} - -/* - * gg_remove_notify_ex() - * - * usuwa z listy kontaktów w trakcie po³±czenia. - * usuwanemu u¿ytkownikowi okre¶lamy jego typ (patrz protocol.html) - * - * - sess - opis sesji - * - uin - numer - * - type - typ - * - * 0, -1. - */ -int gg_remove_notify_ex(struct gg_session *sess, uin_t uin, char type) -{ - struct gg_add_remove a; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_remove_notify_ex(%p, %u, %d);\n", sess, uin, type); - - if (!sess) { - errno = EFAULT; - return -1; - } - - if (sess->state != GG_STATE_CONNECTED) { - errno = ENOTCONN; - return -1; - } - - a.uin = gg_fix32(uin); - a.dunno1 = type; - - return gg_send_packet(sess, GG_REMOVE_NOTIFY, &a, sizeof(a), NULL); -} - -/* - * gg_remove_notify() - * - * usuwa z listy kontaktów w trakcie po³±czenia. - * - * - sess - opis sesji - * - uin - numer - * - * 0, -1. - */ -int gg_remove_notify(struct gg_session *sess, uin_t uin) -{ - return gg_remove_notify_ex(sess, uin, GG_USER_NORMAL); -} - -/* - * gg_userlist_request() - * - * wysy³a ¿±danie/zapytanie listy kontaktów na serwerze. - * - * - sess - opis sesji - * - type - rodzaj zapytania/¿±dania - * - request - tre¶æ zapytania/¿±dania (mo¿e byæ NULL) - * - * 0, -1 - */ -int gg_userlist_request(struct gg_session *sess, char type, const char *request) -{ - int len; - - if (!sess) { - errno = EFAULT; - return -1; - } - - if (sess->state != GG_STATE_CONNECTED) { - errno = ENOTCONN; - return -1; - } - - if (!request) { - sess->userlist_blocks = 1; - return gg_send_packet(sess, GG_USERLIST_REQUEST, &type, sizeof(type), NULL); - } - - len = strlen(request); - - sess->userlist_blocks = 0; - - while (len > 2047) { - sess->userlist_blocks++; - - if (gg_send_packet(sess, GG_USERLIST_REQUEST, &type, sizeof(type), request, 2047, NULL) == -1) - return -1; - - if (type == GG_USERLIST_PUT) - type = GG_USERLIST_PUT_MORE; - - request += 2047; - len -= 2047; - } - - sess->userlist_blocks++; - - return gg_send_packet(sess, GG_USERLIST_REQUEST, &type, sizeof(type), request, len, NULL); -} - -/* - * Local variables: - * c-indentation-style: k&r - * c-basic-offset: 8 - * indent-tabs-mode: notnil - * End: - * - * vim: shiftwidth=8: - */ diff --git a/kopete/protocols/gadu/libgadu/libgadu.h b/kopete/protocols/gadu/libgadu/libgadu.h deleted file mode 100644 index 85c54953..00000000 --- a/kopete/protocols/gadu/libgadu/libgadu.h +++ /dev/null @@ -1,1310 +0,0 @@ -/* $Id$ */ - -/* - * (C) Copyright 2001-2003 Wojtek Kaniewski <wojtekka@irc.pl> - * Robert J. Wo¼ny <speedy@ziew.org> - * Arkadiusz Mi¶kiewicz <arekm@pld-linux.org> - * Tomasz Chiliñski <chilek@chilan.com> - * Piotr Wysocki <wysek@linux.bydg.org> - * Dawid Jarosz <dawjar@poczta.onet.pl> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License Version - * 2.1 as published by the Free Software Foundation. - * - * 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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. - */ - -#ifndef __GG_LIBGADU_H -#define __GG_LIBGADU_H - -#ifdef __cplusplus -#ifdef _WIN32 -#pragma pack(push, 1) -#endif -extern "C" { -#endif - -#include <libgadu-config.h> -#include <sys/types.h> -#include <stdio.h> -#include <stdarg.h> - -#ifdef __GG_LIBGADU_HAVE_OPENSSL -#include <openssl/ssl.h> -#endif - -/* - * typedef uin_t - * - * typ reprezentuj±cy numer osoby. - */ -typedef uint32_t uin_t; - -/* - * ogólna struktura opisuj±ca ró¿ne sesje. przydatna w klientach. - */ -#define gg_common_head(x) \ - int fd; /* podgl±dany deskryptor */ \ - int check; /* sprawdzamy zapis czy odczyt */ \ - int state; /* aktualny stan maszynki */ \ - int error; /* kod b³êdu dla GG_STATE_ERROR */ \ - int type; /* rodzaj sesji */ \ - int id; /* identyfikator */ \ - int timeout; /* sugerowany timeout w sekundach */ \ - int (*callback)(x*); /* callback przy zmianach */ \ - void (*destroy)(x*); /* funkcja niszczenia */ - -struct gg_common { - gg_common_head(struct gg_common) -}; - -struct gg_image_queue; - -/* - * struct gg_session - * - * struktura opisuj±ca dan± sesjê. tworzona przez gg_login(), zwalniana - * przez gg_free_session(). - */ -struct gg_session { - gg_common_head(struct gg_session) - - int async; /* czy po³±czenie jest asynchroniczne */ - int pid; /* pid procesu resolvera */ - int port; /* port, z którym siê ³±czymy */ - int seq; /* numer sekwencyjny ostatniej wiadomo¶ci */ - int last_pong; /* czas otrzymania ostatniego ping/pong */ - int last_event; /* czas otrzymania ostatniego pakietu */ - - struct gg_event *event; /* zdarzenie po ->callback() */ - - uint32_t proxy_addr; /* adres proxy, keszowany */ - uint16_t proxy_port; /* port proxy */ - - uint32_t hub_addr; /* adres huba po resolvniêciu */ - uint32_t server_addr; /* adres serwera, od huba */ - - uint32_t client_addr; /* adres klienta */ - uint16_t client_port; /* port, na którym klient s³ucha */ - - uint32_t external_addr; /* adres zewnetrzny klienta */ - uint16_t external_port; /* port zewnetrzny klienta */ - - uin_t uin; /* numerek klienta */ - char *password; /* i jego has³o. zwalniane automagicznie */ - - int initial_status; /* pocz±tkowy stan klienta */ - int status; /* aktualny stan klienta */ - - char *recv_buf; /* bufor na otrzymywane pakiety */ - int recv_done; /* ile ju¿ wczytano do bufora */ - int recv_left; /* i ile jeszcze trzeba wczytaæ */ - - int protocol_version; /* wersja u¿ywanego protoko³u */ - char *client_version; /* wersja u¿ywanego klienta */ - int last_sysmsg; /* ostatnia wiadomo¶æ systemowa */ - - char *initial_descr; /* pocz±tkowy opis stanu klienta */ - - void *resolver; /* wska¼nik na informacje resolvera */ - - char *header_buf; /* bufor na pocz±tek nag³ówka */ - unsigned int header_done;/* ile ju¿ mamy */ - -#ifdef __GG_LIBGADU_HAVE_OPENSSL - SSL *ssl; /* sesja TLS */ - SSL_CTX *ssl_ctx; /* kontekst sesji? */ -#else - void *ssl; /* zachowujemy ABI */ - void *ssl_ctx; -#endif - - int image_size; /* maksymalny rozmiar obrazków w KiB */ - - char *userlist_reply; /* fragment odpowiedzi listy kontaktów */ - - int userlist_blocks; /* na ile kawa³ków podzielono listê kontaktów */ - - struct gg_image_queue *images; /* aktualnie wczytywane obrazki */ -}; - -/* - * struct gg_http - * - * ogólna struktura opisuj±ca stan wszystkich operacji HTTP. tworzona - * przez gg_http_connect(), zwalniana przez gg_http_free(). - */ -struct gg_http { - gg_common_head(struct gg_http) - - int async; /* czy po³±czenie asynchroniczne */ - int pid; /* pid procesu resolvera */ - int port; /* port, z którym siê ³±czymy */ - - char *query; /* bufor zapytania http */ - char *header; /* bufor nag³ówka */ - int header_size; /* rozmiar wczytanego nag³ówka */ - char *body; /* bufor otrzymanych informacji */ - unsigned int body_size; /* oczekiwana ilo¶æ informacji */ - - void *data; /* dane danej operacji http */ - - char *user_data; /* dane u¿ytkownika, nie s± zwalniane przez gg_http_free() */ - - void *resolver; /* wska¼nik na informacje resolvera */ - - unsigned int body_done; /* ile ju¿ tre¶ci odebrano? */ -}; - -#ifdef __GNUC__ -#define GG_PACKED __attribute__ ((packed)) -#else -#define GG_PACKED -#endif - -#define GG_MAX_PATH 276 - -/* - * struct gg_file_info - * - * odpowiednik windowsowej struktury WIN32_FIND_DATA niezbêdnej przy - * wysy³aniu plików. - */ -struct gg_file_info { - uint32_t mode; /* dwFileAttributes */ - uint32_t ctime[2]; /* ftCreationTime */ - uint32_t atime[2]; /* ftLastAccessTime */ - uint32_t mtime[2]; /* ftLastWriteTime */ - uint32_t size_hi; /* nFileSizeHigh */ - uint32_t size; /* nFileSizeLow */ - uint32_t reserved0; /* dwReserved0 */ - uint32_t reserved1; /* dwReserved1 */ - unsigned char filename[GG_MAX_PATH - 14]; /* cFileName */ - unsigned char short_filename[14]; /* cAlternateFileName */ -} GG_PACKED; - -/* - * struct gg_dcc - * - * struktura opisuj±ca nas³uchuj±ce gniazdo po³±czeñ miêdzy klientami. - * tworzona przez gg_dcc_socket_create(), zwalniana przez gg_dcc_free(). - */ -struct gg_dcc { - gg_common_head(struct gg_dcc) - - struct gg_event *event; /* opis zdarzenia */ - - int active; /* czy to my siê ³±czymy? */ - int port; /* port, na którym siedzi */ - uin_t uin; /* uin klienta */ - uin_t peer_uin; /* uin drugiej strony */ - int file_fd; /* deskryptor pliku */ - unsigned int offset; /* offset w pliku */ - unsigned int chunk_size;/* rozmiar kawa³ka */ - unsigned int chunk_offset;/* offset w aktualnym kawa³ku */ - struct gg_file_info file_info; - /* informacje o pliku */ - int established; /* po³±czenie ustanowione */ - char *voice_buf; /* bufor na pakiet po³±czenia g³osowego */ - int incoming; /* po³±czenie przychodz±ce */ - char *chunk_buf; /* bufor na kawa³ek danych */ - uint32_t remote_addr; /* adres drugiej strony */ - uint16_t remote_port; /* port drugiej strony */ -}; - -/* - * enum gg_session_t - * - * rodzaje sesji. - */ -enum gg_session_t { - GG_SESSION_GG = 1, /* po³±czenie z serwerem gg */ - GG_SESSION_HTTP, /* ogólna sesja http */ - GG_SESSION_SEARCH, /* szukanie */ - GG_SESSION_REGISTER, /* rejestrowanie */ - GG_SESSION_REMIND, /* przypominanie has³a */ - GG_SESSION_PASSWD, /* zmiana has³a */ - GG_SESSION_CHANGE, /* zmiana informacji o sobie */ - GG_SESSION_DCC, /* ogólne po³±czenie DCC */ - GG_SESSION_DCC_SOCKET, /* nas³uchuj±cy socket */ - GG_SESSION_DCC_SEND, /* wysy³anie pliku */ - GG_SESSION_DCC_GET, /* odbieranie pliku */ - GG_SESSION_DCC_VOICE, /* rozmowa g³osowa */ - GG_SESSION_USERLIST_GET, /* pobieranie userlisty */ - GG_SESSION_USERLIST_PUT, /* wysy³anie userlisty */ - GG_SESSION_UNREGISTER, /* usuwanie konta */ - GG_SESSION_USERLIST_REMOVE, /* usuwanie userlisty */ - GG_SESSION_TOKEN, /* pobieranie tokenu */ - - GG_SESSION_USER0 = 256, /* zdefiniowana dla u¿ytkownika */ - GG_SESSION_USER1, /* j.w. */ - GG_SESSION_USER2, /* j.w. */ - GG_SESSION_USER3, /* j.w. */ - GG_SESSION_USER4, /* j.w. */ - GG_SESSION_USER5, /* j.w. */ - GG_SESSION_USER6, /* j.w. */ - GG_SESSION_USER7 /* j.w. */ -}; - -/* - * enum gg_state_t - * - * opisuje stan asynchronicznej maszyny. - */ -enum gg_state_t { - /* wspólne */ - GG_STATE_IDLE = 0, /* nie powinno wyst±piæ. */ - GG_STATE_RESOLVING, /* wywo³a³ gethostbyname() */ - GG_STATE_CONNECTING, /* wywo³a³ connect() */ - GG_STATE_READING_DATA, /* czeka na dane http */ - GG_STATE_ERROR, /* wyst±pi³ b³±d. kod w x->error */ - - /* gg_session */ - GG_STATE_CONNECTING_HUB, /* wywo³a³ connect() na huba */ - GG_STATE_CONNECTING_GG, /* wywo³a³ connect() na serwer */ - GG_STATE_READING_KEY, /* czeka na klucz */ - GG_STATE_READING_REPLY, /* czeka na odpowied¼ */ - GG_STATE_CONNECTED, /* po³±czy³ siê */ - - /* gg_http */ - GG_STATE_SENDING_QUERY, /* wysy³a zapytanie http */ - GG_STATE_READING_HEADER, /* czeka na nag³ówek http */ - GG_STATE_PARSING, /* przetwarza dane */ - GG_STATE_DONE, /* skoñczy³ */ - - /* gg_dcc */ - GG_STATE_LISTENING, /* czeka na po³±czenia */ - GG_STATE_READING_UIN_1, /* czeka na uin peera */ - GG_STATE_READING_UIN_2, /* czeka na swój uin */ - GG_STATE_SENDING_ACK, /* wysy³a potwierdzenie dcc */ - GG_STATE_READING_ACK, /* czeka na potwierdzenie dcc */ - GG_STATE_READING_REQUEST, /* czeka na komendê */ - GG_STATE_SENDING_REQUEST, /* wysy³a komendê */ - GG_STATE_SENDING_FILE_INFO, /* wysy³a informacje o pliku */ - GG_STATE_READING_PRE_FILE_INFO, /* czeka na pakiet przed file_info */ - GG_STATE_READING_FILE_INFO, /* czeka na informacje o pliku */ - GG_STATE_SENDING_FILE_ACK, /* wysy³a potwierdzenie pliku */ - GG_STATE_READING_FILE_ACK, /* czeka na potwierdzenie pliku */ - GG_STATE_SENDING_FILE_HEADER, /* wysy³a nag³ówek pliku */ - GG_STATE_READING_FILE_HEADER, /* czeka na nag³ówek */ - GG_STATE_GETTING_FILE, /* odbiera plik */ - GG_STATE_SENDING_FILE, /* wysy³a plik */ - GG_STATE_READING_VOICE_ACK, /* czeka na potwierdzenie voip */ - GG_STATE_READING_VOICE_HEADER, /* czeka na rodzaj bloku voip */ - GG_STATE_READING_VOICE_SIZE, /* czeka na rozmiar bloku voip */ - GG_STATE_READING_VOICE_DATA, /* czeka na dane voip */ - GG_STATE_SENDING_VOICE_ACK, /* wysy³a potwierdzenie voip */ - GG_STATE_SENDING_VOICE_REQUEST, /* wysy³a ¿±danie voip */ - GG_STATE_READING_TYPE, /* czeka na typ po³±czenia */ - - /* nowe. bez sensu jest to API. */ - GG_STATE_TLS_NEGOTIATION /* negocjuje po³±czenie TLS */ -}; - -/* - * enum gg_check_t - * - * informuje, co proces klienta powinien sprawdziæ na deskryptorze danego - * po³±czenia. - */ -enum gg_check_t { - GG_CHECK_NONE = 0, /* nic. nie powinno wyst±piæ */ - GG_CHECK_WRITE = 1, /* sprawdzamy mo¿liwo¶æ zapisu */ - GG_CHECK_READ = 2 /* sprawdzamy mo¿liwo¶æ odczytu */ -}; - -/* - * struct gg_login_params - * - * parametry gg_login(). przeniesiono do struktury, ¿eby unikn±æ problemów - * z ci±g³ymi zmianami API, gdy dodano co¶ nowego do protoko³u. - */ -struct gg_login_params { - uin_t uin; /* numerek */ - char *password; /* has³o */ - int async; /* asynchroniczne sockety? */ - int status; /* pocz±tkowy status klienta */ - char *status_descr; /* opis statusu */ - uint32_t server_addr; /* adres serwera gg */ - uint16_t server_port; /* port serwera gg */ - uint32_t client_addr; /* adres dcc klienta */ - uint16_t client_port; /* port dcc klienta */ - int protocol_version; /* wersja protoko³u */ - char *client_version; /* wersja klienta */ - int has_audio; /* czy ma d¼wiêk? */ - int last_sysmsg; /* ostatnia wiadomo¶æ systemowa */ - uint32_t external_addr; /* adres widziany na zewnatrz */ - uint16_t external_port; /* port widziany na zewnatrz */ - int tls; /* czy ³±czymy po TLS? */ - int image_size; /* maksymalny rozmiar obrazka w KiB */ - int era_omnix; /* czy udawaæ klienta era omnix? */ - - char dummy[6 * sizeof(int)]; /* miejsce na kolejnych 6 zmiennych, - * ¿eby z dodaniem parametru nie - * zmienia³ siê rozmiar struktury */ -}; - -struct gg_session *gg_login(const struct gg_login_params *p); -void gg_free_session(struct gg_session *sess); -void gg_logoff(struct gg_session *sess); -int gg_change_status(struct gg_session *sess, int status); -int gg_change_status_descr(struct gg_session *sess, int status, const char *descr); -int gg_change_status_descr_time(struct gg_session *sess, int status, const char *descr, int time); -int gg_send_message(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message); -int gg_send_message_richtext(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message, const unsigned char *format, int formatlen); -int gg_send_message_confer(struct gg_session *sess, int msgclass, int recipients_count, uin_t *recipients, const unsigned char *message); -int gg_send_message_confer_richtext(struct gg_session *sess, int msgclass, int recipients_count, uin_t *recipients, const unsigned char *message, const unsigned char *format, int formatlen); -int gg_send_message_ctcp(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message, int message_len); -int gg_ping(struct gg_session *sess); -int gg_userlist_request(struct gg_session *sess, char type, const char *request); -int gg_image_request(struct gg_session *sess, uin_t recipient, int size, uint32_t crc32); -int gg_image_reply(struct gg_session *sess, uin_t recipient, const char *filename, const char *image, int size); - -uint32_t gg_crc32(uint32_t crc, const unsigned char *buf, int len); - -struct gg_image_queue { - uin_t sender; /* nadawca obrazka */ - uint32_t size; /* rozmiar */ - uint32_t crc32; /* suma kontrolna */ - char *filename; /* nazwa pliku */ - char *image; /* bufor z obrazem */ - uint32_t done; /* ile ju¿ wczytano */ - - struct gg_image_queue *next; /* nastêpny na li¶cie */ -}; - -/* - * enum gg_event_t - * - * rodzaje zdarzeñ. - */ -enum gg_event_t { - GG_EVENT_NONE = 0, /* nic siê nie wydarzy³o */ - GG_EVENT_MSG, /* otrzymano wiadomo¶æ */ - GG_EVENT_NOTIFY, /* kto¶ siê pojawi³ */ - GG_EVENT_NOTIFY_DESCR, /* kto¶ siê pojawi³ z opisem */ - GG_EVENT_STATUS, /* kto¶ zmieni³ stan */ - GG_EVENT_ACK, /* potwierdzenie wys³ania wiadomo¶ci */ - GG_EVENT_PONG, /* pakiet pong */ - GG_EVENT_CONN_FAILED, /* po³±czenie siê nie uda³o */ - GG_EVENT_CONN_SUCCESS, /* po³±czenie siê powiod³o */ - GG_EVENT_DISCONNECT, /* serwer zrywa po³±czenie */ - - GG_EVENT_DCC_NEW, /* nowe po³±czenie miêdzy klientami */ - GG_EVENT_DCC_ERROR, /* b³±d po³±czenia miêdzy klientami */ - GG_EVENT_DCC_DONE, /* zakoñczono po³±czenie */ - GG_EVENT_DCC_CLIENT_ACCEPT, /* moment akceptacji klienta */ - GG_EVENT_DCC_CALLBACK, /* klient siê po³±czy³ na ¿±danie */ - GG_EVENT_DCC_NEED_FILE_INFO, /* nale¿y wype³niæ file_info */ - GG_EVENT_DCC_NEED_FILE_ACK, /* czeka na potwierdzenie pliku */ - GG_EVENT_DCC_NEED_VOICE_ACK, /* czeka na potwierdzenie rozmowy */ - GG_EVENT_DCC_VOICE_DATA, /* ramka danych rozmowy g³osowej */ - - GG_EVENT_PUBDIR50_SEARCH_REPLY, /* odpowiedz wyszukiwania */ - GG_EVENT_PUBDIR50_READ, /* odczytano w³asne dane z katalogu */ - GG_EVENT_PUBDIR50_WRITE, /* wpisano w³asne dane do katalogu */ - - GG_EVENT_STATUS60, /* kto¶ zmieni³ stan w GG 6.0 */ - GG_EVENT_NOTIFY60, /* kto¶ siê pojawi³ w GG 6.0 */ - GG_EVENT_USERLIST, /* odpowied¼ listy kontaktów w GG 6.0 */ - GG_EVENT_IMAGE_REQUEST, /* pro¶ba o wys³anie obrazka GG 6.0 */ - GG_EVENT_IMAGE_REPLY, /* podes³any obrazek GG 6.0 */ - GG_EVENT_DCC_ACK /* potwierdzenie transmisji */ -}; - -#define GG_EVENT_SEARCH50_REPLY GG_EVENT_PUBDIR50_SEARCH_REPLY - -/* - * enum gg_failure_t - * - * okre¶la powód nieudanego po³±czenia. - */ -enum gg_failure_t { - GG_FAILURE_RESOLVING = 1, /* nie znaleziono serwera */ - GG_FAILURE_CONNECTING, /* nie mo¿na siê po³±czyæ */ - GG_FAILURE_INVALID, /* serwer zwróci³ nieprawid³owe dane */ - GG_FAILURE_READING, /* zerwano po³±czenie podczas odczytu */ - GG_FAILURE_WRITING, /* zerwano po³±czenie podczas zapisu */ - GG_FAILURE_PASSWORD, /* nieprawid³owe has³o */ - GG_FAILURE_404, /* XXX nieu¿ywane */ - GG_FAILURE_TLS, /* b³±d negocjacji TLS */ - GG_FAILURE_NEED_EMAIL, /* serwer roz³±czy³ nas z pro¶b± o zmianê emaila */ - GG_FAILURE_INTRUDER, /* za du¿o prób po³±czenia siê z nieprawid³owym has³em */ - GG_FAILURE_UNAVAILABLE /* serwery s± wy³±czone */ -}; - -/* - * enum gg_error_t - * - * okre¶la rodzaj b³êdu wywo³anego przez dan± operacjê. nie zawiera - * przesadnie szczegó³owych informacji o powodzie b³êdu, by nie komplikowaæ - * obs³ugi b³êdów. je¶li wymagana jest wiêksza dok³adno¶æ, nale¿y sprawdziæ - * zawarto¶æ zmiennej errno. - */ -enum gg_error_t { - GG_ERROR_RESOLVING = 1, /* b³±d znajdowania hosta */ - GG_ERROR_CONNECTING, /* b³±d ³aczenia siê */ - GG_ERROR_READING, /* b³±d odczytu */ - GG_ERROR_WRITING, /* b³±d wysy³ania */ - - GG_ERROR_DCC_HANDSHAKE, /* b³±d negocjacji */ - GG_ERROR_DCC_FILE, /* b³±d odczytu/zapisu pliku */ - GG_ERROR_DCC_EOF, /* plik siê skoñczy³? */ - GG_ERROR_DCC_NET, /* b³±d wysy³ania/odbierania */ - GG_ERROR_DCC_REFUSED /* po³±czenie odrzucone przez usera */ -}; - -/* - * struktury dotycz±ce wyszukiwania w GG 5.0. NIE NALE¯Y SIÊ DO NICH - * ODWO£YWAÆ BEZPO¦REDNIO! do dostêpu do nich s³u¿± funkcje gg_pubdir50_*() - */ -struct gg_pubdir50_entry { - int num; - char *field; - char *value; -}; - -struct gg_pubdir50_s { - int count; - uin_t next; - int type; - uint32_t seq; - struct gg_pubdir50_entry *entries; - int entries_count; -}; - -/* - * typedef gg_pubdir_50_t - * - * typ opisuj±cy zapytanie lub wynik zapytania katalogu publicznego - * z protoko³u GG 5.0. nie nale¿y siê odwo³ywaæ bezpo¶rednio do jego - * pól -- s³u¿± do tego funkcje gg_pubdir50_*() - */ -typedef struct gg_pubdir50_s *gg_pubdir50_t; - -/* - * struct gg_event - * - * struktura opisuj±ca rodzaj zdarzenia. wychodzi z gg_watch_fd() lub - * z gg_dcc_watch_fd() - */ -struct gg_event { - int type; /* rodzaj zdarzenia -- gg_event_t */ - union { /* @event */ - struct gg_notify_reply *notify; /* informacje o li¶cie kontaktów -- GG_EVENT_NOTIFY */ - - enum gg_failure_t failure; /* b³±d po³±czenia -- GG_EVENT_FAILURE */ - - struct gg_dcc *dcc_new; /* nowe po³±czenie bezpo¶rednie -- GG_EVENT_DCC_NEW */ - - int dcc_error; /* b³±d po³±czenia bezpo¶redniego -- GG_EVENT_DCC_ERROR */ - - gg_pubdir50_t pubdir50; /* wynik operacji zwi±zanej z katalogiem publicznym -- GG_EVENT_PUBDIR50_* */ - - struct { /* @msg odebrano wiadomo¶æ -- GG_EVENT_MSG */ - uin_t sender; /* numer nadawcy */ - int msgclass; /* klasa wiadomo¶ci */ - time_t time; /* czas nadania */ - unsigned char *message; /* tre¶æ wiadomo¶ci */ - - int recipients_count; /* ilo¶æ odbiorców konferencji */ - uin_t *recipients; /* odbiorcy konferencji */ - - int formats_length; /* d³ugo¶æ informacji o formatowaniu tekstu */ - void *formats; /* informacje o formatowaniu tekstu */ - } msg; - - struct { /* @notify_descr informacje o li¶cie kontaktów z opisami stanu -- GG_EVENT_NOTIFY_DESCR */ - struct gg_notify_reply *notify; /* informacje o li¶cie kontaktów */ - char *descr; /* opis stanu */ - } notify_descr; - - struct { /* @status zmiana stanu -- GG_EVENT_STATUS */ - uin_t uin; /* numer */ - uint32_t status; /* nowy stan */ - char *descr; /* opis stanu */ - } status; - - struct { /* @status60 zmiana stanu -- GG_EVENT_STATUS60 */ - uin_t uin; /* numer */ - int status; /* nowy stan */ - uint32_t remote_ip; /* adres ip */ - uint16_t remote_port; /* port */ - int version; /* wersja klienta */ - int image_size; /* maksymalny rozmiar grafiki w KiB */ - char *descr; /* opis stanu */ - time_t time; /* czas powrotu */ - } status60; - - struct { /* @notify60 informacja o li¶cie kontaktów -- GG_EVENT_NOTIFY60 */ - uin_t uin; /* numer */ - int status; /* stan */ - uint32_t remote_ip; /* adres ip */ - uint16_t remote_port; /* port */ - int version; /* wersja klienta */ - int image_size; /* maksymalny rozmiar grafiki w KiB */ - char *descr; /* opis stanu */ - time_t time; /* czas powrotu */ - } *notify60; - - struct { /* @ack potwierdzenie wiadomo¶ci -- GG_EVENT_ACK */ - uin_t recipient; /* numer odbiorcy */ - int status; /* stan dorêczenia wiadomo¶ci */ - int seq; /* numer sekwencyjny wiadomo¶ci */ - } ack; - - struct { /* @dcc_voice_data otrzymano dane d¼wiêkowe -- GG_EVENT_DCC_VOICE_DATA */ - uint8_t *data; /* dane d¼wiêkowe */ - int length; /* ilo¶æ danych d¼wiêkowych */ - } dcc_voice_data; - - struct { /* @userlist odpowied¼ listy kontaktów serwera */ - char type; /* rodzaj odpowiedzi */ - char *reply; /* tre¶æ odpowiedzi */ - } userlist; - - struct { /* @image_request pro¶ba o obrazek */ - uin_t sender; /* nadawca pro¶by */ - uint32_t size; /* rozmiar obrazka */ - uint32_t crc32; /* suma kontrolna */ - } image_request; - - struct { /* @image_reply odpowied¼ z obrazkiem */ - uin_t sender; /* nadawca odpowiedzi */ - uint32_t size; /* rozmiar obrazka */ - uint32_t crc32; /* suma kontrolna */ - char *filename; /* nazwa pliku */ - char *image; /* bufor z obrazkiem */ - } image_reply; - } event; -}; - -struct gg_event *gg_watch_fd(struct gg_session *sess); -void gg_event_free(struct gg_event *e); -#define gg_free_event gg_event_free - -/* - * funkcje obs³ugi listy kontaktów. - */ -int gg_notify_ex(struct gg_session *sess, uin_t *userlist, char *types, int count); -int gg_notify(struct gg_session *sess, uin_t *userlist, int count); -int gg_add_notify_ex(struct gg_session *sess, uin_t uin, char type); -int gg_add_notify(struct gg_session *sess, uin_t uin); -int gg_remove_notify_ex(struct gg_session *sess, uin_t uin, char type); -int gg_remove_notify(struct gg_session *sess, uin_t uin); - -/* - * funkcje obs³ugi http. - */ -struct gg_http *gg_http_connect(const char *hostname, int port, int async, const char *method, const char *path, const char *header); -int gg_http_watch_fd(struct gg_http *h); -void gg_http_stop(struct gg_http *h); -void gg_http_free(struct gg_http *h); -void gg_http_free_fields(struct gg_http *h); -#define gg_free_http gg_http_free - -/* - * struktury opisuj±ca kryteria wyszukiwania dla gg_search(). nieaktualne, - * zast±pione przez gg_pubdir50_t. pozostawiono je dla zachowania ABI. - */ -struct gg_search_request { - int active; - unsigned int start; - char *nickname; - char *first_name; - char *last_name; - char *city; - int gender; - int min_birth; - int max_birth; - char *email; - char *phone; - uin_t uin; -}; - -struct gg_search { - int count; - struct gg_search_result *results; -}; - -struct gg_search_result { - uin_t uin; - char *first_name; - char *last_name; - char *nickname; - int born; - int gender; - char *city; - int active; -}; - -#define GG_GENDER_NONE 0 -#define GG_GENDER_FEMALE 1 -#define GG_GENDER_MALE 2 - -/* - * funkcje wyszukiwania. - */ -struct gg_http *gg_search(const struct gg_search_request *r, int async); -int gg_search_watch_fd(struct gg_http *f); -void gg_free_search(struct gg_http *f); -#define gg_search_free gg_free_search - -const struct gg_search_request *gg_search_request_mode_0(char *nickname, char *first_name, char *last_name, char *city, int gender, int min_birth, int max_birth, int active, int start); -const struct gg_search_request *gg_search_request_mode_1(char *email, int active, int start); -const struct gg_search_request *gg_search_request_mode_2(char *phone, int active, int start); -const struct gg_search_request *gg_search_request_mode_3(uin_t uin, int active, int start); -void gg_search_request_free(struct gg_search_request *r); - -/* - * funkcje obs³ugi katalogu publicznego zgodne z GG 5.0. tym razem funkcje - * zachowuj± pewien poziom abstrakcji, ¿eby unikn±æ zmian ABI przy zmianach - * w protokole. - * - * NIE NALE¯Y SIÊ ODWO£YWAÆ DO PÓL gg_pubdir50_t BEZPO¦REDNIO! - */ -uint32_t gg_pubdir50(struct gg_session *sess, gg_pubdir50_t req); -gg_pubdir50_t gg_pubdir50_new(int type); -int gg_pubdir50_add(gg_pubdir50_t req, const char *field, const char *value); -int gg_pubdir50_seq_set(gg_pubdir50_t req, uint32_t seq); -const char *gg_pubdir50_get(gg_pubdir50_t res, int num, const char *field); -int gg_pubdir50_type(gg_pubdir50_t res); -int gg_pubdir50_count(gg_pubdir50_t res); -uin_t gg_pubdir50_next(gg_pubdir50_t res); -uint32_t gg_pubdir50_seq(gg_pubdir50_t res); -void gg_pubdir50_free(gg_pubdir50_t res); - -#define GG_PUBDIR50_UIN "FmNumber" -#define GG_PUBDIR50_STATUS "FmStatus" -#define GG_PUBDIR50_FIRSTNAME "firstname" -#define GG_PUBDIR50_LASTNAME "lastname" -#define GG_PUBDIR50_NICKNAME "nickname" -#define GG_PUBDIR50_BIRTHYEAR "birthyear" -#define GG_PUBDIR50_CITY "city" -#define GG_PUBDIR50_GENDER "gender" -#define GG_PUBDIR50_GENDER_FEMALE "1" -#define GG_PUBDIR50_GENDER_MALE "2" -#define GG_PUBDIR50_GENDER_SET_FEMALE "2" -#define GG_PUBDIR50_GENDER_SET_MALE "1" -#define GG_PUBDIR50_ACTIVE "ActiveOnly" -#define GG_PUBDIR50_ACTIVE_TRUE "1" -#define GG_PUBDIR50_START "fmstart" -#define GG_PUBDIR50_FAMILYNAME "familyname" -#define GG_PUBDIR50_FAMILYCITY "familycity" - -int gg_pubdir50_handle_reply(struct gg_event *e, const char *packet, int length); - -/* - * struct gg_pubdir - * - * operacje na katalogu publicznym. - */ -struct gg_pubdir { - int success; /* czy siê uda³o */ - uin_t uin; /* otrzymany numerek. 0 je¶li b³±d */ -}; - -/* ogólne funkcje, nie powinny byæ u¿ywane */ -int gg_pubdir_watch_fd(struct gg_http *f); -void gg_pubdir_free(struct gg_http *f); -#define gg_free_pubdir gg_pubdir_free - -struct gg_token { - int width; /* szeroko¶æ obrazka */ - int height; /* wysoko¶æ obrazka */ - int length; /* ilo¶æ znaków w tokenie */ - char *tokenid; /* id tokenu */ -}; - -/* funkcje dotycz±ce tokenów */ -struct gg_http *gg_token(int async); -int gg_token_watch_fd(struct gg_http *h); -void gg_token_free(struct gg_http *h); - -/* rejestracja nowego numerka */ -struct gg_http *gg_register(const char *email, const char *password, int async); -struct gg_http *gg_register2(const char *email, const char *password, const char *qa, int async); -struct gg_http *gg_register3(const char *email, const char *password, const char *tokenid, const char *tokenval, int async); -#define gg_register_watch_fd gg_pubdir_watch_fd -#define gg_register_free gg_pubdir_free -#define gg_free_register gg_pubdir_free - -struct gg_http *gg_unregister(uin_t uin, const char *password, const char *email, int async); -struct gg_http *gg_unregister2(uin_t uin, const char *password, const char *qa, int async); -struct gg_http *gg_unregister3(uin_t uin, const char *password, const char *tokenid, const char *tokenval, int async); -#define gg_unregister_watch_fd gg_pubdir_watch_fd -#define gg_unregister_free gg_pubdir_free - -/* przypomnienie has³a e-mailem */ -struct gg_http *gg_remind_passwd(uin_t uin, int async); -struct gg_http *gg_remind_passwd2(uin_t uin, const char *tokenid, const char *tokenval, int async); -struct gg_http *gg_remind_passwd3(uin_t uin, const char *email, const char *tokenid, const char *tokenval, int async); -#define gg_remind_passwd_watch_fd gg_pubdir_watch_fd -#define gg_remind_passwd_free gg_pubdir_free -#define gg_free_remind_passwd gg_pubdir_free - -/* zmiana has³a */ -struct gg_http *gg_change_passwd(uin_t uin, const char *passwd, const char *newpasswd, const char *newemail, int async); -struct gg_http *gg_change_passwd2(uin_t uin, const char *passwd, const char *newpasswd, const char *email, const char *newemail, int async); -struct gg_http *gg_change_passwd3(uin_t uin, const char *passwd, const char *newpasswd, const char *qa, int async); -struct gg_http *gg_change_passwd4(uin_t uin, const char *email, const char *passwd, const char *newpasswd, const char *tokenid, const char *tokenval, int async); -#define gg_change_passwd_free gg_pubdir_free -#define gg_free_change_passwd gg_pubdir_free - -/* - * struct gg_change_info_request - * - * opis ¿±dania zmiany informacji w katalogu publicznym. - */ -struct gg_change_info_request { - char *first_name; /* imiê */ - char *last_name; /* nazwisko */ - char *nickname; /* pseudonim */ - char *email; /* email */ - int born; /* rok urodzenia */ - int gender; /* p³eæ */ - char *city; /* miasto */ -}; - -struct gg_change_info_request *gg_change_info_request_new(const char *first_name, const char *last_name, const char *nickname, const char *email, int born, int gender, const char *city); -void gg_change_info_request_free(struct gg_change_info_request *r); - -struct gg_http *gg_change_info(uin_t uin, const char *passwd, const struct gg_change_info_request *request, int async); -#define gg_change_pubdir_watch_fd gg_pubdir_watch_fd -#define gg_change_pubdir_free gg_pubdir_free -#define gg_free_change_pubdir gg_pubdir_free - -/* - * funkcje dotycz±ce listy kontaktów na serwerze. - */ -struct gg_http *gg_userlist_get(uin_t uin, const char *password, int async); -int gg_userlist_get_watch_fd(struct gg_http *f); -void gg_userlist_get_free(struct gg_http *f); - -struct gg_http *gg_userlist_put(uin_t uin, const char *password, const char *contacts, int async); -int gg_userlist_put_watch_fd(struct gg_http *f); -void gg_userlist_put_free(struct gg_http *f); - -struct gg_http *gg_userlist_remove(uin_t uin, const char *password, int async); -int gg_userlist_remove_watch_fd(struct gg_http *f); -void gg_userlist_remove_free(struct gg_http *f); - - - -/* - * funkcje dotycz±ce komunikacji miêdzy klientami. - */ -extern int gg_dcc_port; /* port, na którym nas³uchuje klient */ -extern unsigned long gg_dcc_ip; /* adres, na którym nas³uchuje klient */ - -int gg_dcc_request(struct gg_session *sess, uin_t uin); - -struct gg_dcc *gg_dcc_send_file(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin); -struct gg_dcc *gg_dcc_get_file(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin); -struct gg_dcc *gg_dcc_voice_chat(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin); -void gg_dcc_set_type(struct gg_dcc *d, int type); -int gg_dcc_fill_file_info(struct gg_dcc *d, const char *filename); -int gg_dcc_fill_file_info2(struct gg_dcc *d, const char *filename, const char *local_filename); -int gg_dcc_voice_send(struct gg_dcc *d, char *buf, int length); - -#define GG_DCC_VOICE_FRAME_LENGTH 195 -#define GG_DCC_VOICE_FRAME_LENGTH_505 326 - -struct gg_dcc *gg_dcc_socket_create(uin_t uin, uint16_t port); -#define gg_dcc_socket_free gg_free_dcc -#define gg_dcc_socket_watch_fd gg_dcc_watch_fd - -struct gg_event *gg_dcc_watch_fd(struct gg_dcc *d); - -void gg_dcc_free(struct gg_dcc *c); -#define gg_free_dcc gg_dcc_free - -/* - * je¶li chcemy sobie podebugowaæ, wystarczy ustawiæ `gg_debug_level'. - * niestety w miarê przybywania wpisów `gg_debug(...)' nie chcia³o mi - * siê ustawiaæ odpowiednich leveli, wiêc wiêkszo¶æ sz³a do _MISC. - */ -extern int gg_debug_level; /* poziom debugowania. mapa bitowa sta³ych GG_DEBUG_* */ - -/* - * mo¿na podaæ wska¼nik do funkcji obs³uguj±cej wywo³ania gg_debug(). - * nieoficjalne, nieudokumentowane, mo¿e siê zmieniæ. je¶li kto¶ jest - * zainteresowany, niech da znaæ na ekg-devel. - */ -extern void (*gg_debug_handler)(int level, const char *format, va_list ap); - -/* - * mo¿na podaæ plik, do którego bêd± zapisywane teksty z gg_debug(). - */ -extern FILE *gg_debug_file; - -#define GG_DEBUG_NET 1 -#define GG_DEBUG_TRAFFIC 2 -#define GG_DEBUG_DUMP 4 -#define GG_DEBUG_FUNCTION 8 -#define GG_DEBUG_MISC 16 - -#ifdef GG_DEBUG_DISABLE -#define gg_debug(x, y...) do { } while(0) -#else -void gg_debug(int level, const char *format, ...); -#endif - -const char *gg_libgadu_version(void); - -/* - * konfiguracja http proxy. - */ -extern int gg_proxy_enabled; /* w³±cza obs³ugê proxy */ -extern char *gg_proxy_host; /* okre¶la adres serwera proxy */ -extern int gg_proxy_port; /* okre¶la port serwera proxy */ -extern char *gg_proxy_username; /* okre¶la nazwê u¿ytkownika przy autoryzacji serwera proxy */ -extern char *gg_proxy_password; /* okre¶la has³o u¿ytkownika przy autoryzacji serwera proxy */ -extern int gg_proxy_http_only; /* w³±cza obs³ugê proxy wy³±cznie dla us³ug HTTP */ - - -/* - * adres, z którego ¶lemy pakiety (np ³±czymy siê z serwerem) - * u¿ywany przy gg_connect() - */ -extern unsigned long gg_local_ip; -/* - * ------------------------------------------------------------------------- - * poni¿ej znajduj± siê wewnêtrzne sprawy biblioteki. zwyk³y klient nie - * powinien ich w ogóle ruszaæ, bo i nie ma po co. wszystko mo¿na za³atwiæ - * procedurami wy¿szego poziomu, których definicje znajduj± siê na pocz±tku - * tego pliku. - * ------------------------------------------------------------------------- - */ - -#ifdef __GG_LIBGADU_HAVE_PTHREAD -int gg_resolve_pthread(int *fd, void **resolver, const char *hostname); -#endif - -#ifdef _WIN32 -int gg_thread_socket(int thread_id, int socket); -#endif - -int gg_resolve(int *fd, int *pid, const char *hostname); - -#ifdef __GNUC__ -char *gg_saprintf(const char *format, ...) __attribute__ ((format (printf, 1, 2))); -#else -char *gg_saprintf(const char *format, ...); -#endif - -char *gg_vsaprintf(const char *format, va_list ap); - -#define gg_alloc_sprintf gg_saprintf - -char *gg_get_line(char **ptr); - -int gg_connect(void *addr, int port, int async); -struct in_addr *gg_gethostbyname(const char *hostname); -char *gg_read_line(int sock, char *buf, int length); -void gg_chomp(char *line); -char *gg_urlencode(const char *str); -int gg_http_hash(const char *format, ...); -int gg_read(struct gg_session *sess, char *buf, int length); -int gg_write(struct gg_session *sess, const char *buf, int length); -void *gg_recv_packet(struct gg_session *sess); -int gg_send_packet(struct gg_session *sess, int type, ...); -unsigned int gg_login_hash(const unsigned char *password, unsigned int seed); -uint32_t gg_fix32(uint32_t x); -uint16_t gg_fix16(uint16_t x); -#define fix16 gg_fix16 -#define fix32 gg_fix32 -char *gg_proxy_auth(void); -char *gg_base64_encode(const char *buf); -char *gg_base64_decode(const char *buf); -int gg_image_queue_remove(struct gg_session *s, struct gg_image_queue *q, int freeq); - -#define GG_APPMSG_HOST "appmsg.gadu-gadu.pl" -#define GG_APPMSG_PORT 80 -#define GG_PUBDIR_HOST "pubdir.gadu-gadu.pl" -#define GG_PUBDIR_PORT 80 -#define GG_REGISTER_HOST "register.gadu-gadu.pl" -#define GG_REGISTER_PORT 80 -#define GG_REMIND_HOST "retr.gadu-gadu.pl" -#define GG_REMIND_PORT 80 - -#define GG_DEFAULT_PORT 8074 -#define GG_HTTPS_PORT 443 -#define GG_HTTP_USERAGENT "Mozilla/4.7 [en] (Win98; I)" - -#define GG_DEFAULT_CLIENT_VERSION "6, 1, 0, 158" -#define GG_DEFAULT_PROTOCOL_VERSION 0x24 -#define GG_DEFAULT_TIMEOUT 30 -#define GG_HAS_AUDIO_MASK 0x40000000 -#define GG_ERA_OMNIX_MASK 0x04000000 -#define GG_LIBGADU_VERSION "CVS" - -#define GG_DEFAULT_DCC_PORT 1550 - -struct gg_header { - uint32_t type; /* typ pakietu */ - uint32_t length; /* d³ugo¶æ reszty pakietu */ -} GG_PACKED; - -#define GG_WELCOME 0x0001 -#define GG_NEED_EMAIL 0x0014 - -struct gg_welcome { - uint32_t key; /* klucz szyfrowania has³a */ -} GG_PACKED; - -#define GG_LOGIN 0x000c - -struct gg_login { - uint32_t uin; /* mój numerek */ - uint32_t hash; /* hash has³a */ - uint32_t status; /* status na dzieñ dobry */ - uint32_t version; /* moja wersja klienta */ - uint32_t local_ip; /* mój adres ip */ - uint16_t local_port; /* port, na którym s³ucham */ -} GG_PACKED; - -#define GG_LOGIN_EXT 0x0013 - -struct gg_login_ext { - uint32_t uin; /* mój numerek */ - uint32_t hash; /* hash has³a */ - uint32_t status; /* status na dzieñ dobry */ - uint32_t version; /* moja wersja klienta */ - uint32_t local_ip; /* mój adres ip */ - uint16_t local_port; /* port, na którym s³ucham */ - uint32_t external_ip; /* zewnêtrzny adres ip */ - uint16_t external_port; /* zewnêtrzny port */ -} GG_PACKED; - -#define GG_LOGIN60 0x0015 - -struct gg_login60 { - uint32_t uin; /* mój numerek */ - uint32_t hash; /* hash has³a */ - uint32_t status; /* status na dzieñ dobry */ - uint32_t version; /* moja wersja klienta */ - uint8_t dunno1; /* 0x00 */ - uint32_t local_ip; /* mój adres ip */ - uint16_t local_port; /* port, na którym s³ucham */ - uint32_t external_ip; /* zewnêtrzny adres ip */ - uint16_t external_port; /* zewnêtrzny port */ - uint8_t image_size; /* maksymalny rozmiar grafiki w KiB */ - uint8_t dunno2; /* 0xbe */ -} GG_PACKED; - -#define GG_LOGIN_OK 0x0003 - -#define GG_LOGIN_FAILED 0x0009 - -#define GG_PUBDIR50_REQUEST 0x0014 - -#define GG_PUBDIR50_WRITE 0x01 -#define GG_PUBDIR50_READ 0x02 -#define GG_PUBDIR50_SEARCH 0x03 -#define GG_PUBDIR50_SEARCH_REQUEST GG_PUBDIR50_SEARCH -#define GG_PUBDIR50_SEARCH_REPLY 0x05 - -struct gg_pubdir50_request { - uint8_t type; /* GG_PUBDIR50_* */ - uint32_t seq; /* czas wys³ania zapytania */ -} GG_PACKED; - -#define GG_PUBDIR50_REPLY 0x000e - -struct gg_pubdir50_reply { - uint8_t type; /* GG_PUBDIR50_* */ - uint32_t seq; /* czas wys³ania zapytania */ -} GG_PACKED; - -#define GG_NEW_STATUS 0x0002 - -#define GG_STATUS_NOT_AVAIL 0x0001 /* niedostêpny */ -#define GG_STATUS_NOT_AVAIL_DESCR 0x0015 /* niedostêpny z opisem (4.8) */ -#define GG_STATUS_AVAIL 0x0002 /* dostêpny */ -#define GG_STATUS_AVAIL_DESCR 0x0004 /* dostêpny z opisem (4.9) */ -#define GG_STATUS_BUSY 0x0003 /* zajêty */ -#define GG_STATUS_BUSY_DESCR 0x0005 /* zajêty z opisem (4.8) */ -#define GG_STATUS_INVISIBLE 0x0014 /* niewidoczny (4.6) */ -#define GG_STATUS_INVISIBLE_DESCR 0x0016 /* niewidoczny z opisem (4.9) */ -#define GG_STATUS_BLOCKED 0x0006 /* zablokowany */ - -#define GG_STATUS_FRIENDS_MASK 0x8000 /* tylko dla znajomych (4.6) */ - -#define GG_STATUS_DESCR_MAXSIZE 70 - -/* - * makra do ³atwego i szybkiego sprawdzania stanu. - */ - -/* GG_S_F() tryb tylko dla znajomych */ -#define GG_S_F(x) (((x) & GG_STATUS_FRIENDS_MASK) != 0) - -/* GG_S() stan bez uwzglêdnienia trybu tylko dla znajomych */ -#define GG_S(x) ((x) & ~GG_STATUS_FRIENDS_MASK) - -/* GG_S_A() dostêpny */ -#define GG_S_A(x) (GG_S(x) == GG_STATUS_AVAIL || GG_S(x) == GG_STATUS_AVAIL_DESCR) - -/* GG_S_NA() niedostêpny */ -#define GG_S_NA(x) (GG_S(x) == GG_STATUS_NOT_AVAIL || GG_S(x) == GG_STATUS_NOT_AVAIL_DESCR) - -/* GG_S_B() zajêty */ -#define GG_S_B(x) (GG_S(x) == GG_STATUS_BUSY || GG_S(x) == GG_STATUS_BUSY_DESCR) - -/* GG_S_I() niewidoczny */ -#define GG_S_I(x) (GG_S(x) == GG_STATUS_INVISIBLE || GG_S(x) == GG_STATUS_INVISIBLE_DESCR) - -/* GG_S_D() stan opisowy */ -#define GG_S_D(x) (GG_S(x) == GG_STATUS_NOT_AVAIL_DESCR || GG_S(x) == GG_STATUS_AVAIL_DESCR || GG_S(x) == GG_STATUS_BUSY_DESCR || GG_S(x) == GG_STATUS_INVISIBLE_DESCR) - -/* GG_S_BL() blokowany lub blokuj±cy */ -#define GG_S_BL(x) (GG_S(x) == GG_STATUS_BLOCKED) - -struct gg_new_status { - uint32_t status; /* na jaki zmieniæ? */ -} GG_PACKED; - -#define GG_NOTIFY_FIRST 0x000f -#define GG_NOTIFY_LAST 0x0010 - -#define GG_NOTIFY 0x0010 - -struct gg_notify { - uint32_t uin; /* numerek danej osoby */ - uint8_t dunno1; /* rodzaj wpisu w li¶cie */ -} GG_PACKED; - -#define GG_USER_OFFLINE 0x01 /* bêdziemy niewidoczni dla u¿ytkownika */ -#define GG_USER_NORMAL 0x03 /* zwyk³y u¿ytkownik */ -#define GG_USER_BLOCKED 0x04 /* zablokowany u¿ytkownik */ - -#define GG_LIST_EMPTY 0x0012 - -#define GG_NOTIFY_REPLY 0x000c /* tak, to samo co GG_LOGIN */ - -struct gg_notify_reply { - uint32_t uin; /* numerek */ - uint32_t status; /* status danej osoby */ - uint32_t remote_ip; /* adres ip delikwenta */ - uint16_t remote_port; /* port, na którym s³ucha klient */ - uint32_t version; /* wersja klienta */ - uint16_t dunno2; /* znowu port? */ -} GG_PACKED; - -#define GG_NOTIFY_REPLY60 0x0011 - -struct gg_notify_reply60 { - uint32_t uin; /* numerek plus flagi w MSB */ - uint8_t status; /* status danej osoby */ - uint32_t remote_ip; /* adres ip delikwenta */ - uint16_t remote_port; /* port, na którym s³ucha klient */ - uint8_t version; /* wersja klienta */ - uint8_t image_size; /* maksymalny rozmiar grafiki w KiB */ - uint8_t dunno1; /* 0x00 */ -} GG_PACKED; - -#define GG_STATUS60 0x000f - -struct gg_status60 { - uint32_t uin; /* numerek plus flagi w MSB */ - uint8_t status; /* status danej osoby */ - uint32_t remote_ip; /* adres ip delikwenta */ - uint16_t remote_port; /* port, na którym s³ucha klient */ - uint8_t version; /* wersja klienta */ - uint8_t image_size; /* maksymalny rozmiar grafiki w KiB */ - uint8_t dunno1; /* 0x00 */ -} GG_PACKED; - -#define GG_ADD_NOTIFY 0x000d -#define GG_REMOVE_NOTIFY 0x000e - -struct gg_add_remove { - uint32_t uin; /* numerek */ - uint8_t dunno1; /* bitmapa */ -} GG_PACKED; - -#define GG_STATUS 0x0002 - -struct gg_status { - uint32_t uin; /* numerek */ - uint32_t status; /* nowy stan */ -} GG_PACKED; - -#define GG_SEND_MSG 0x000b - -#define GG_CLASS_QUEUED 0x0001 -#define GG_CLASS_OFFLINE GG_CLASS_QUEUED -#define GG_CLASS_MSG 0x0004 -#define GG_CLASS_CHAT 0x0008 -#define GG_CLASS_CTCP 0x0010 -#define GG_CLASS_ACK 0x0020 -#define GG_CLASS_EXT GG_CLASS_ACK /* kompatybilno¶æ wstecz */ - -#define GG_MSG_MAXSIZE 2000 - -struct gg_send_msg { - uint32_t recipient; - uint32_t seq; - uint32_t msgclass; -} GG_PACKED; - -struct gg_msg_richtext { - uint8_t flag; - uint16_t length; -} GG_PACKED; - -struct gg_msg_richtext_format { - uint16_t position; - uint8_t font; -} GG_PACKED; - -struct gg_msg_richtext_image { - uint16_t unknown1; - uint32_t size; - uint32_t crc32; -} GG_PACKED; - -#define GG_FONT_BOLD 0x01 -#define GG_FONT_ITALIC 0x02 -#define GG_FONT_UNDERLINE 0x04 -#define GG_FONT_COLOR 0x08 -#define GG_FONT_IMAGE 0x80 - -struct gg_msg_richtext_color { - uint8_t red; - uint8_t green; - uint8_t blue; -} GG_PACKED; - -struct gg_msg_recipients { - uint8_t flag; - uint32_t count; -} GG_PACKED; - -struct gg_msg_image_request { - uint8_t flag; - uint32_t size; - uint32_t crc32; -} GG_PACKED; - -struct gg_msg_image_reply { - uint8_t flag; - uint32_t size; - uint32_t crc32; - /* char filename[]; */ - /* char image[]; */ -} GG_PACKED; - -#define GG_SEND_MSG_ACK 0x0005 - -#define GG_ACK_BLOCKED 0x0001 -#define GG_ACK_DELIVERED 0x0002 -#define GG_ACK_QUEUED 0x0003 -#define GG_ACK_MBOXFULL 0x0004 -#define GG_ACK_NOT_DELIVERED 0x0006 - -struct gg_send_msg_ack { - uint32_t status; - uint32_t recipient; - uint32_t seq; -} GG_PACKED; - -#define GG_RECV_MSG 0x000a - -struct gg_recv_msg { - uint32_t sender; - uint32_t seq; - uint32_t time; - uint32_t msgclass; -} GG_PACKED; - -#define GG_PING 0x0008 - -#define GG_PONG 0x0007 - -#define GG_DISCONNECTING 0x000b - -#define GG_USERLIST_REQUEST 0x0016 - -#define GG_USERLIST_PUT 0x00 -#define GG_USERLIST_PUT_MORE 0x01 -#define GG_USERLIST_GET 0x02 - -struct gg_userlist_request { - uint8_t type; -} GG_PACKED; - -#define GG_USERLIST_REPLY 0x0010 - -#define GG_USERLIST_PUT_REPLY 0x00 -#define GG_USERLIST_PUT_MORE_REPLY 0x02 -#define GG_USERLIST_GET_REPLY 0x06 -#define GG_USERLIST_GET_MORE_REPLY 0x04 - -struct gg_userlist_reply { - uint8_t type; -} GG_PACKED; - -/* - * pakiety, sta³e, struktury dla DCC - */ - -struct gg_dcc_tiny_packet { - uint8_t type; /* rodzaj pakietu */ -} GG_PACKED; - -struct gg_dcc_small_packet { - uint32_t type; /* rodzaj pakietu */ -} GG_PACKED; - -struct gg_dcc_big_packet { - uint32_t type; /* rodzaj pakietu */ - uint32_t dunno1; /* niewiadoma */ - uint32_t dunno2; /* niewiadoma */ -} GG_PACKED; - -/* - * póki co, nie znamy dok³adnie protoko³u. nie wiemy, co czemu odpowiada. - * nazwy s± niepowa¿ne i tymczasowe. - */ -#define GG_DCC_WANT_FILE 0x0003 /* peer chce plik */ -#define GG_DCC_HAVE_FILE 0x0001 /* wiêc mu damy */ -#define GG_DCC_HAVE_FILEINFO 0x0003 /* niech ma informacje o pliku */ -#define GG_DCC_GIMME_FILE 0x0006 /* peer jest pewny */ -#define GG_DCC_CATCH_FILE 0x0002 /* wysy³amy plik */ - -#define GG_DCC_FILEATTR_READONLY 0x0020 - -#define GG_DCC_TIMEOUT_SEND 1800 /* 30 minut */ -#define GG_DCC_TIMEOUT_GET 1800 /* 30 minut */ -#define GG_DCC_TIMEOUT_FILE_ACK 300 /* 5 minut */ -#define GG_DCC_TIMEOUT_VOICE_ACK 300 /* 5 minut */ - -#ifdef __cplusplus -} -#ifdef _WIN32 -#pragma pack(pop) -#endif -#endif - -#endif /* __GG_LIBGADU_H */ - -/* - * Local variables: - * c-indentation-style: k&r - * c-basic-offset: 8 - * indent-tabs-mode: notnil - * End: - * - * vim: shiftwidth=8: - */ diff --git a/kopete/protocols/gadu/libgadu/pubdir.c b/kopete/protocols/gadu/libgadu/pubdir.c deleted file mode 100644 index 2741ea4b..00000000 --- a/kopete/protocols/gadu/libgadu/pubdir.c +++ /dev/null @@ -1,689 +0,0 @@ -/* $Id$ */ - -/* - * (C) Copyright 2001-2006 Wojtek Kaniewski <wojtekka@irc.pl> - * Dawid Jarosz <dawjar@poczta.onet.pl> - * Adam Wysocki <gophi@ekg.chmurka.net> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License Version - * 2.1 as published by the Free Software Foundation. - * - * 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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. - */ - -#include <ctype.h> -#include <errno.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include "libgadu.h" - -/* - * gg_register3() - * - * rozpoczyna rejestracj� u�ytkownika protoko�em GG 6.0. wymaga wcze�niejszego - * pobrania tokenu za pomoc� funkcji gg_token(). - * - * - email - adres e-mail klienta - * - password - has�o klienta - * - tokenid - identyfikator tokenu - * - tokenval - warto�� tokenu - * - async - po��czenie asynchroniczne - * - * zaalokowana struct gg_http, kt�r� po�niej nale�y zwolni� - * funkcj� gg_register_free(), albo NULL je�li wyst�pi� b��d. - */ -struct gg_http *gg_register3(const char *email, const char *password, const char *tokenid, const char *tokenval, int async) -{ - struct gg_http *h; - char *__pwd, *__email, *__tokenid, *__tokenval, *form, *query; - - if (!email || !password || !tokenid || !tokenval) { - gg_debug(GG_DEBUG_MISC, "=> register, NULL parameter\n"); - errno = EFAULT; - return NULL; - } - - __pwd = gg_urlencode(password); - __email = gg_urlencode(email); - __tokenid = gg_urlencode(tokenid); - __tokenval = gg_urlencode(tokenval); - - if (!__pwd || !__email || !__tokenid || !__tokenval) { - gg_debug(GG_DEBUG_MISC, "=> register, not enough memory for form fields\n"); - free(__pwd); - free(__email); - free(__tokenid); - free(__tokenval); - return NULL; - } - - form = gg_saprintf("pwd=%s&email=%s&tokenid=%s&tokenval=%s&code=%u", - __pwd, __email, __tokenid, __tokenval, - gg_http_hash("ss", email, password)); - - free(__pwd); - free(__email); - free(__tokenid); - free(__tokenval); - - if (!form) { - gg_debug(GG_DEBUG_MISC, "=> register, not enough memory for form query\n"); - return NULL; - } - - gg_debug(GG_DEBUG_MISC, "=> register, %s\n", form); - - query = gg_saprintf( - "Host: " GG_REGISTER_HOST "\r\n" - "Content-Type: application/x-www-form-urlencoded\r\n" - "User-Agent: " GG_HTTP_USERAGENT "\r\n" - "Content-Length: %d\r\n" - "Pragma: no-cache\r\n" - "\r\n" - "%s", - (int) strlen(form), form); - - free(form); - - if (!query) { - gg_debug(GG_DEBUG_MISC, "=> register, not enough memory for query\n"); - return NULL; - } - - if (!(h = gg_http_connect(GG_REGISTER_HOST, GG_REGISTER_PORT, async, "POST", "/appsvc/fmregister3.asp", query))) { - gg_debug(GG_DEBUG_MISC, "=> register, gg_http_connect() failed mysteriously\n"); - free(query); - return NULL; - } - - h->type = GG_SESSION_REGISTER; - - free(query); - - h->callback = gg_pubdir_watch_fd; - h->destroy = gg_pubdir_free; - - if (!async) - gg_pubdir_watch_fd(h); - - return h; -} - -/* - * gg_unregister3() - * - * usuwa konto u�ytkownika z serwera protoko�em GG 6.0 - * - * - uin - numerek GG - * - password - has�o klienta - * - tokenid - identyfikator tokenu - * - tokenval - warto�� tokenu - * - async - po��czenie asynchroniczne - * - * zaalokowana struct gg_http, kt�r� po�niej nale�y zwolni� - * funkcj� gg_unregister_free(), albo NULL je�li wyst�pi� b��d. - */ -struct gg_http *gg_unregister3(uin_t uin, const char *password, const char *tokenid, const char *tokenval, int async) -{ - struct gg_http *h; - char *__fmpwd, *__pwd, *__tokenid, *__tokenval, *form, *query; - - if (!password || !tokenid || !tokenval) { - gg_debug(GG_DEBUG_MISC, "=> unregister, NULL parameter\n"); - errno = EFAULT; - return NULL; - } - - __pwd = gg_saprintf("%ld", random()); - __fmpwd = gg_urlencode(password); - __tokenid = gg_urlencode(tokenid); - __tokenval = gg_urlencode(tokenval); - - if (!__fmpwd || !__pwd || !__tokenid || !__tokenval) { - gg_debug(GG_DEBUG_MISC, "=> unregister, not enough memory for form fields\n"); - free(__pwd); - free(__fmpwd); - free(__tokenid); - free(__tokenval); - return NULL; - } - - form = gg_saprintf("fmnumber=%d&fmpwd=%s&delete=1&pwd=%s&email=deletedaccount@gadu-gadu.pl&tokenid=%s&tokenval=%s&code=%u", uin, __fmpwd, __pwd, __tokenid, __tokenval, gg_http_hash("ss", "deletedaccount@gadu-gadu.pl", __pwd)); - - free(__fmpwd); - free(__pwd); - free(__tokenid); - free(__tokenval); - - if (!form) { - gg_debug(GG_DEBUG_MISC, "=> unregister, not enough memory for form query\n"); - return NULL; - } - - gg_debug(GG_DEBUG_MISC, "=> unregister, %s\n", form); - - query = gg_saprintf( - "Host: " GG_REGISTER_HOST "\r\n" - "Content-Type: application/x-www-form-urlencoded\r\n" - "User-Agent: " GG_HTTP_USERAGENT "\r\n" - "Content-Length: %d\r\n" - "Pragma: no-cache\r\n" - "\r\n" - "%s", - (int) strlen(form), form); - - free(form); - - if (!query) { - gg_debug(GG_DEBUG_MISC, "=> unregister, not enough memory for query\n"); - return NULL; - } - - if (!(h = gg_http_connect(GG_REGISTER_HOST, GG_REGISTER_PORT, async, "POST", "/appsvc/fmregister3.asp", query))) { - gg_debug(GG_DEBUG_MISC, "=> unregister, gg_http_connect() failed mysteriously\n"); - free(query); - return NULL; - } - - h->type = GG_SESSION_UNREGISTER; - - free(query); - - h->callback = gg_pubdir_watch_fd; - h->destroy = gg_pubdir_free; - - if (!async) - gg_pubdir_watch_fd(h); - - return h; -} - -/* - * gg_change_passwd4() - * - * wysy�a ��danie zmiany has�a zgodnie z protoko�em GG 6.0. wymaga - * wcze�niejszego pobrania tokenu za pomoc� funkcji gg_token(). - * - * - uin - numer - * - email - adres e-mail - * - passwd - stare has�o - * - newpasswd - nowe has�o - * - tokenid - identyfikator tokenu - * - tokenval - warto�� tokenu - * - async - po��czenie asynchroniczne - * - * zaalokowana struct gg_http, kt�r� po�niej nale�y zwolni� - * funkcj� gg_change_passwd_free(), albo NULL je�li wyst�pi� b��d. - */ -struct gg_http *gg_change_passwd4(uin_t uin, const char *email, const char *passwd, const char *newpasswd, const char *tokenid, const char *tokenval, int async) -{ - struct gg_http *h; - char *form, *query, *__email, *__fmpwd, *__pwd, *__tokenid, *__tokenval; - - if (!uin || !email || !passwd || !newpasswd || !tokenid || !tokenval) { - gg_debug(GG_DEBUG_MISC, "=> change, NULL parameter\n"); - errno = EFAULT; - return NULL; - } - - __fmpwd = gg_urlencode(passwd); - __pwd = gg_urlencode(newpasswd); - __email = gg_urlencode(email); - __tokenid = gg_urlencode(tokenid); - __tokenval = gg_urlencode(tokenval); - - if (!__fmpwd || !__pwd || !__email || !__tokenid || !__tokenval) { - gg_debug(GG_DEBUG_MISC, "=> change, not enough memory for form fields\n"); - free(__fmpwd); - free(__pwd); - free(__email); - free(__tokenid); - free(__tokenval); - return NULL; - } - - if (!(form = gg_saprintf("fmnumber=%d&fmpwd=%s&pwd=%s&email=%s&tokenid=%s&tokenval=%s&code=%u", uin, __fmpwd, __pwd, __email, __tokenid, __tokenval, gg_http_hash("ss", email, newpasswd)))) { - gg_debug(GG_DEBUG_MISC, "=> change, not enough memory for form fields\n"); - free(__fmpwd); - free(__pwd); - free(__email); - free(__tokenid); - free(__tokenval); - - return NULL; - } - - free(__fmpwd); - free(__pwd); - free(__email); - free(__tokenid); - free(__tokenval); - - gg_debug(GG_DEBUG_MISC, "=> change, %s\n", form); - - query = gg_saprintf( - "Host: " GG_REGISTER_HOST "\r\n" - "Content-Type: application/x-www-form-urlencoded\r\n" - "User-Agent: " GG_HTTP_USERAGENT "\r\n" - "Content-Length: %d\r\n" - "Pragma: no-cache\r\n" - "\r\n" - "%s", - (int) strlen(form), form); - - free(form); - - if (!query) { - gg_debug(GG_DEBUG_MISC, "=> change, not enough memory for query\n"); - return NULL; - } - - if (!(h = gg_http_connect(GG_REGISTER_HOST, GG_REGISTER_PORT, async, "POST", "/appsvc/fmregister3.asp", query))) { - gg_debug(GG_DEBUG_MISC, "=> change, gg_http_connect() failed mysteriously\n"); - free(query); - return NULL; - } - - h->type = GG_SESSION_PASSWD; - - free(query); - - h->callback = gg_pubdir_watch_fd; - h->destroy = gg_pubdir_free; - - if (!async) - gg_pubdir_watch_fd(h); - - return h; -} - -/* - * gg_remind_passwd3() - * - * wysy�a ��danie przypomnienia has�a e-mailem. - * - * - uin - numer - * - email - adres e-mail taki, jak ten zapisany na serwerze - * - async - po��czenie asynchroniczne - * - tokenid - identyfikator tokenu - * - tokenval - warto�� tokenu - * - * zaalokowana struct gg_http, kt�r� po�niej nale�y zwolni� - * funkcj� gg_remind_passwd_free(), albo NULL je�li wyst�pi� b��d. - */ -struct gg_http *gg_remind_passwd3(uin_t uin, const char *email, const char *tokenid, const char *tokenval, int async) -{ - struct gg_http *h; - char *form, *query, *__tokenid, *__tokenval, *__email; - - if (!tokenid || !tokenval || !email) { - gg_debug(GG_DEBUG_MISC, "=> remind, NULL parameter\n"); - errno = EFAULT; - return NULL; - } - - __tokenid = gg_urlencode(tokenid); - __tokenval = gg_urlencode(tokenval); - __email = gg_urlencode(email); - - if (!__tokenid || !__tokenval || !__email) { - gg_debug(GG_DEBUG_MISC, "=> remind, not enough memory for form fields\n"); - free(__tokenid); - free(__tokenval); - free(__email); - return NULL; - } - - if (!(form = gg_saprintf("userid=%d&code=%u&tokenid=%s&tokenval=%s&email=%s", uin, gg_http_hash("u", uin), __tokenid, __tokenval, __email))) { - gg_debug(GG_DEBUG_MISC, "=> remind, not enough memory for form fields\n"); - free(__tokenid); - free(__tokenval); - free(__email); - return NULL; - } - - free(__tokenid); - free(__tokenval); - free(__email); - - gg_debug(GG_DEBUG_MISC, "=> remind, %s\n", form); - - query = gg_saprintf( - "Host: " GG_REMIND_HOST "\r\n" - "Content-Type: application/x-www-form-urlencoded\r\n" - "User-Agent: " GG_HTTP_USERAGENT "\r\n" - "Content-Length: %d\r\n" - "Pragma: no-cache\r\n" - "\r\n" - "%s", - (int) strlen(form), form); - - free(form); - - if (!query) { - gg_debug(GG_DEBUG_MISC, "=> remind, not enough memory for query\n"); - return NULL; - } - - if (!(h = gg_http_connect(GG_REMIND_HOST, GG_REMIND_PORT, async, "POST", "/appsvc/fmsendpwd3.asp", query))) { - gg_debug(GG_DEBUG_MISC, "=> remind, gg_http_connect() failed mysteriously\n"); - free(query); - return NULL; - } - - h->type = GG_SESSION_REMIND; - - free(query); - - h->callback = gg_pubdir_watch_fd; - h->destroy = gg_pubdir_free; - - if (!async) - gg_pubdir_watch_fd(h); - - return h; -} - -/* - * gg_pubdir_watch_fd() - * - * przy asynchronicznych operacjach na katalogu publicznym nale�y wywo�ywa� - * t� funkcj� przy zmianach na obserwowanym deskryptorze. - * - * - h - struktura opisuj�ca po��czenie - * - * je�li wszystko posz�o dobrze to 0, inaczej -1. operacja b�dzie - * zako�czona, je�li h->state == GG_STATE_DONE. je�li wyst�pi jaki� - * b��d, to b�dzie tam GG_STATE_ERROR i odpowiedni kod b��du w h->error. - */ -int gg_pubdir_watch_fd(struct gg_http *h) -{ - struct gg_pubdir *p; - char *tmp; - - if (!h) { - errno = EFAULT; - return -1; - } - - if (h->state == GG_STATE_ERROR) { - gg_debug(GG_DEBUG_MISC, "=> pubdir, watch_fd issued on failed session\n"); - errno = EINVAL; - return -1; - } - - if (h->state != GG_STATE_PARSING) { - if (gg_http_watch_fd(h) == -1) { - gg_debug(GG_DEBUG_MISC, "=> pubdir, http failure\n"); - errno = EINVAL; - return -1; - } - } - - if (h->state != GG_STATE_PARSING) - return 0; - - h->state = GG_STATE_DONE; - - if (!(h->data = p = malloc(sizeof(struct gg_pubdir)))) { - gg_debug(GG_DEBUG_MISC, "=> pubdir, not enough memory for results\n"); - return -1; - } - - p->success = 0; - p->uin = 0; - - gg_debug(GG_DEBUG_MISC, "=> pubdir, let's parse \"%s\"\n", h->body); - - if ((tmp = strstr(h->body, "Tokens okregisterreply_packet.reg.dwUserId="))) { - p->success = 1; - p->uin = strtol(tmp + sizeof("Tokens okregisterreply_packet.reg.dwUserId=") - 1, NULL, 0); - gg_debug(GG_DEBUG_MISC, "=> pubdir, success (okregisterreply, uin=%d)\n", p->uin); - } else if ((tmp = strstr(h->body, "success")) || (tmp = strstr(h->body, "results"))) { - p->success = 1; - if (tmp[7] == ':') - p->uin = strtol(tmp + 8, NULL, 0); - gg_debug(GG_DEBUG_MISC, "=> pubdir, success (uin=%d)\n", p->uin); - } else - gg_debug(GG_DEBUG_MISC, "=> pubdir, error.\n"); - - return 0; -} - -/* - * gg_pubdir_free() - * - * zwalnia pami�� po efektach operacji na katalogu publicznym. - * - * - h - zwalniana struktura - */ -void gg_pubdir_free(struct gg_http *h) -{ - if (!h) - return; - - free(h->data); - gg_http_free(h); -} - -/* - * gg_token() - * - * pobiera z serwera token do autoryzacji zak�adania konta, usuwania - * konta i zmiany has�a. - * - * zaalokowana struct gg_http, kt�r� po�niej nale�y zwolni� - * funkcj� gg_token_free(), albo NULL je�li wyst�pi� b��d. - */ -struct gg_http *gg_token(int async) -{ - struct gg_http *h; - const char *query; - - query = "Host: " GG_REGISTER_HOST "\r\n" - "Content-Type: application/x-www-form-urlencoded\r\n" - "User-Agent: " GG_HTTP_USERAGENT "\r\n" - "Content-Length: 0\r\n" - "Pragma: no-cache\r\n" - "\r\n"; - - if (!(h = gg_http_connect(GG_REGISTER_HOST, GG_REGISTER_PORT, async, "POST", "/appsvc/regtoken.asp", query))) { - gg_debug(GG_DEBUG_MISC, "=> token, gg_http_connect() failed mysteriously\n"); - return NULL; - } - - h->type = GG_SESSION_TOKEN; - - h->callback = gg_token_watch_fd; - h->destroy = gg_token_free; - - if (!async) - gg_token_watch_fd(h); - - return h; -} - -/* - * gg_token_watch_fd() - * - * przy asynchronicznych operacjach zwi�zanych z tokenem nale�y wywo�ywa� - * t� funkcj� przy zmianach na obserwowanym deskryptorze. - * - * - h - struktura opisuj�ca po��czenie - * - * je�li wszystko posz�o dobrze to 0, inaczej -1. operacja b�dzie - * zako�czona, je�li h->state == GG_STATE_DONE. je�li wyst�pi jaki� - * b��d, to b�dzie tam GG_STATE_ERROR i odpowiedni kod b��du w h->error. - */ -int gg_token_watch_fd(struct gg_http *h) -{ - if (!h) { - errno = EFAULT; - return -1; - } - - if (h->state == GG_STATE_ERROR) { - gg_debug(GG_DEBUG_MISC, "=> token, watch_fd issued on failed session\n"); - errno = EINVAL; - return -1; - } - - if (h->state != GG_STATE_PARSING) { - if (gg_http_watch_fd(h) == -1) { - gg_debug(GG_DEBUG_MISC, "=> token, http failure\n"); - errno = EINVAL; - return -1; - } - } - - if (h->state != GG_STATE_PARSING) - return 0; - - /* je�li h->data jest puste, to �ci�gali�my tokenid i url do niego, - * ale je�li co� tam jest, to znaczy, �e mamy drugi etap polegaj�cy - * na pobieraniu tokenu. */ - if (!h->data) { - int width, height, length; - char *url = NULL, *tokenid = NULL, *path, *headers; - const char *host; - struct gg_http *h2; - struct gg_token *t; - - gg_debug(GG_DEBUG_MISC, "=> token body \"%s\"\n", h->body); - - if (h->body && (!(url = malloc(strlen(h->body))) || !(tokenid = malloc(strlen(h->body))))) { - gg_debug(GG_DEBUG_MISC, "=> token, not enough memory for results\n"); - free(url); - return -1; - } - - if (!h->body || sscanf(h->body, "%d %d %d\r\n%s\r\n%s", &width, &height, &length, tokenid, url) != 5) { - gg_debug(GG_DEBUG_MISC, "=> token, parsing failed\n"); - free(url); - free(tokenid); - errno = EINVAL; - return -1; - } - - /* dostali�my tokenid i wszystkie niezb�dne informacje, - * wi�c pobierzmy obrazek z tokenem */ - - if (strncmp(url, "http://", 7)) { - path = gg_saprintf("%s?tokenid=%s", url, tokenid); - host = GG_REGISTER_HOST; - } else { - char *slash = (char*)strchr(url + 7, '/'); - - if (slash) { - path = gg_saprintf("%s?tokenid=%s", slash, tokenid); - *slash = 0; - host = url + 7; - } else { - gg_debug(GG_DEBUG_MISC, "=> token, url parsing failed\n"); - free(url); - free(tokenid); - errno = EINVAL; - return -1; - } - } - - if (!path) { - gg_debug(GG_DEBUG_MISC, "=> token, not enough memory for token url\n"); - free(url); - free(tokenid); - return -1; - } - - if (!(headers = gg_saprintf("Host: %s\r\nUser-Agent: " GG_HTTP_USERAGENT "\r\n\r\n", host))) { - gg_debug(GG_DEBUG_MISC, "=> token, not enough memory for token url\n"); - free(path); - free(url); - free(tokenid); - return -1; - } - - if (!(h2 = gg_http_connect(host, GG_REGISTER_PORT, h->async, "GET", path, headers))) { - gg_debug(GG_DEBUG_MISC, "=> token, gg_http_connect() failed mysteriously\n"); - free(headers); - free(url); - free(path); - free(tokenid); - return -1; - } - - free(headers); - free(path); - free(url); - - memcpy(h, h2, sizeof(struct gg_http)); - free(h2); - - h->type = GG_SESSION_TOKEN; - - h->callback = gg_token_watch_fd; - h->destroy = gg_token_free; - - if (!h->async) - gg_token_watch_fd(h); - - if (!(h->data = t = malloc(sizeof(struct gg_token)))) { - gg_debug(GG_DEBUG_MISC, "=> token, not enough memory for token data\n"); - free(tokenid); - return -1; - } - - t->width = width; - t->height = height; - t->length = length; - t->tokenid = tokenid; - } else { - /* obrazek mamy w h->body */ - h->state = GG_STATE_DONE; - } - - return 0; -} - -/* - * gg_token_free() - * - * zwalnia pami�� po efektach pobierania tokenu. - * - * - h - zwalniana struktura - */ -void gg_token_free(struct gg_http *h) -{ - struct gg_token *t; - - if (!h) - return; - - if ((t = h->data)) - free(t->tokenid); - - free(h->data); - gg_http_free(h); -} - -/* - * Local variables: - * c-indentation-style: k&r - * c-basic-offset: 8 - * indent-tabs-mode: notnil - * End: - * - * vim: shiftwidth=8: - */ diff --git a/kopete/protocols/gadu/libgadu/pubdir50.c b/kopete/protocols/gadu/libgadu/pubdir50.c deleted file mode 100644 index 877ab83e..00000000 --- a/kopete/protocols/gadu/libgadu/pubdir50.c +++ /dev/null @@ -1,467 +0,0 @@ -/* $Id$ */ - -/* - * (C) Copyright 2003 Wojtek Kaniewski <wojtekka@irc.pl> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License Version - * 2.1 as published by the Free Software Foundation. - * - * 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser 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. - */ - -#include <errno.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> - -#include "libgadu.h" - -/* - * gg_pubdir50_new() - * - * tworzy now± zmienn± typu gg_pubdir50_t. - * - * zaalokowana zmienna lub NULL w przypadku braku pamiêci. - */ -gg_pubdir50_t gg_pubdir50_new(int type) -{ - gg_pubdir50_t res = malloc(sizeof(struct gg_pubdir50_s)); - - gg_debug(GG_DEBUG_FUNCTION, "** gg_pubdir50_new(%d);\n", type); - - if (!res) { - gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_new() out of memory\n"); - return NULL; - } - - memset(res, 0, sizeof(struct gg_pubdir50_s)); - - res->type = type; - - return res; -} - -/* - * gg_pubdir50_add_n() // funkcja wewnêtrzna - * - * funkcja dodaje lub zastêpuje istniej±ce pole do zapytania lub odpowiedzi. - * - * - req - wska¼nik opisu zapytania, - * - num - numer wyniku (0 dla zapytania), - * - field - nazwa pola, - * - value - warto¶æ pola, - * - * 0/-1 - */ -static int gg_pubdir50_add_n(gg_pubdir50_t req, int num, const char *field, const char *value) -{ - struct gg_pubdir50_entry *tmp = NULL, *entry; - char *dupfield, *dupvalue; - int i; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_pubdir50_add_n(%p, %d, \"%s\", \"%s\");\n", req, num, field, value); - - if (!(dupvalue = strdup(value))) { - gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_add_n() out of memory\n"); - return -1; - } - - for (i = 0; i < req->entries_count; i++) { - if (req->entries[i].num != num || strcmp(req->entries[i].field, field)) - continue; - - free(req->entries[i].value); - req->entries[i].value = dupvalue; - - return 0; - } - - if (!(dupfield = strdup(field))) { - gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_add_n() out of memory\n"); - free(dupvalue); - return -1; - } - - if (!(tmp = realloc(req->entries, sizeof(struct gg_pubdir50_entry) * (req->entries_count + 1)))) { - gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_add_n() out of memory\n"); - free(dupfield); - free(dupvalue); - return -1; - } - - req->entries = tmp; - - entry = &req->entries[req->entries_count]; - entry->num = num; - entry->field = dupfield; - entry->value = dupvalue; - - req->entries_count++; - - return 0; -} - -/* - * gg_pubdir50_add() - * - * funkcja dodaje pole do zapytania. - * - * - req - wska¼nik opisu zapytania, - * - field - nazwa pola, - * - value - warto¶æ pola, - * - * 0/-1 - */ -int gg_pubdir50_add(gg_pubdir50_t req, const char *field, const char *value) -{ - return gg_pubdir50_add_n(req, 0, field, value); -} - -/* - * gg_pubdir50_seq_set() - * - * ustawia numer sekwencyjny zapytania. - * - * - req - zapytanie, - * - seq - nowy numer sekwencyjny. - * - * 0/-1. - */ -int gg_pubdir50_seq_set(gg_pubdir50_t req, uint32_t seq) -{ - gg_debug(GG_DEBUG_FUNCTION, "** gg_pubdir50_seq_set(%p, %d);\n", req, seq); - - if (!req) { - gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_seq_set() invalid arguments\n"); - errno = EFAULT; - return -1; - } - - req->seq = seq; - - return 0; -} - -/* - * gg_pubdir50_free() - * - * zwalnia pamiêæ po zapytaniu lub rezultacie szukania u¿ytkownika. - * - * - s - zwalniana zmienna, - */ -void gg_pubdir50_free(gg_pubdir50_t s) -{ - int i; - - if (!s) - return; - - for (i = 0; i < s->entries_count; i++) { - free(s->entries[i].field); - free(s->entries[i].value); - } - - free(s->entries); - free(s); -} - -/* - * gg_pubdir50() - * - * wysy³a zapytanie katalogu publicznego do serwera. - * - * - sess - sesja, - * - req - zapytanie. - * - * numer sekwencyjny wyszukiwania lub 0 w przypadku b³êdu. - */ -uint32_t gg_pubdir50(struct gg_session *sess, gg_pubdir50_t req) -{ - int i, size = 5; - uint32_t res; - char *buf, *p; - struct gg_pubdir50_request *r; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_pubdir50(%p, %p);\n", sess, req); - - if (!sess || !req) { - gg_debug(GG_DEBUG_MISC, "// gg_pubdir50() invalid arguments\n"); - errno = EFAULT; - return 0; - } - - if (sess->state != GG_STATE_CONNECTED) { - gg_debug(GG_DEBUG_MISC, "// gg_pubdir50() not connected\n"); - errno = ENOTCONN; - return 0; - } - - for (i = 0; i < req->entries_count; i++) { - /* wyszukiwanie bierze tylko pierwszy wpis */ - if (req->entries[i].num) - continue; - - size += strlen(req->entries[i].field) + 1; - size += strlen(req->entries[i].value) + 1; - } - - if (!(buf = malloc(size))) { - gg_debug(GG_DEBUG_MISC, "// gg_pubdir50() out of memory (%d bytes)\n", size); - return 0; - } - - r = (struct gg_pubdir50_request*) buf; - res = time(NULL); - r->type = req->type; - r->seq = (req->seq) ? gg_fix32(req->seq) : gg_fix32(time(NULL)); - req->seq = gg_fix32(r->seq); - - for (i = 0, p = buf + 5; i < req->entries_count; i++) { - if (req->entries[i].num) - continue; - - strcpy(p, req->entries[i].field); - p += strlen(p) + 1; - - strcpy(p, req->entries[i].value); - p += strlen(p) + 1; - } - - if (gg_send_packet(sess, GG_PUBDIR50_REQUEST, buf, size, NULL, 0) == -1) - res = 0; - - free(buf); - - return res; -} - -/* - * gg_pubdir50_handle_reply() // funkcja wewnêtrzna - * - * analizuje przychodz±cy pakiet odpowiedzi i zapisuje wynik w struct gg_event. - * - * - e - opis zdarzenia - * - packet - zawarto¶æ pakietu odpowiedzi - * - length - d³ugo¶æ pakietu odpowiedzi - * - * 0/-1 - */ -int gg_pubdir50_handle_reply(struct gg_event *e, const char *packet, int length) -{ - const char *end = packet + length, *p; - struct gg_pubdir50_reply *r = (struct gg_pubdir50_reply*) packet; - gg_pubdir50_t res; - int num = 0; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_pubdir50_handle_reply(%p, %p, %d);\n", e, packet, length); - - if (!e || !packet) { - gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_handle_reply() invalid arguments\n"); - errno = EFAULT; - return -1; - } - - if (length < 5) { - gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_handle_reply() packet too short\n"); - errno = EINVAL; - return -1; - } - - if (!(res = gg_pubdir50_new(r->type))) { - gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_handle_reply() unable to allocate reply\n"); - return -1; - } - - e->event.pubdir50 = res; - - res->seq = gg_fix32(r->seq); - - switch (res->type) { - case GG_PUBDIR50_READ: - e->type = GG_EVENT_PUBDIR50_READ; - break; - - case GG_PUBDIR50_WRITE: - e->type = GG_EVENT_PUBDIR50_WRITE; - break; - - default: - e->type = GG_EVENT_PUBDIR50_SEARCH_REPLY; - break; - } - - /* brak wyników? */ - if (length == 5) - return 0; - - /* pomiñ pocz±tek odpowiedzi */ - p = packet + 5; - - while (p < end) { - const char *field, *value; - - field = p; - - /* sprawd¼, czy nie mamy podzia³u na kolejne pole */ - if (!*field) { - num++; - field++; - } - - value = NULL; - - for (p = field; p < end; p++) { - /* je¶li mamy koniec tekstu... */ - if (!*p) { - /* ...i jeszcze nie mieli¶my warto¶ci pola to - * wiemy, ¿e po tym zerze jest warto¶æ... */ - if (!value) - value = p + 1; - else - /* ...w przeciwym wypadku koniec - * warto¶ci i mo¿emy wychodziæ - * grzecznie z pêtli */ - break; - } - } - - /* sprawd¼my, czy pole nie wychodzi poza pakiet, ¿eby nie - * mieæ segfaultów, je¶li serwer przestanie zakañczaæ pakietów - * przez \0 */ - - if (p == end) { - gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_handle_reply() premature end of packet\n"); - goto failure; - } - - p++; - - /* je¶li dostali¶my namier na nastêpne wyniki, to znaczy ¿e - * mamy koniec wyników i nie jest to kolejna osoba. */ - if (!strcasecmp(field, "nextstart")) { - res->next = atoi(value); - num--; - } else { - if (gg_pubdir50_add_n(res, num, field, value) == -1) - goto failure; - } - } - - res->count = num + 1; - - return 0; - -failure: - gg_pubdir50_free(res); - return -1; -} - -/* - * gg_pubdir50_get() - * - * pobiera informacjê z rezultatu wyszukiwania. - * - * - res - rezultat wyszukiwania, - * - num - numer odpowiedzi, - * - field - nazwa pola (wielko¶æ liter nie ma znaczenia). - * - * warto¶æ pola lub NULL, je¶li nie znaleziono. - */ -const char *gg_pubdir50_get(gg_pubdir50_t res, int num, const char *field) -{ - char *value = NULL; - int i; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_pubdir50_get(%p, %d, \"%s\");\n", res, num, field); - - if (!res || num < 0 || !field) { - gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_get() invalid arguments\n"); - errno = EINVAL; - return NULL; - } - - for (i = 0; i < res->entries_count; i++) { - if (res->entries[i].num == num && !strcasecmp(res->entries[i].field, field)) { - value = res->entries[i].value; - break; - } - } - - return value; -} - -/* - * gg_pubdir50_count() - * - * zwraca ilo¶æ wyników danego zapytania. - * - * - res - odpowied¼ - * - * ilo¶æ lub -1 w przypadku b³êdu. - */ -int gg_pubdir50_count(gg_pubdir50_t res) -{ - return (!res) ? -1 : res->count; -} - -/* - * gg_pubdir50_type() - * - * zwraca rodzaj zapytania lub odpowiedzi. - * - * - res - zapytanie lub odpowied¼ - * - * ilo¶æ lub -1 w przypadku b³êdu. - */ -int gg_pubdir50_type(gg_pubdir50_t res) -{ - return (!res) ? -1 : res->type; -} - -/* - * gg_pubdir50_next() - * - * zwraca numer, od którego nale¿y rozpocz±æ kolejne wyszukiwanie, je¶li - * zale¿y nam na kolejnych wynikach. - * - * - res - odpowied¼ - * - * numer lub -1 w przypadku b³êdu. - */ -uin_t gg_pubdir50_next(gg_pubdir50_t res) -{ - return (!res) ? (unsigned) -1 : res->next; -} - -/* - * gg_pubdir50_seq() - * - * zwraca numer sekwencyjny zapytania lub odpowiedzi. - * - * - res - zapytanie lub odpowied¼ - * - * numer lub -1 w przypadku b³êdu. - */ -uint32_t gg_pubdir50_seq(gg_pubdir50_t res) -{ - return (!res) ? (unsigned) -1 : res->seq; -} - -/* - * Local variables: - * c-indentation-style: k&r - * c-basic-offset: 8 - * indent-tabs-mode: notnil - * End: - * - * vim: shiftwidth=8: - */ diff --git a/kopete/protocols/gadu/ui/CMakeLists.txt b/kopete/protocols/gadu/ui/CMakeLists.txt new file mode 100644 index 00000000..10b5b07d --- /dev/null +++ b/kopete/protocols/gadu/ui/CMakeLists.txt @@ -0,0 +1,28 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_BINARY_DIR}/kopete/libkopete/ui + ${CMAKE_SOURCE_DIR}/kopete/libkopete + ${CMAKE_SOURCE_DIR}/kopete/libkopete/ui + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### gaduui (static) ########################### + +tde_add_library( gaduui STATIC_PIC AUTOMOC + SOURCES + gaduadd.ui gadusearch.ui gadueditaccountui.ui gaduawayui.ui + gaduregisteraccountui.ui empty.cpp +) diff --git a/kopete/protocols/groupwise/CMakeLists.txt b/kopete/protocols/groupwise/CMakeLists.txt new file mode 100644 index 00000000..c6df3323 --- /dev/null +++ b/kopete/protocols/groupwise/CMakeLists.txt @@ -0,0 +1,50 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_subdirectory( icons ) +add_subdirectory( libgroupwise ) +add_subdirectory( ui ) + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/ui + ${CMAKE_CURRENT_SOURCE_DIR}/libgroupwise + ${CMAKE_CURRENT_SOURCE_DIR}/libgroupwise/tasks + ${CMAKE_CURRENT_SOURCE_DIR}/libgroupwise/qca/src + ${CMAKE_CURRENT_SOURCE_DIR}/ui + ${CMAKE_SOURCE_DIR}/kopete/libkopete + ${CMAKE_SOURCE_DIR}/kopete/libkopete/ui + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + +link_directories( + ${TQT_LIBRARY_DIRS} +) + + +##### other data ################################ + +install( FILES kopete_groupwise.desktop DESTINATION ${SERVICES_INSTALL_DIR} ) +install( FILES gwchatui.rc DESTINATION ${DATA_INSTALL_DIR}/kopete_groupwise ) + + +##### kopete_groupwise (module) ################# + +tde_add_kpart( kopete_groupwise AUTOMOC + SOURCES + gwprotocol.cpp gwcontact.cpp gwaccount.cpp gwbytestream.cpp + gwconnector.cpp gwmessagemanager.cpp gwcontactlist.cpp + LINK + kopetegroupwiseui-static groupwise-static groupwise_tasks-static + groupwise_qca-static kopete-shared + DESTINATION ${PLUGIN_INSTALL_DIR} +) diff --git a/kopete/protocols/groupwise/icons/CMakeLists.txt b/kopete/protocols/groupwise/icons/CMakeLists.txt new file mode 100644 index 00000000..ba51467b --- /dev/null +++ b/kopete/protocols/groupwise/icons/CMakeLists.txt @@ -0,0 +1,12 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +tde_install_icons( DESTINATION ${DATA_INSTALL_DIR}/kopete/icons ) diff --git a/kopete/protocols/groupwise/libgroupwise/CMakeLists.txt b/kopete/protocols/groupwise/libgroupwise/CMakeLists.txt new file mode 100644 index 00000000..ef158cd9 --- /dev/null +++ b/kopete/protocols/groupwise/libgroupwise/CMakeLists.txt @@ -0,0 +1,53 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_subdirectory( qca ) +add_subdirectory( tasks ) + +# add_definitions( +# -DUSE_TLSHANDLER +# ) + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/qca/src + ${CMAKE_SOURCE_DIR}/kopete/libkopete + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### groupwise (static) ######################## + +tde_add_library( groupwise STATIC_PIC AUTOMOC + SOURCES + bytestream.cpp chatroommanager.cpp client.cpp connector.cpp + coreprotocol.cpp eventprotocol.cpp eventtransfer.cpp + gwclientstream.cpp gwerror.cpp gwfield.cpp gwglobal.cpp + inputprotocolbase.cpp privacymanager.cpp qcatlshandler.cpp + request.cpp requestfactory.cpp response.cpp responseprotocol.cpp + rtf.cc safedelete.cpp securestream.cpp stream.cpp task.cpp + tlshandler.cpp transfer.cpp transferbase.cpp userdetailsmanager.cpp + usertransfer.cpp +) + + +##### gwtest (static) ########################### + +tde_add_library( gwtest STATIC_PIC AUTOMOC + SOURCES + coreprotocol.cpp eventtransfer.cpp gwfield.cpp request.cpp + requestfactory.cpp transfer.cpp usertransfer.cpp client.cpp task.cpp + safedelete.cpp gwclientstream.cpp qcatlshandler.cpp stream.cpp + tlshandler.cpp response.cpp connector.cpp securestream.cpp + bytestream.cpp +) diff --git a/kopete/protocols/groupwise/libgroupwise/qca/CMakeLists.txt b/kopete/protocols/groupwise/libgroupwise/qca/CMakeLists.txt new file mode 100644 index 00000000..7356f221 --- /dev/null +++ b/kopete/protocols/groupwise/libgroupwise/qca/CMakeLists.txt @@ -0,0 +1,12 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_subdirectory( src ) diff --git a/kopete/protocols/groupwise/libgroupwise/qca/src/CMakeLists.txt b/kopete/protocols/groupwise/libgroupwise/qca/src/CMakeLists.txt new file mode 100644 index 00000000..9c74e339 --- /dev/null +++ b/kopete/protocols/groupwise/libgroupwise/qca/src/CMakeLists.txt @@ -0,0 +1,22 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### groupwise_qca (static) #################### + +tde_add_library( groupwise_qca STATIC_PIC AUTOMOC + SOURCES qca.cpp +) diff --git a/kopete/protocols/groupwise/libgroupwise/tasks/CMakeLists.txt b/kopete/protocols/groupwise/libgroupwise/tasks/CMakeLists.txt new file mode 100644 index 00000000..1fc4a60a --- /dev/null +++ b/kopete/protocols/groupwise/libgroupwise/tasks/CMakeLists.txt @@ -0,0 +1,38 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ${CMAKE_CURRENT_SOURCE_DIR}/../qca/src + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### groupwise_tasks (static) ################## + +tde_add_library( groupwise_tasks STATIC_PIC AUTOMOC + SOURCES + requesttask.cpp eventtask.cpp logintask.cpp setstatustask.cpp + statustask.cpp conferencetask.cpp createconferencetask.cpp + sendmessagetask.cpp getdetailstask.cpp getstatustask.cpp + typingtask.cpp connectiontask.cpp sendinvitetask.cpp + joinconferencetask.cpp leaveconferencetask.cpp rejectinvitetask.cpp + keepalivetask.cpp createcontacttask.cpp modifycontactlisttask.cpp + createfoldertask.cpp movecontacttask.cpp updateitemtask.cpp + createcontactinstancetask.cpp deleteitemtask.cpp updatefoldertask.cpp + updatecontacttask.cpp pollsearchresultstask.cpp privacyitemtask.cpp + needfoldertask.cpp searchchattask.cpp searchusertask.cpp + searchusertask.h getchatsearchresultstask.cpp chatcountstask.cpp + chatpropertiestask.cpp joinchattask.cpp +) diff --git a/kopete/protocols/groupwise/ui/CMakeLists.txt b/kopete/protocols/groupwise/ui/CMakeLists.txt new file mode 100644 index 00000000..2045bef7 --- /dev/null +++ b/kopete/protocols/groupwise/ui/CMakeLists.txt @@ -0,0 +1,35 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../libgroupwise + ${CMAKE_CURRENT_SOURCE_DIR}/../libgroupwise/qca/src + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ${CMAKE_BINARY_DIR}/kopete/libkopete/ui + ${CMAKE_SOURCE_DIR}/kopete/libkopete + ${CMAKE_SOURCE_DIR}/kopete/libkopete/ui + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### kopetegroupwiseui (static) ################ + +tde_add_library( kopetegroupwiseui STATIC_PIC AUTOMOC + SOURCES + gwaccountpreferences.ui gwaddcontactpage.cpp gwaddui.ui + gweditaccountwidget.cpp gwreceiveinvitationdialog.cpp + gwshowinvitation.ui gwcontactpropswidget.ui gwcontactproperties.cpp + gwprivacy.ui gwprivacydialog.cpp gwsearch.cpp gwcustomstatuswidget.ui + gwcustomstatusedit.ui gwcontactsearch.ui gwchatsearchwidget.ui + gwchatsearchdialog.cpp gwchatpropswidget.ui gwchatpropsdialog.cpp +) diff --git a/kopete/protocols/irc/CMakeLists.txt b/kopete/protocols/irc/CMakeLists.txt new file mode 100644 index 00000000..6c795704 --- /dev/null +++ b/kopete/protocols/irc/CMakeLists.txt @@ -0,0 +1,54 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_subdirectory( icons ) +add_subdirectory( libkirc ) +add_subdirectory( ui ) + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/ui + ${CMAKE_CURRENT_SOURCE_DIR}/ui + ${CMAKE_CURRENT_SOURCE_DIR}/libkirc + ${CMAKE_SOURCE_DIR}/kopete/libkopete + ${CMAKE_SOURCE_DIR}/kopete/libkopete/ui + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + +link_directories( + ${TQT_LIBRARY_DIRS} +) + + +##### other data ################################ + +install( FILES + kopete_irc.desktop irc.protocol + DESTINATION ${SERVICES_INSTALL_DIR} ) + +install( FILES + ircnetworks.xml ircchatui.rc + DESTINATION ${DATA_INSTALL_DIR}/kopete ) + + +##### kopete_irc (module) ####################### + +tde_add_kpart( kopete_irc AUTOMOC + SOURCES + ircaccount.cpp ircaddcontactpage.cpp ircchannelcontact.cpp + irccontact.cpp ircguiclient.cpp ircprotocol.cpp ircservercontact.cpp + ircsignalhandler.cpp irctransferhandler.cpp ircusercontact.cpp + irccontactmanager.cpp kcodecaction.cpp ksparser.cpp + LINK + kopeteircui-static kirc-static kopete-shared + DESTINATION ${PLUGIN_INSTALL_DIR} +) diff --git a/kopete/protocols/irc/icons/CMakeLists.txt b/kopete/protocols/irc/icons/CMakeLists.txt new file mode 100644 index 00000000..ba51467b --- /dev/null +++ b/kopete/protocols/irc/icons/CMakeLists.txt @@ -0,0 +1,12 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +tde_install_icons( DESTINATION ${DATA_INSTALL_DIR}/kopete/icons ) diff --git a/kopete/protocols/irc/libkirc/CMakeLists.txt b/kopete/protocols/irc/libkirc/CMakeLists.txt new file mode 100644 index 00000000..d2b298c2 --- /dev/null +++ b/kopete/protocols/irc/libkirc/CMakeLists.txt @@ -0,0 +1,30 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/kopete/libkopete + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### kirc (static) ############################# + +tde_add_library( kirc STATIC_PIC AUTOMOC + SOURCES + kircengine.cpp kircengine_commands.cpp kircengine_ctcp.cpp + kircengine_numericreplies.cpp kircentity.cpp kircmessage.cpp + kircmessageredirector.cpp kirctransfer.cpp kirctransferhandler.cpp + kirctransferserver.cpp ksslsocket.cpp +) diff --git a/kopete/protocols/irc/libkirc/kircentity.h b/kopete/protocols/irc/libkirc/kircentity.h index d802d8f4..1878a406 100644 --- a/kopete/protocols/irc/libkirc/kircentity.h +++ b/kopete/protocols/irc/libkirc/kircentity.h @@ -39,7 +39,7 @@ class Entity Q_OBJECT public: - typedef enum Type + enum Type { Unknown, Server, diff --git a/kopete/protocols/irc/ui/CMakeLists.txt b/kopete/protocols/irc/ui/CMakeLists.txt new file mode 100644 index 00000000..7d77d5b8 --- /dev/null +++ b/kopete/protocols/irc/ui/CMakeLists.txt @@ -0,0 +1,30 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ${CMAKE_CURRENT_SOURCE_DIR}/../libkirc + ${CMAKE_BINARY_DIR}/kopete/libkopete/ui + ${CMAKE_SOURCE_DIR}/kopete/libkopete + ${CMAKE_SOURCE_DIR}/kopete/libkopete/ui + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### kopeteircui (static) ###################### + +tde_add_library( kopeteircui STATIC_PIC AUTOMOC + SOURCES + ircadd.ui empty.cpp irceditaccountwidget.cpp irceditaccount.ui + channellist.cpp channellistdialog.cpp networkconfig.ui +) diff --git a/kopete/protocols/jabber/CMakeLists.txt b/kopete/protocols/jabber/CMakeLists.txt new file mode 100644 index 00000000..d3fb6d79 --- /dev/null +++ b/kopete/protocols/jabber/CMakeLists.txt @@ -0,0 +1,85 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_subdirectory( ui ) +add_subdirectory( icons ) +add_subdirectory( libiris ) +add_subdirectory( kioslave ) + +if( WITH_JINGLE ) + add_subdirectory( jingle ) + set( SUPPORT_JINGLE 1 CACHE INTERNAL "" FORCE ) + set( JINGLE_LIBRARIES + kopetejabberjingle-static cricketsessionphone-static cricketxmllite-static + cricketp2pclient-static cricketxmpp-static cricketp2pbase-static cricketbase-static + mediastreamer-static ortp-static + ${GLIB2_LIBRARIES} ${GTHREAD2_LIBRARIES} ${GMODULE2_LIBRARIES} + ${EXPAT_LIBRARY} ${SPEEX_LIBRARIES} pthread + ) +endif( ) + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/ui + ${CMAKE_CURRENT_BINARY_DIR}/jingle + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/libiris/iris/include + ${CMAKE_CURRENT_SOURCE_DIR}/libiris/iris/jabber + ${CMAKE_CURRENT_SOURCE_DIR}/libiris/iris/xmpp-im + ${CMAKE_CURRENT_SOURCE_DIR}/libiris/qca/src + ${CMAKE_CURRENT_SOURCE_DIR}/libiris/cutestuff/util + ${CMAKE_CURRENT_SOURCE_DIR}/libiris/cutestuff/network + ${CMAKE_CURRENT_SOURCE_DIR}/ui + ${CMAKE_CURRENT_SOURCE_DIR}/jingle + ${CMAKE_CURRENT_SOURCE_DIR}/../../libkopete + ${CMAKE_CURRENT_SOURCE_DIR}/../../libkopete/ui + ${CMAKE_BINARY_DIR} + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + +link_directories( + ${TQT_LIBRARY_DIRS} +) + + +##### other data ################################ + +install( FILES kopete_jabber.desktop DESTINATION ${SERVICES_INSTALL_DIR} ) +install( FILES jabberchatui.rc DESTINATION ${DATA_INSTALL_DIR}/kopete_jabber ) + + +##### jabberclient (static) ##################### + +tde_add_library( jabberclient STATIC_PIC AUTOMOC + SOURCES + jabberclient.cpp jabberconnector.cpp jabberbytestream.cpp +) + + +##### kopete_jabber (module) #################### + +tde_add_kpart( kopete_jabber AUTOMOC + SOURCES + jabberprotocol.cpp jabberaccount.cpp jabberresource.cpp + jabberresourcepool.cpp jabberbasecontact.cpp jabbercontact.cpp + jabbergroupcontact.cpp jabbergroupmembercontact.cpp + jabbercontactpool.cpp jabberformtranslator.cpp jabberformlineedit.cpp + jabberchatsession.cpp jabbergroupchatmanager.cpp + jabberfiletransfer.cpp jabbercapabilitiesmanager.cpp + jabbertransport.cpp jabberbookmarks.cpp + LINK + jabberclient-static kopetejabberui-static + iris_jabber-static iris_xmpp_core-static iris_xmpp_im-static iris-static + qca-static cutestuff_network-static cutestuff_util-static ${JINGLE_LIBRARIES} + kopete-shared + DESTINATION ${PLUGIN_INSTALL_DIR} +) diff --git a/kopete/protocols/jabber/icons/CMakeLists.txt b/kopete/protocols/jabber/icons/CMakeLists.txt new file mode 100644 index 00000000..37a5c370 --- /dev/null +++ b/kopete/protocols/jabber/icons/CMakeLists.txt @@ -0,0 +1,12 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +tde_install_icons( ) diff --git a/kopete/protocols/jabber/jingle/CMakeLists.txt b/kopete/protocols/jabber/jingle/CMakeLists.txt new file mode 100644 index 00000000..18bbf758 --- /dev/null +++ b/kopete/protocols/jabber/jingle/CMakeLists.txt @@ -0,0 +1,38 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_subdirectory( libjingle ) + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/libjingle + ${CMAKE_CURRENT_SOURCE_DIR}/../libiris/iris/include + ${CMAKE_CURRENT_SOURCE_DIR}/../libiris/iris/xmpp-im + ${CMAKE_CURRENT_SOURCE_DIR}/../libiris/iris/jabber + ${CMAKE_CURRENT_SOURCE_DIR}/../libiris/cutestuff/util + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/kopete/libkopete + ${CMAKE_SOURCE_DIR}/kopete/libkopete/ui + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### kopetejabberjingle (static) ############### + +tde_moc( MOCS voicecaller.h ) + +tde_add_library( kopetejabberjingle STATIC_PIC AUTOMOC + SOURCES + jinglevoicecaller.cpp jinglevoicesessiondialogbase.ui + jinglevoicesessiondialog.cpp ${MOCS} +) diff --git a/kopete/protocols/jabber/jingle/jinglevoicecaller.cpp b/kopete/protocols/jabber/jingle/jinglevoicecaller.cpp index dd809cea..12e4b93d 100644 --- a/kopete/protocols/jabber/jingle/jinglevoicecaller.cpp +++ b/kopete/protocols/jabber/jingle/jinglevoicecaller.cpp @@ -374,3 +374,5 @@ cricket::Thread* JingleVoiceCaller::thread_ = NULL; cricket::NetworkManager* JingleVoiceCaller::network_manager_ = NULL; cricket::BasicPortAllocator* JingleVoiceCaller::port_allocator_ = NULL; cricket::SocketAddress* JingleVoiceCaller::stun_addr_ = NULL; + +#include "jinglevoicecaller.moc" diff --git a/kopete/protocols/jabber/jingle/libjingle/CMakeLists.txt b/kopete/protocols/jabber/jingle/libjingle/CMakeLists.txt new file mode 100644 index 00000000..0aa34648 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/CMakeLists.txt @@ -0,0 +1,12 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_subdirectory( talk ) diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/CMakeLists.txt b/kopete/protocols/jabber/jingle/libjingle/talk/CMakeLists.txt new file mode 100644 index 00000000..1a1d0416 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/CMakeLists.txt @@ -0,0 +1,19 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include( ConfigureChecks.cmake ) + +add_subdirectory( base ) +add_subdirectory( p2p ) +add_subdirectory( xmllite ) +add_subdirectory( xmpp ) +add_subdirectory( session ) +add_subdirectory( third_party ) diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/ConfigureChecks.cmake b/kopete/protocols/jabber/jingle/libjingle/talk/ConfigureChecks.cmake new file mode 100644 index 00000000..396efa92 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/ConfigureChecks.cmake @@ -0,0 +1,48 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +# gthread-2.0 +pkg_search_module( GTHREAD2 gthread-2.0 ) +if( NOT GTHREAD2_FOUND ) + tde_message_fatal( "gthread-2.0 is required, but was not found on your system" ) +endif( ) + + +# gmodule-2.0 +pkg_search_module( GMODULE2 gmodule-2.0 ) +if( NOT GMODULE2_FOUND ) + tde_message_fatal( "gmodule-2.0 are required, but not found on your system" ) +endif( ) + + +# speex +if( WITH_SPEEX ) + pkg_search_module( SPEEX speex ) + if( SPEEX_FOUND ) + set( HAVE_SPEEX 1 CACHE INTERNAL "" FORCE ) + if( NOT SPEEX_INCLUDE_DIRS ) + set( SPEEX_INCLUDE_DIRS "/usr/include/speex" ) + endif( ) + else( ) + tde_message_fatal( "speex is required, but was not found on your system" ) + endif( ) +endif( ) + +# expat +check_include_file( expat.h HAVE_EXPAT_H ) +if( HAVE_EXPAT_H ) + check_library_exists( expat XML_ParserCreate "" HAVE_EXPAT ) +endif( ) +if( HAVE_EXPAT_H AND HAVE_EXPAT ) + set( EXPAT_LIBRARY expat CACHE INTERNAL "" FORCE ) +else( ) + tde_message_fatal( "expat is required, but was not found on your system" ) +endif( ) diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/base/CMakeLists.txt b/kopete/protocols/jabber/jingle/libjingle/talk/base/CMakeLists.txt new file mode 100644 index 00000000..8f037a9a --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/base/CMakeLists.txt @@ -0,0 +1,32 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_definitions( + -DPOSIX +) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/../.. + ${CMAKE_BINARY_DIR} + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### cricketbase (static) ###################### + +tde_add_library( cricketbase STATIC_PIC + SOURCES + socketaddress.cc jtime.cc asyncudpsocket.cc messagequeue.cc + thread.cc physicalsocketserver.cc bytebuffer.cc asyncpacketsocket.cc + network.cc asynctcpsocket.cc socketadapters.cc md5c.c base64.cc + task.cc taskrunner.cc host.cc socketaddresspair.cc +) diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/base/asynctcpsocket.cc b/kopete/protocols/jabber/jingle/libjingle/talk/base/asynctcpsocket.cc index 6d4697a6..8bf66a38 100644 --- a/kopete/protocols/jabber/jingle/libjingle/talk/base/asynctcpsocket.cc +++ b/kopete/protocols/jabber/jingle/libjingle/talk/base/asynctcpsocket.cc @@ -32,6 +32,7 @@ #include "talk/base/byteorder.h" #include "talk/base/common.h" #include "talk/base/logging.h" +#include <cstring> #if defined(_MSC_VER) && _MSC_VER < 1300 namespace std { diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/base/bytebuffer.cc b/kopete/protocols/jabber/jingle/libjingle/talk/base/bytebuffer.cc index 067f50ed..e3af08b7 100644 --- a/kopete/protocols/jabber/jingle/libjingle/talk/base/bytebuffer.cc +++ b/kopete/protocols/jabber/jingle/libjingle/talk/base/bytebuffer.cc @@ -30,6 +30,7 @@ #include "talk/base/byteorder.h" #include <algorithm> #include <cassert> +#include <cstring> #if defined(_MSC_VER) && _MSC_VER < 1300 namespace std { diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/base/host.cc b/kopete/protocols/jabber/jingle/libjingle/talk/base/host.cc index 7b7490d9..f604050f 100644 --- a/kopete/protocols/jabber/jingle/libjingle/talk/base/host.cc +++ b/kopete/protocols/jabber/jingle/libjingle/talk/base/host.cc @@ -30,6 +30,8 @@ #include "talk/base/network.h" #include "talk/base/socket.h" #include <string> +#include <cstring> +#include <cstdlib> #include <iostream> #include <cassert> #include <errno.h> diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/base/messagequeue.h b/kopete/protocols/jabber/jingle/libjingle/talk/base/messagequeue.h index 2a9cbed6..9b35b9af 100644 --- a/kopete/protocols/jabber/jingle/libjingle/talk/base/messagequeue.h +++ b/kopete/protocols/jabber/jingle/libjingle/talk/base/messagequeue.h @@ -32,6 +32,7 @@ #include "talk/base/criticalsection.h" #include "talk/base/socketserver.h" #include "talk/base/jtime.h" +#include <string.h> #include <vector> #include <queue> #include <algorithm> diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/base/physicalsocketserver.cc b/kopete/protocols/jabber/jingle/libjingle/talk/base/physicalsocketserver.cc index 91d2daad..37836302 100644 --- a/kopete/protocols/jabber/jingle/libjingle/talk/base/physicalsocketserver.cc +++ b/kopete/protocols/jabber/jingle/libjingle/talk/base/physicalsocketserver.cc @@ -30,6 +30,7 @@ #endif #include <cassert> +#include <algorithm> #ifdef POSIX extern "C" { @@ -37,6 +38,7 @@ extern "C" { #include <fcntl.h> #include <sys/time.h> #include <unistd.h> +#include <string.h> } #endif @@ -59,9 +61,6 @@ extern "C" { #include <windows.h> #undef SetPort -#include <algorithm> -#include <iostream> - class WinsockInitializer { public: WinsockInitializer() { diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/base/socketadapters.cc b/kopete/protocols/jabber/jingle/libjingle/talk/base/socketadapters.cc index 049e923c..f57043e3 100644 --- a/kopete/protocols/jabber/jingle/libjingle/talk/base/socketadapters.cc +++ b/kopete/protocols/jabber/jingle/libjingle/talk/base/socketadapters.cc @@ -42,6 +42,7 @@ #endif #include <cassert> +#include <cstring> #include "talk/base/base64.h" #include "talk/base/basicdefs.h" diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/p2p/CMakeLists.txt b/kopete/protocols/jabber/jingle/libjingle/talk/p2p/CMakeLists.txt new file mode 100644 index 00000000..1708f179 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/p2p/CMakeLists.txt @@ -0,0 +1,13 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_subdirectory( base ) +add_subdirectory( client ) diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/CMakeLists.txt b/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/CMakeLists.txt new file mode 100644 index 00000000..ba05a061 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/CMakeLists.txt @@ -0,0 +1,52 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_definitions( + -DPOSIX +) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/../../.. + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### cricketp2pbase (static) ################### + +tde_add_library( cricketp2pbase STATIC_PIC + SOURCES + stun.cc port.cc udpport.cc tcpport.cc helpers.cc sessionmanager.cc + session.cc p2psocket.cc relayport.cc stunrequest.cc stunport.cc + socketmanager.cc +) + + +##### relayserver (executable) ################## + +tde_add_executable( relayserver + SOURCES + relayserver.cc relayserver_main.cc + LINK + cricketbase-static cricketp2pbase-static pthread + DESTINATION ${BIN_INSTALL_DIR} +) + + +##### stunserver (executable) ################### + +tde_add_executable( stunserver + SOURCES + stunserver.cc stunserver_main.cc + LINK + cricketbase-static cricketp2pbase-static pthread + DESTINATION ${BIN_INSTALL_DIR} +) diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/relayserver_main.cc b/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/relayserver_main.cc index 5f624f37..4dfae42c 100644 --- a/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/relayserver_main.cc +++ b/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/relayserver_main.cc @@ -30,6 +30,7 @@ #include "talk/p2p/base/relayserver.h" #include <iostream> #include <assert.h> +#include <cstring> #ifdef POSIX extern "C" { diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/stun.cc b/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/stun.cc index 6a22b238..2d6aa67c 100644 --- a/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/stun.cc +++ b/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/stun.cc @@ -29,6 +29,7 @@ #include "talk/p2p/base/stun.h" #include <iostream> #include <cassert> +#include <cstring> #if defined(_MSC_VER) && _MSC_VER < 1300 namespace std { diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/stunserver.cc b/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/stunserver.cc index 6e4f6b66..c6d9f9f8 100644 --- a/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/stunserver.cc +++ b/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/stunserver.cc @@ -28,6 +28,7 @@ #include "talk/base/bytebuffer.h" #include "talk/p2p/base/stunserver.h" #include <iostream> +#include <cstring> #ifdef POSIX extern "C" { diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/stunserver_main.cc b/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/stunserver_main.cc index bd8a96e5..bac3e35f 100644 --- a/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/stunserver_main.cc +++ b/kopete/protocols/jabber/jingle/libjingle/talk/p2p/base/stunserver_main.cc @@ -29,6 +29,7 @@ #include "talk/base/thread.h" #include "talk/p2p/base/stunserver.h" #include <iostream> +#include <cstring> #ifdef POSIX extern "C" { diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/p2p/client/CMakeLists.txt b/kopete/protocols/jabber/jingle/libjingle/talk/p2p/client/CMakeLists.txt new file mode 100644 index 00000000..7ede9820 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/p2p/client/CMakeLists.txt @@ -0,0 +1,30 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_definitions( + -DLINUX + -DPOSIX + -DINTERNAL_BUILD +) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/../../.. + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### cricketp2pclient (static) ################# + +tde_add_library( cricketp2pclient STATIC_PIC + SOURCES + sessionclient.cc basicportallocator.cc socketmonitor.cc +) diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/session/CMakeLists.txt b/kopete/protocols/jabber/jingle/libjingle/talk/session/CMakeLists.txt new file mode 100644 index 00000000..0b78949f --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/session/CMakeLists.txt @@ -0,0 +1,12 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_subdirectory( phone ) diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/session/phone/CMakeLists.txt b/kopete/protocols/jabber/jingle/libjingle/talk/session/phone/CMakeLists.txt new file mode 100644 index 00000000..3f22e535 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/session/phone/CMakeLists.txt @@ -0,0 +1,34 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_definitions( + -DPOSIX +) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/../../.. + ${CMAKE_CURRENT_SOURCE_DIR}/../../third_party/ortp + ${CMAKE_CURRENT_SOURCE_DIR}/../../third_party/mediastreamer + ${CMAKE_BINARY_DIR} + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} + ${GLIB2_INCLUDE_DIRS} + ${SPEEX_INCLUDE_DIRS} +) + + +##### cricketsessionphone (static) ############## + +tde_add_library( cricketsessionphone STATIC_PIC + SOURCES + audiomonitor.cc channelmanager.cc voicechannel.cc call.cc + phonesessionclient.cc linphonemediaengine.cc +) diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/session/phone/linphonemediaengine.cc b/kopete/protocols/jabber/jingle/libjingle/talk/session/phone/linphonemediaengine.cc index e363392c..f3244c54 100644 --- a/kopete/protocols/jabber/jingle/libjingle/talk/session/phone/linphonemediaengine.cc +++ b/kopete/protocols/jabber/jingle/libjingle/talk/session/phone/linphonemediaengine.cc @@ -27,7 +27,7 @@ extern "C" { #include "talk/third_party/mediastreamer/msspeexdec.h" #endif } -#include <ortp/ortp.h> +#include <ortp.h> #include <netdb.h> #include <unistd.h> #include <fcntl.h> diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/session/phone/phonesessionclient.cc b/kopete/protocols/jabber/jingle/libjingle/talk/session/phone/phonesessionclient.cc index d8a31df2..7f2ff11f 100644 --- a/kopete/protocols/jabber/jingle/libjingle/talk/session/phone/phonesessionclient.cc +++ b/kopete/protocols/jabber/jingle/libjingle/talk/session/phone/phonesessionclient.cc @@ -25,6 +25,8 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include <stdio.h> + #include "talk/base/logging.h" #include "talk/session/receiver.h" #include "talk/session/phone/phonesessionclient.h" diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/CMakeLists.txt b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/CMakeLists.txt new file mode 100644 index 00000000..da1647c0 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/CMakeLists.txt @@ -0,0 +1,13 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_subdirectory( mediastreamer ) +add_subdirectory( ortp ) diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/CMakeLists.txt b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/CMakeLists.txt new file mode 100644 index 00000000..8c5a923b --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/CMakeLists.txt @@ -0,0 +1,36 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_definitions( + -DG_LOG_DOMAIN="MediaStreamer" +) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../ortp + ${CMAKE_BINARY_DIR} + ${GLIB2_INCLUDE_DIRS} + ${SPEEX_INCLUDE_DIRS} +) + + +##### mediastreamer (static) #################### + +tde_add_library( mediastreamer STATIC_PIC + SOURCES + msfilter.c mscodec.c mssoundread.c mssoundwrite.c msbuffer.c + msqueue.c msfifo.c ms.c mssync.c msnosync.c msread.c mswrite.c + mscopy.c msosswrite.c msossread.c msringplayer.c msrtprecv.c + msrtpsend.c msAlawenc.c msAlawdec.c msMUlawenc.c msMUlawdec.c + mstimer.c msqdispatcher.c msfdispatcher.c sndcard.c osscard.c + hpuxsndcard.c alsacard.c jackcard.c audiostream.c msspeexenc.c + msspeexdec.c msilbcdec.c msilbcenc.c +) diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/msrtprecv.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/msrtprecv.h index 5c8b616c..0f36c379 100644 --- a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/msrtprecv.h +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/msrtprecv.h @@ -28,7 +28,7 @@ /* because of a conflict between config.h from oRTP and config.h from linphone:*/ #undef PACKAGE #undef VERSION -#include <ortp/ortp.h> +#include <ortp.h> /*this is the class that implements a copy filter*/ diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/msrtpsend.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/msrtpsend.c index b13dfe28..645a19cd 100644 --- a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/msrtpsend.c +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/msrtpsend.c @@ -19,7 +19,7 @@ */ #include "msrtpsend.h" -#include <ortp/telephonyevents.h> +#include <telephonyevents.h> #include "mssync.h" #include "mscodec.h" diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/msrtpsend.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/msrtpsend.h index 746e436d..96889964 100644 --- a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/msrtpsend.h +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/mediastreamer/msrtpsend.h @@ -27,7 +27,7 @@ #undef PACKAGE #undef VERSION -#include <ortp/ortp.h> +#include <ortp.h> /*this is the class that implements a sending through rtp filter*/ diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/CMakeLists.txt b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/CMakeLists.txt new file mode 100644 index 00000000..92a73a36 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/CMakeLists.txt @@ -0,0 +1,32 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_definitions( + -D_ORTP_SOURCE + -DG_LOG_DOMAIN="oRTP" +) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_BINARY_DIR} + ${GLIB2_INCLUDE_DIRS} +) + + +##### ortp (static) ############################# + +tde_add_library( ortp STATIC_PIC + SOURCES + port_fct.c rtpmod.c rtpparse.c rtpsession.c jitterctl.c + rtpsignaltable.c rtptimer.c posixtimer.c ortp.c scheduler.c + avprofile.c sessionset.c telephonyevents.c payloadtype.c rtcp.c + utils.c rtcpparse.c str_utils.c +) diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/avprofile.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/avprofile.c new file mode 100644 index 00000000..8917e21b --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/avprofile.c @@ -0,0 +1,281 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include <payloadtype.h> + +char offset127=127; +char offset0xD5=0xD5; +char offset0=0; + +/* IMPORTANT */ +/* some compiler don't support the "field:" syntax. Those macros are there to trap the problem +This means that if you want to keep portability, payload types must be defined with their fields +in the right order. */ + +#if !defined(__hpux) && !defined(WIN32) + +#define TYPE(val) type: (val) +#define CLOCK_RATE(val) clock_rate: (val) +#define BITS_PER_SAMPLE(val) bits_per_sample: (val) +#define ZERO_PATTERN(val) zero_pattern: (val) +#define PATTERN_LENGTH(val) pattern_length: (val) +#define NORMAL_BITRATE(val) normal_bitrate: (val) +#define MIME_TYPE(val) mime_type: (val) +#define FMTP(val) FMTP : (val) + +#else + +#define TYPE(val) (val) +#define CLOCK_RATE(val) (val) +#define BITS_PER_SAMPLE(val) (val) +#define ZERO_PATTERN(val) (val) +#define PATTERN_LENGTH(val) (val) +#define NORMAL_BITRATE(val) (val) +#define MIME_TYPE(val) (val) +#define FMTP(val) (val) + +#endif + +PayloadType pcmu8000={ + TYPE( PAYLOAD_AUDIO_CONTINUOUS), + CLOCK_RATE( 8000), + BITS_PER_SAMPLE(8), + ZERO_PATTERN( &offset127), + PATTERN_LENGTH( 1), + NORMAL_BITRATE( 64000), + MIME_TYPE ("PCMU") +}; + +PayloadType pcma8000={ + TYPE( PAYLOAD_AUDIO_CONTINUOUS), + CLOCK_RATE(8000), + BITS_PER_SAMPLE(8), + ZERO_PATTERN( &offset0xD5), + PATTERN_LENGTH( 1), + NORMAL_BITRATE( 64000), + MIME_TYPE ("PCMA") +}; + +PayloadType pcm8000={ + TYPE( PAYLOAD_AUDIO_CONTINUOUS), + CLOCK_RATE(8000), + BITS_PER_SAMPLE(16), + ZERO_PATTERN( &offset0), + PATTERN_LENGTH(1), + NORMAL_BITRATE( 128000), + MIME_TYPE ("PCM") +}; + +PayloadType lpc1016={ + TYPE( PAYLOAD_AUDIO_PACKETIZED), + CLOCK_RATE(8000), + BITS_PER_SAMPLE( 0), + ZERO_PATTERN( NULL), + PATTERN_LENGTH( 0), + NORMAL_BITRATE( 2400), + MIME_TYPE ("1016") +}; + + +PayloadType gsm= +{ + TYPE( PAYLOAD_AUDIO_PACKETIZED), + CLOCK_RATE(8000), + BITS_PER_SAMPLE( 0), + ZERO_PATTERN(NULL), + PATTERN_LENGTH( 0), + NORMAL_BITRATE( 13500), + MIME_TYPE ("GSM") +}; + +PayloadType payload_type_g7231= +{ + TYPE( PAYLOAD_AUDIO_PACKETIZED), + CLOCK_RATE(8000), + BITS_PER_SAMPLE( 0), + ZERO_PATTERN(NULL), + PATTERN_LENGTH( 0), + NORMAL_BITRATE( 6300), + MIME_TYPE ("G723") +}; + +PayloadType payload_type_g729={ + TYPE( PAYLOAD_AUDIO_PACKETIZED), + CLOCK_RATE(8000), + BITS_PER_SAMPLE( 0), + ZERO_PATTERN(NULL), + PATTERN_LENGTH( 0), + NORMAL_BITRATE( 8000), + MIME_TYPE ("G729") +}; + +PayloadType mpv= +{ + TYPE( PAYLOAD_VIDEO), + CLOCK_RATE(90000), + BITS_PER_SAMPLE(0), + ZERO_PATTERN(NULL), + PATTERN_LENGTH(0), + NORMAL_BITRATE( 256000), + MIME_TYPE ("MPV") +}; + + +PayloadType h261={ + TYPE( PAYLOAD_VIDEO), + CLOCK_RATE(90000), + BITS_PER_SAMPLE(0), + ZERO_PATTERN(NULL), + PATTERN_LENGTH(0), + NORMAL_BITRATE(0), + MIME_TYPE ("H261") +}; + +PayloadType h263={ + TYPE( PAYLOAD_VIDEO), + CLOCK_RATE(90000), + BITS_PER_SAMPLE(0), + ZERO_PATTERN(NULL), + PATTERN_LENGTH(0), + NORMAL_BITRATE(256000), + MIME_TYPE ("H263") +}; + +PayloadType truespeech= +{ + TYPE( PAYLOAD_AUDIO_PACKETIZED), + CLOCK_RATE(8000), + BITS_PER_SAMPLE( 0), + ZERO_PATTERN(NULL), + PATTERN_LENGTH( 0), + NORMAL_BITRATE(8536), + MIME_TYPE ("TSP0") +}; + + +RtpProfile av_profile; + + +void av_profile_init(RtpProfile *profile) +{ + rtp_profile_clear_all(profile); + rtp_profile_set_name(profile,"AV profile"); + rtp_profile_set_payload(profile,0,&pcmu8000); + rtp_profile_set_payload(profile,1,&lpc1016); + rtp_profile_set_payload(profile,3,&gsm); + rtp_profile_set_payload(profile,4,&payload_type_g7231); + rtp_profile_set_payload(profile,8,&pcma8000); + rtp_profile_set_payload(profile,18,&payload_type_g729); + rtp_profile_set_payload(profile,31,&h261); + rtp_profile_set_payload(profile,32,&mpv); + rtp_profile_set_payload(profile,34,&h263); +} + +/* these are extra payload types that can be used dynamically */ +PayloadType lpc1015={ + TYPE( PAYLOAD_AUDIO_PACKETIZED), + CLOCK_RATE(8000), + BITS_PER_SAMPLE(0), + ZERO_PATTERN(NULL), + PATTERN_LENGTH(0), + NORMAL_BITRATE(2400), + MIME_TYPE ("1015") +}; + +PayloadType speex_nb={ + TYPE( PAYLOAD_AUDIO_PACKETIZED), + CLOCK_RATE(8000), + BITS_PER_SAMPLE(0), + ZERO_PATTERN(NULL), + PATTERN_LENGTH(0), + NORMAL_BITRATE(8000), /*not true: 8000 is the minimum*/ + MIME_TYPE ("speex") +}; + +PayloadType speex_wb={ + TYPE( PAYLOAD_AUDIO_PACKETIZED), + CLOCK_RATE(16000), + BITS_PER_SAMPLE(0), + ZERO_PATTERN(NULL), + PATTERN_LENGTH(0), + NORMAL_BITRATE(28000), + MIME_TYPE ("speex") +}; + +PayloadType payload_type_ilbc={ + TYPE( PAYLOAD_AUDIO_PACKETIZED), + CLOCK_RATE(8000), + BITS_PER_SAMPLE(0), + ZERO_PATTERN(NULL), + PATTERN_LENGTH(0), + NORMAL_BITRATE(13300), /* the minimum, with 30ms frames */ + MIME_TYPE ("iLBC"), +}; + +PayloadType amr={ + TYPE(PAYLOAD_AUDIO_PACKETIZED), + CLOCK_RATE(8000), + BITS_PER_SAMPLE(0), + ZERO_PATTERN(NULL), + PATTERN_LENGTH(0), + NORMAL_BITRATE(0), + MIME_TYPE ("AMR") +}; + +PayloadType amrwb={ + TYPE(PAYLOAD_AUDIO_PACKETIZED), + CLOCK_RATE(16000), + BITS_PER_SAMPLE(0), + ZERO_PATTERN(NULL), + PATTERN_LENGTH(0), + NORMAL_BITRATE(0), + MIME_TYPE ("AMR-WB") +}; + +PayloadType mp4v={ + TYPE( PAYLOAD_VIDEO), + CLOCK_RATE(90000), + BITS_PER_SAMPLE(0), + ZERO_PATTERN(NULL), + PATTERN_LENGTH(0), + NORMAL_BITRATE(0), + MIME_TYPE ("MP4V-ES") +}; + + +PayloadType h263_1998={ + TYPE( PAYLOAD_VIDEO), + CLOCK_RATE(90000), + BITS_PER_SAMPLE(0), + ZERO_PATTERN(NULL), + PATTERN_LENGTH(0), + NORMAL_BITRATE(0), + MIME_TYPE ("H263-1998") +}; + +PayloadType h263_2000={ + TYPE( PAYLOAD_VIDEO), + CLOCK_RATE(90000), + BITS_PER_SAMPLE(0), + ZERO_PATTERN(NULL), + PATTERN_LENGTH(0), + NORMAL_BITRATE(0), + MIME_TYPE ("H263-2000") +}; diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/export.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/export.c new file mode 100644 index 00000000..0f061c36 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/export.c @@ -0,0 +1,25 @@ +/* + * file : export.c + * + * this file is used when building the oRTP stack as a dynamic loadable library + * on win32 OS. Indeed, structures cannot been exported 'as is' using the .def + * file. Since we want to use the av_profile and telephone_event instances as defined + * in the original source code, We have to implement those 2 functions to retrieve + * pointers on them. + * + */ + + +#include "export.h" + + +RtpProfile * get_av_profile( void ) +{ + return &av_profile; +} + +PayloadType * get_telephone_event( void ) +{ + return &telephone_event; +} + diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/export.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/export.h new file mode 100644 index 00000000..0f5a3992 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/export.h @@ -0,0 +1,38 @@ +/* + * file : export.h + * + * this file is used when building the oRTP stack as a dynamic loadable library + * on win32 OS. Indeed, structures cannot been exported 'as is' using the .def + * file. Since we want to use the av_profile and telephone_event instances as defined + * in the original source code, We have to implement those 2 functions to retrieve + * pointers on them. + * + */ + + + +#ifndef EXPORT_H +#define EXPORT_H + + +#if defined __cplusplus +extern "C" +{ +#endif + + +#include "payloadtype.h" +#include "telephonyevents.h" + + + RtpProfile * get_av_profile( void ); + PayloadType * get_telephone_event( void ); + + + +#if defined __cplusplus +} +#endif + + +#endif diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/jitterctl.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/jitterctl.c new file mode 100644 index 00000000..5f236f71 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/jitterctl.c @@ -0,0 +1,141 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/*************************************************************************** + * jitterctl.c + * + * Mon Nov 8 11:53:21 2004 + * Copyright 2004 Simon MORLAT + * Email simon.morlat@linphone.org + ****************************************************************************/ + +#include <rtpsession.h> +#include <payloadtype.h> +#include <math.h> +#include <stdlib.h> + +#define JC_BETA 0.03 /*allows a clock slide around 3% */ +#define JC_GAMMA (JC_BETA) + +#include "jitterctl.h" + +void jitter_control_init(JitterControl *ctl, int base_jiitt_time, PayloadType *payload){ + ctl->count=0; + ctl->slide=0; + ctl->jitter=0; + ctl->inter_jitter=0; + ctl->slide=0; + if (base_jiitt_time!=-1) ctl->jitt_comp = base_jiitt_time; + /* convert in timestamp unit: */ + if (payload!=NULL){ + jitter_control_set_payload(ctl,payload); + } + ctl->adapt_jitt_comp_ts=ctl->jitt_comp_ts; + ctl->corrective_slide=0; +} + +void jitter_control_enable_adaptive(JitterControl *ctl, gboolean val){ + ctl->adaptive=val; +} + +void jitter_control_set_payload(JitterControl *ctl, PayloadType *pt){ + ctl->jitt_comp_ts = + (gint) (((double) ctl->jitt_comp / 1000.0) * (pt->clock_rate)); + ctl->corrective_step=(160 * 8000 )/pt->clock_rate; /* This formula got to me after some beers */ + ctl->adapt_jitt_comp_ts=ctl->jitt_comp_ts; +} + + +void jitter_control_dump_stats(JitterControl *ctl){ + g_log("oRTP-stats",G_LOG_LEVEL_MESSAGE,"JitterControl:\n\tslide=%g,jitter=%g,count=%i", + ctl->slide,ctl->jitter, ctl->count); +} + + +/* + The algorithm computes two values: + slide: an average of difference between the expected and the socket-received timestamp + jitter: an average of the absolute value of the difference between socket-received timestamp and slide. + slide is used to make clock-slide detection and correction. + jitter is added to the initial jitt_comp_time value. It compensates bursty packets arrival (packets + not arriving at regular interval ). +*/ +void jitter_control_new_packet(JitterControl *ctl, guint32 packet_ts, guint32 cur_str_ts, gint32 * slide, gint32 *safe_delay){ + int diff=packet_ts - cur_str_ts; + float gap; + int d; + //printf("diff=%g\n",diff); + + ctl->count++; + ctl->slide= (ctl->slide*(1-JC_BETA)) + ((float)diff*JC_BETA); + gap=fabs((float)diff - ctl->slide); + ctl->jitter=(ctl->jitter*(1-JC_GAMMA)) + (gap*JC_GAMMA); + d=diff-ctl->olddiff; + ctl->inter_jitter=ctl->inter_jitter+ (( (float)abs(d) - ctl->inter_jitter)*(1/16.0)); + ctl->olddiff=diff; + if (ctl->adaptive){ + int tmp; + if (ctl->count%50==0) { + /*jitter_control_dump_stats(ctl);*/ + } + tmp=(int)(ctl->slide)-ctl->corrective_slide; + if (tmp>ctl->corrective_step) ctl->corrective_slide+=ctl->corrective_step; + else if (tmp<-ctl->corrective_step) ctl->corrective_slide-=ctl->corrective_step; + /* the following is nearly equivalent, but maybe it consumes more CPU: ?*/ + /*ctl->corrective_slide=(((gint)ctl->slide)/ctl->corrective_step)*ctl->corrective_step;*/ + + ctl->adapt_jitt_comp_ts=MAX(ctl->jitt_comp_ts,ctl->jitter); + + *slide=(gint32)ctl->slide; + *safe_delay=(gint32)ctl->adapt_jitt_comp_ts; + }else { + *slide=0; + *safe_delay=(gint32)ctl->jitt_comp_ts; + } + return ; +} + + +/** + *rtp_session_set_jitter_compensation: + *@session: a RtpSession + *@milisec: the time interval in milisec to be jitter compensed. + * + * Sets the time interval for which packet are buffered instead of being delivered to the + * application. + **/ +void +rtp_session_set_jitter_compensation (RtpSession * session, gint milisec) +{ + PayloadType *payload = rtp_profile_get_payload (session->profile, + session-> + payload_type); + if (payload==NULL){ + g_warning("rtp_session_set_jitter_compensation: cannot set because the payload type is unknown"); + return; + } + jitter_control_init(&session->rtp.jittctl,milisec,payload); +} + +void rtp_session_enable_adaptive_jitter_compensation(RtpSession *session, gboolean val){ + jitter_control_enable_adaptive(&session->rtp.jittctl,val); +} + +gboolean rtp_session_adaptive_jitter_compensation_enabled(RtpSession *session){ + return session->rtp.jittctl.adaptive; +} diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/jitterctl.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/jitterctl.h new file mode 100644 index 00000000..8e6986a9 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/jitterctl.h @@ -0,0 +1,38 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +/*************************************************************************** + * jitterctl.c + * + * Mon Nov 8 11:53:21 2004 + * Copyright 2004 Simon MORLAT + * Email simon.morlat@linphone.org + ****************************************************************************/ + +#ifndef JITTERCTL_H +#define JITTERCTL_H + + +void jitter_control_init(JitterControl *ctl, int base_jiitt_time, PayloadType *pt); +void jitter_control_enable_adaptive(JitterControl *ctl, gboolean val); +void jitter_control_new_packet(JitterControl *ctl, guint32 packet_ts, guint32 cur_str_ts, + gint32 * slide, gint32 *safe_delay); +#define jitter_control_adaptive_enabled(ctl) ((ctl)->adaptive) +void jitter_control_set_payload(JitterControl *ctl, PayloadType *pt); + +#endif diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/ortp-config.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/ortp-config.h new file mode 100644 index 00000000..049a76d8 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/ortp-config.h @@ -0,0 +1,9 @@ +#include <config.h> + +#define ORTP_MAJOR_VERSION 0 +#define ORTP_MINOR_VERSION 7 +#define ORTP_MICRO_VERSION 1 +#define ORTP_EXTRA_VERSION +#define ORTP_VERSION "0.7.1" + +#define POSIXTIMER_INTERVAL 10000 diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/ortp.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/ortp.c new file mode 100644 index 00000000..80e07682 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/ortp.c @@ -0,0 +1,258 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <ortp.h> +#include "scheduler.h" +#include <stdlib.h> + +rtp_stats_t ortp_global_stats; + +#ifdef ENABLE_MEMCHECK +gint ortp_allocations=0; +#endif + + +RtpScheduler *__ortp_scheduler; + + +void dummy_log(const gchar *log_domain, + GLogLevelFlags log_level, + const gchar *message, + gpointer user_data) +{ + return; +} + +extern void av_profile_init(RtpProfile *profile); + +static void init_random_number_generator(){ + struct timeval t; + gettimeofday(&t,NULL); + srandom(t.tv_usec+t.tv_sec); +} + +/** + *ortp_init: + * + * Initialize the oRTP library. You should call this function first before using + * oRTP API. +**/ + +void ortp_init() +{ + static gboolean initialized=FALSE; + if (initialized) return; + initialized=TRUE; + +#ifdef _WIN32 + WORD wVersionRequested; + WSADATA wsaData; + + wVersionRequested = MAKEWORD( 1, 0 ); + + if (WSAStartup(wVersionRequested,&wsaData)!=0) + { + g_error("Fail to initialise socket api"); + } +#endif + +#ifdef HAVE_GLIB + if (!g_thread_supported()) g_thread_init (NULL); +#endif + av_profile_init(&av_profile); + ortp_global_stats_reset(); + init_random_number_generator(); + g_message("oRTP-" ORTP_VERSION "initialized."); +} + + +/** + *ortp_scheduler_init: + * + * Initialize the oRTP scheduler. You only have to do that if you intend to use the + * scheduled mode of the #RtpSession in your application. + * +**/ +void ortp_scheduler_init() +{ + static gboolean initialized=FALSE; + if (initialized) return; + initialized=TRUE; +#ifdef __hpux + /* on hpux, we must block sigalrm on the main process, because signal delivery + is ?random?, well, sometimes the SIGALRM goes to both the main thread and the + scheduler thread */ + sigset_t set; + sigemptyset(&set); + sigaddset(&set,SIGALRM); + sigprocmask(SIG_BLOCK,&set,NULL); +#endif /* __hpux */ + if (!g_thread_supported()) g_thread_init(NULL); + __ortp_scheduler=rtp_scheduler_new(); + rtp_scheduler_start(__ortp_scheduler); + //sleep(1); +} + + +/** + *ortp_exit: + * + * Gracefully uninitialize the library, including shutdowning the scheduler if it was started. + * +**/ +void ortp_exit() +{ + if (__ortp_scheduler!=NULL) + { + rtp_scheduler_destroy(__ortp_scheduler); + __ortp_scheduler=NULL; + } +} + +/** + *ortp_get_scheduler: + * + * Returns a pointer to the scheduler, NULL if it was not running. + * The application developer should have to call this function. + * + *Returns: a pointer to the scheduler. +**/ +RtpScheduler * ortp_get_scheduler() +{ + if (__ortp_scheduler==NULL) g_error("Cannot use the scheduled mode: the scheduler is not " + "started. Call ortp_scheduler_init() at the begginning of the application."); + return __ortp_scheduler; +} + + +void ortp_log(const gchar *log_domain,GLogLevelFlags log_level, + const gchar *message, + gpointer user_data) +{ + gchar *lev; + switch(log_level){ + case G_LOG_LEVEL_MESSAGE: + lev="message"; + break; + case G_LOG_LEVEL_WARNING: + lev="warning"; + break; + case G_LOG_LEVEL_ERROR: + lev="error"; + default: + lev="(unknown log type)"; + } + if (user_data==NULL){ + user_data=stdout; + } + fprintf((FILE*)user_data,"%s-%s:%s\n",log_domain,lev,message); +} + + +/** + *ortp_set_debug_file: + *@domain: one of "oRTP" or "oRTP-stats" logging domain. + *@file: a FILE pointer where to output the messages from the domain. + * + * Warning: domain is ignored when not compiling with glib support. +**/ +void ortp_set_debug_file(gchar *domain,FILE *file) +{ + if (file!=NULL) + g_log_set_handler (domain, G_LOG_LEVEL_MASK, ortp_log, (gpointer)file); + else g_log_set_handler (domain, G_LOG_LEVEL_MASK, dummy_log, NULL); +} +/** + *ortp_set_log_handler: + *@domain: one of the "oRTP" or "oRTP-stats" logging domain. + *@func: your logging function, compatible with the GLogFunc prototype. + * + * Warning: domain is ignored when not compiling with glib support. +**/ +void ortp_set_log_handler(const gchar *domain, GLogFunc func, gpointer userdata){ + g_log_set_handler(domain,G_LOG_LEVEL_MASK,func,userdata); +} + + + +void ortp_global_stats_display() +{ + rtp_stats_display(&ortp_global_stats,"Global statistics"); +#ifdef ENABLE_MEMCHECK + printf("Unfreed allocations: %i\n",ortp_allocations); +#endif +} + + +void rtp_stats_display(rtp_stats_t *stats, char *header) +{ + + g_log("oRTP-stats",G_LOG_LEVEL_MESSAGE, + "\n %s :\n" + " number of rtp packet sent=%lld\n" + " number of rtp bytes sent=%lld bytes\n" + " number of rtp packet received=%lld\n" + " number of rtp bytes received=%lld bytes\n" + " number of incoming rtp bytes successfully delivered to the application=%lld \n" + " number of times the application queried a packet that didn't exist=%lld \n" + " number of rtp packets received too late=%lld\n" + " number of rtp packets skipped=%lld\n" + " number of bad formatted rtp packets=%lld\n" + " number of packet discarded because of queue overflow=%lld\n", + header, + (long long)stats->packet_sent, + (long long)stats->sent, + (long long)stats->packet_recv, + (long long)stats->hw_recv, + (long long)stats->recv, + (long long)stats->unavaillable, + (long long)stats->outoftime, + (long long)stats->skipped, + (long long)stats->bad, + (long long)stats->discarded); +} + +void ortp_global_stats_reset(){ + memset(&ortp_global_stats,0,sizeof(rtp_stats_t)); +} + +rtp_stats_t *ortp_get_global_stats(){ + return &ortp_global_stats; +} + +void rtp_stats_reset(rtp_stats_t *stats){ + memset((void*)stats,0,sizeof(rtp_stats_t)); +} + + +/** + *ortp_min_version_required: + *@major: + *@minor: + *@micro: + * + * This function give the opportunity to programs to check if the libortp they link to + * has the minimum version number they need. + * + * Returns: true if ortp has a version number greater or equal than the required one. +**/ +gboolean ortp_min_version_required(int major, int minor, int micro){ + return ((major*1000000) + (minor*1000) + micro) <= + ((ORTP_MAJOR_VERSION*1000000) + (ORTP_MINOR_VERSION*1000) + ORTP_MICRO_VERSION); +} diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/ortp.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/ortp.h new file mode 100644 index 00000000..a3c8b01c --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/ortp.h @@ -0,0 +1,54 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#ifndef ORTP_H +#define ORTP_H + +#include <rtpsession.h> +#include <sessionset.h> + +#ifdef __cplusplus +extern "C" +{ +#endif +gboolean ortp_min_version_required(int major, int minor, int micro); +void ortp_init(); +void ortp_scheduler_init(); +void ortp_exit(); + + +void ortp_set_debug_file(gchar *domain, FILE *file); +/* domain is ignored when not compiling with glib support */ +void ortp_set_log_handler(const gchar *domain, GLogFunc func, gpointer ud); + +extern rtp_stats_t ortp_global_stats; + +void ortp_global_stats_reset(); +rtp_stats_t *ortp_get_global_stats(); + +void ortp_global_stats_display(); +void rtp_stats_display(rtp_stats_t *stats, char *header); +void rtp_stats_reset(rtp_stats_t *stats); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/payloadtype.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/payloadtype.c new file mode 100644 index 00000000..c4886208 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/payloadtype.c @@ -0,0 +1,268 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <payloadtype.h> + +#include <stdio.h> +#include <stdlib.h> + +#ifdef WIN32 +#define snprintf _snprintf +#define strcasecmp stricmp +#endif + +/** + *rtp_profile_clear_all: + *@profile: an RTP profile (#RtpProfile object) + * + * Initialize the profile to the empty profile (all payload type are unassigned). + * +**/ + +/** + *rtp_profile_set_name: + *@profile: a rtp profile object (#RtpProfile) + *@nm: a string + * + * Set a name to the rtp profile. (This is not required) + * +**/ + +/** + *rtp_profile_get_name: + *@profile: a rtp profile object (#RtpProfile) + * + *Returns: the name of the rtp profile. May be NULL. +**/ + +/** + *rtp_profile_set_payload: + *@profile: an RTP profile (a #RtpProfile object) + *@index: the payload type number + *@pt: the payload type description (a #PayloadType object ) + * + * Assign payload type number @index to payload type desribed in @pt for the RTP profile + * @profile. + * +**/ + +/** + *rtp_profile_get_payload: + *@profile: an RTP profile (a #RtpProfile object) + *@index: the payload type number + * + * Gets the payload description of the payload type @index in the profile @profile. + * + *Returns: the payload description (a #PayloadType object) +**/ + +/** + *rtp_profile_clear_payload: + *@profile: an RTP profile (a #RtpProfile object) + *@index: the payload type number + * + * Set payload type number @index unassigned in profile @profile. + * +**/ + +char *payload_type_get_rtpmap(PayloadType *pt) +{ + int len=strlen(pt->mime_type)+15; + char *rtpmap=g_malloc(len); + snprintf(rtpmap,len,"%s/%i/1",pt->mime_type,pt->clock_rate); + return rtpmap; +} + +PayloadType *payload_type_new() +{ + PayloadType *newpayload=g_new0(PayloadType,1); + newpayload->flags|=PAYLOAD_TYPE_ALLOCATED; + return newpayload; +} + + +PayloadType *payload_type_clone(PayloadType *payload) +{ + PayloadType *newpayload=g_new0(PayloadType,1); + memcpy(newpayload,payload,sizeof(PayloadType)); + newpayload->mime_type=g_strdup(payload->mime_type); + if (payload->fmtp!=NULL) newpayload->fmtp=g_strdup(payload->fmtp); + newpayload->flags|=PAYLOAD_TYPE_ALLOCATED; + return newpayload; +} + +void payload_type_destroy(PayloadType *pt) +{ + g_free(pt->mime_type); + g_free(pt->fmtp); + g_free(pt); +} + +gint rtp_profile_get_payload_number_from_mime(RtpProfile *profile,const char *mime) +{ + PayloadType *pt; + gint i; + for (i=0;i<RTP_PROFILE_MAX_PAYLOADS;i++) + { + pt=rtp_profile_get_payload(profile,i); + if (pt!=NULL) + { + if (strcasecmp(pt->mime_type,mime)==0){ + return i; + } + } + } + return -1; +} + +gint rtp_profile_find_payload_number(RtpProfile*profile,const gchar *mime,int rate) +{ + int i; + PayloadType *pt; + for (i=0;i<RTP_PROFILE_MAX_PAYLOADS;i++) + { + pt=rtp_profile_get_payload(profile,i); + if (pt!=NULL) + { + if (strcasecmp(pt->mime_type,mime)==0 && pt->clock_rate==rate){ + + return i; + } + } + } + return -1; +} + +gint rtp_profile_get_payload_number_from_rtpmap(RtpProfile *profile,const char *rtpmap) +{ + gint clock_rate,ret; + char *p,*mime,*tmp,*c; + + /* parse the rtpmap */ + tmp=g_strdup(rtpmap); + p=strchr(tmp,'/'); + if (p!=NULL){ + mime=tmp; + *p='\0'; + c=p+1; + p=strchr(c,'/'); + if (p!=NULL) *p='\0'; + clock_rate=atoi(c); + }else return -1; + + //printf("Searching for payload %s at freq %i",mime,clock_rate); + ret=rtp_profile_find_payload_number(profile,mime,clock_rate); + g_free(tmp); + return ret; +} + +PayloadType * rtp_profile_find_payload(RtpProfile *prof,const gchar *mime,int rate) +{ + int i; + i=rtp_profile_find_payload_number(prof,mime,rate); + if (i>=0) return rtp_profile_get_payload(prof,i); + return NULL; +} + + +PayloadType * rtp_profile_get_payload_from_mime(RtpProfile *profile,const char *mime) +{ + int pt; + pt=rtp_profile_get_payload_number_from_mime(profile,mime); + if (pt==-1) return NULL; + else return rtp_profile_get_payload(profile,pt); +} + + +PayloadType * rtp_profile_get_payload_from_rtpmap(RtpProfile *profile, const char *rtpmap) +{ + int pt; + pt=rtp_profile_get_payload_number_from_rtpmap(profile,rtpmap); + if (pt==-1) return NULL; + else return rtp_profile_get_payload(profile,pt); +} + +int rtp_profile_move_payload(RtpProfile *prof,int oldpos,int newpos){ + prof->payload[newpos]=prof->payload[oldpos]; + prof->payload[oldpos]=NULL; + return 0; +} + +RtpProfile * rtp_profile_new(const char *name) +{ + RtpProfile *prof=g_new0(RtpProfile,1); + rtp_profile_set_name(prof,name); + rtp_profile_clear_all(prof); + return prof; +} + +void rtp_profile_set_name(RtpProfile *obj, const char *name){ + if (obj->name!=NULL) g_free(obj->name); + obj->name=g_strdup(name); +} + +/* ! payload are not cloned*/ +RtpProfile * rtp_profile_clone(RtpProfile *prof) +{ + int i; + PayloadType *pt; + RtpProfile *newprof=rtp_profile_new(prof->name); + rtp_profile_clear_all(newprof); + for (i=0;i<128;i++){ + pt=rtp_profile_get_payload(prof,i); + if (pt!=NULL){ + rtp_profile_set_payload(newprof,i,pt); + } + } + return newprof; +} + +void rtp_profile_copy(const RtpProfile *orig, RtpProfile *dest){ + memcpy(dest,orig,sizeof(RtpProfile)); +} + + +/*clone a profile and its payloads */ +RtpProfile * rtp_profile_clone_full(RtpProfile *prof) +{ + int i; + PayloadType *pt; + RtpProfile *newprof=rtp_profile_new(prof->name); + rtp_profile_clear_all(newprof); + for (i=0;i<RTP_PROFILE_MAX_PAYLOADS;i++){ + pt=rtp_profile_get_payload(prof,i); + if (pt!=NULL){ + rtp_profile_set_payload(newprof,i,payload_type_clone(pt)); + } + } + return newprof; +} + +void rtp_profile_destroy(RtpProfile *prof) +{ + int i; + PayloadType *payload; + for (i=0;i<RTP_PROFILE_MAX_PAYLOADS;i++) + { + payload=rtp_profile_get_payload(prof,i); + if (payload!=NULL && (payload->flags & PAYLOAD_TYPE_ALLOCATED)) + payload_type_destroy(payload); + } + g_free(prof); +} diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/payloadtype.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/payloadtype.h new file mode 100644 index 00000000..e5efa797 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/payloadtype.h @@ -0,0 +1,136 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef PAYLOADTYPE_H +#define PAYLOADTYPE_H +#include <rtpport.h> + +typedef enum{ + PAYLOAD_TYPE_ALLOCATED = 1 +}PayloadTypeFlags; + +struct _PayloadType +{ + gint type; + #define PAYLOAD_AUDIO_CONTINUOUS 0 + #define PAYLOAD_AUDIO_PACKETIZED 1 + #define PAYLOAD_VIDEO 2 + #define PAYLOAD_OTHER 3 /* ?? */ + gint clock_rate; + char bits_per_sample; /* in case of continuous audio data */ + char *zero_pattern; + gint pattern_length; + /* other usefull information */ + gint normal_bitrate; /*in bit/s */ + char *mime_type; + char *fmtp; /*various parameters, as a string */ + PayloadTypeFlags flags; + void *user_data; +}; + +#ifndef PayloadType_defined +#define PayloadType_defined +typedef struct _PayloadType PayloadType; +#endif + +#ifdef __cplusplus +extern "C"{ +#endif +PayloadType *payload_type_new(); +PayloadType *payload_type_clone(PayloadType *payload); +void payload_type_destroy(PayloadType *pt); +#ifdef __cplusplus +} +#endif + +#define payload_type_set_flag(pt,flag) (pt)->flags|=(flag) +#define payload_type_unset_flag(pt,flag) (pt)->flags&=(~flag) + +#define RTP_PROFILE_MAX_PAYLOADS 128 + +struct _RtpProfile +{ + char *name; + PayloadType *payload[RTP_PROFILE_MAX_PAYLOADS]; +}; + + +typedef struct _RtpProfile RtpProfile; + + +extern RtpProfile av_profile; + +#define payload_type_set_user_data(pt,p) (pt)->user_data=(p) +#define payload_type_get_user_data(pt) ((pt)->user_data) + + + +#define rtp_profile_get_name(profile) (const char*)((profile)->name) +#define rtp_profile_set_payload(profile,index,pt) (profile)->payload[(index)]=(pt) +#define rtp_profile_clear_payload(profile,index) (profile)->payload[(index)]=NULL +#define rtp_profile_clear_all(profile) memset((void*)(profile),0,sizeof(RtpProfile)) +#define rtp_profile_get_payload(profile,index) ((profile)->payload[(index)]) +#ifdef __cplusplus +extern "C"{ +#endif +void rtp_profile_set_name(RtpProfile *prof, const char *name); +PayloadType * rtp_profile_get_payload_from_mime(RtpProfile *profile,const char *mime); +PayloadType * rtp_profile_get_payload_from_rtpmap(RtpProfile *profile, const char *rtpmap); +gint rtp_profile_get_payload_number_from_mime(RtpProfile *profile,const char *mime); +gint rtp_profile_get_payload_number_from_rtpmap(RtpProfile *profile, const char *rtpmap); +gint rtp_profile_find_payload_number(RtpProfile *prof,const gchar *mime,int rate); +PayloadType * rtp_profile_find_payload(RtpProfile *prof,const gchar *mime,int rate); +gint rtp_profile_move_payload(RtpProfile *prof,int oldpos,int newpos); + +RtpProfile * rtp_profile_new(const char *name); +/* clone a profile, payload are not cloned */ +RtpProfile * rtp_profile_clone(RtpProfile *prof); +/* copy a profile into another one; payload are not cloned */ +void rtp_profile_copy(const RtpProfile *orig, RtpProfile *dest); + +/*clone a profile and its payloads (ie payload type are newly allocated, not reusing payload types of the reference profile) */ +RtpProfile * rtp_profile_clone_full(RtpProfile *prof); +/* frees the profile and all its PayloadTypes*/ +void rtp_profile_destroy(RtpProfile *prof); +#ifdef __cplusplus +} +#endif + +/* some payload types */ +/* audio */ +extern PayloadType pcmu8000; +extern PayloadType pcma8000; +extern PayloadType pcm8000; +extern PayloadType lpc1016; +extern PayloadType gsm; +extern PayloadType lpc1015; +extern PayloadType speex_nb; +extern PayloadType speex_wb; +extern PayloadType payload_type_ilbc; +extern PayloadType truespeech; + +/* video */ +extern PayloadType mpv; +extern PayloadType h261; +extern PayloadType h263; + + + + +#endif diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/port_fct.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/port_fct.c new file mode 100644 index 00000000..2ad6b4dc --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/port_fct.c @@ -0,0 +1,183 @@ + +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* port_fct.h. define methods to help for portability between unix and win32 */ + +#include <unistd.h> + +#include <rtpport.h> +#include "port_fct.h" + + + +/* + * this method is an utility method that calls fnctl() on UNIX or + * ioctlsocket on Win32. + * int retrun the result of the system method + */ +int set_non_blocking_socket (gint sock) +{ + + +#ifndef _WIN32 + return fcntl (sock, F_SETFL, O_NONBLOCK); +#else + unsigned long nonBlock = 1; + return ioctlsocket(sock, FIONBIO , &nonBlock); +#endif +} + + +/* + * this method is an utility method that calls close() on UNIX or + * closesocket on Win32. + * int retrun the result of the system method + */ +#ifndef _WIN32 + int close_socket(gint sock) + { + return close (sock); + } +#else + int close_socket(SOCKET sock) + { + return closesocket(sock); + } +#endif + + + +/* + * getSocketError() return a string describing the error + */ +#ifdef _WIN32 +char *getSocketError() +{ + int error = WSAGetLastError (); + static char buf[80]; + + switch (error) + { + case WSANOTINITIALISED: return "Windows sockets not initialized : call WSAStartup"; + case WSAEADDRINUSE: return "Local Address already in use"; + case WSAEADDRNOTAVAIL: return "The specified address is not a valid address for this machine"; +// case WSAEFAULT: return ""; +// case WSAEINPROGRESS: return ""; + case WSAEINVAL: return "The socket is already bound to an address."; + case WSAENOBUFS: return "Not enough buffers available, too many connections."; + case WSAENOTSOCK: return "The descriptor is not a socket."; + case WSAECONNRESET: return "Connection reset by peer"; +/* + + case : return ""; + case : return ""; + case : return ""; + case : return ""; + case : return ""; + case : return ""; +*/ + default : + sprintf (buf,"Error code : %d", error); + return buf; + break; + } + + return buf; + +} +#endif + +#ifndef _WIN32 + /* Use UNIX inet_aton method */ +#else + int inet_aton (const char * cp, struct in_addr * addr) + { + unsigned long retval; + + retval = inet_addr (cp); + + if (retval == INADDR_NONE) + { + return -1; + } + else + { + addr->S_un.S_addr = retval; + return 1; + } + } +#endif + +#ifndef HAVE_GLIB + +char * g_strdup_vprintf(const char *fmt, va_list ap) +{ + /* Guess we need no more than 100 bytes. */ + int n, size = 100; + char *p; + if ((p = g_malloc (size)) == NULL) + return NULL; + while (1) + { + /* Try to print in the allocated space. */ + n = vsnprintf (p, size, fmt, ap); + /* If that worked, return the string. */ + if (n > -1 && n < size) + return p; + //printf("Reallocing space.\n"); + /* Else try again with more space. */ + if (n > -1) /* glibc 2.1 */ + size = n + 1; /* precisely what is needed */ + else /* glibc 2.0 */ + size *= 2; /* twice the old size */ + if ((p = g_realloc (p, size)) == NULL) + return NULL; + } +} + + + +extern void ortp_log(const gchar *log_domain,GLogLevelFlags log_level, + const gchar *message, + gpointer user_data); + +static GLogFunc __log_func=ortp_log; +static gpointer __log_user_data=(gpointer)NULL; + +void g_log(const gchar *log_domain,GLogLevelFlags log_level,const gchar *format,...){ + va_list args; + va_start(args,format); + g_logv(log_domain,log_level,format,args); + va_end(args); +} + +void g_logv(const gchar *log_domain,GLogLevelFlags log_level,const gchar *format,va_list args){ + gchar *msg; + msg=g_strdup_vprintf(format,args); + __log_func(log_domain,log_level,msg,__log_user_data); + g_free(msg); +} + +void g_log_set_handler(const gchar *log_domain,GLogLevelFlags log_levels, GLogFunc log_func, gpointer user_data){ + __log_func=log_func; + __log_user_data=user_data; +} + +#endif diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/port_fct.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/port_fct.h new file mode 100644 index 00000000..3b3abe31 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/port_fct.h @@ -0,0 +1,48 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* fct-win32.h. define unix methods that are not defined in win32 env */ + +#ifndef PORT_FCT_H +#define PORT_FCT_H + +#ifdef _WIN32 +#include <Winsock2.h> +#else +#include <fcntl.h> +#endif + +#include <rtpport.h> + +#ifndef _WIN32 +/* use unix pthread_t... */ + extern int close_socket(gint sock); +#else + #define pthread_t HANDLE + extern int pthread_create(pthread_t *thread,const void *attr,void *(__cdecl *start)(void *),void* arg); + extern int pthread_join(pthread_t thread,void **); + + extern int close_socket(SOCKET sock); + extern int inet_aton (const char * cp, struct in_addr * addr); +#endif + +extern int set_non_blocking_socket (int sock); +extern int set_thread_priority(); + +#endif diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/posixtimer.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/posixtimer.c new file mode 100644 index 00000000..9e20ead4 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/posixtimer.c @@ -0,0 +1,167 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <rtpport.h> +#include "rtptimer.h" + + +#ifndef _WIN32 + +#ifdef __linux__ +#include <sys/select.h> +#endif + +#include <sys/time.h> +#include <sys/types.h> +#include <unistd.h> + + +static struct timeval orig,cur; +static guint32 posix_timer_time=0; /*in milisecond */ + +void posix_timer_init() +{ + posix_timer.state=RTP_TIMER_RUNNING; + gettimeofday(&orig,NULL); + posix_timer_time=0; +} + + + + +void posix_timer_do() +{ + gint32 diff,time; + struct timeval tv; + + gettimeofday(&cur,NULL); + time=((cur.tv_usec-orig.tv_usec)/1000 ) + ((cur.tv_sec-orig.tv_sec)*1000 ); + if ( (diff=time-posix_timer_time)>50){ + g_warning("Must catchup %i miliseconds.",diff); + } + while((diff = posix_timer_time-time) > 0) + { + tv.tv_sec = diff/1000; + tv.tv_usec = (diff%1000)*1000; + select(0,NULL,NULL,NULL,&tv); + gettimeofday(&cur,NULL); + time=((cur.tv_usec-orig.tv_usec)/1000 ) + ((cur.tv_sec-orig.tv_sec)*1000 ); + } + posix_timer_time+=POSIXTIMER_INTERVAL/1000; + +} + +void posix_timer_uninit() +{ + posix_timer.state=RTP_TIMER_STOPPED; +} + +RtpTimer posix_timer={ 0, + posix_timer_init, + posix_timer_do, + posix_timer_uninit, + {0,POSIXTIMER_INTERVAL}}; + + +#else //WIN32 + +#include <windows.h> +#include <mmsystem.h> + + +MMRESULT timerId; +HANDLE TimeEvent; +int late_ticks; + + +static DWORD posix_timer_time; +static DWORD offset_time; + + +#define TIME_INTERVAL 50 +#define TIME_RESOLUTION 10 +#define TIME_TIMEOUT 100 + + + +void CALLBACK timerCb(UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2) +{ + // Check timerId + if (timerId == uID) + { + SetEvent(TimeEvent); + posix_timer_time += TIME_INTERVAL; + } +} + + +void win_timer_init(void) +{ + timerId = timeSetEvent(TIME_INTERVAL,10,timerCb,0,TIME_PERIODIC | TIME_CALLBACK_FUNCTION); + TimeEvent = CreateEvent(NULL,FALSE,FALSE,NULL); + + late_ticks = 0; + + offset_time = GetTickCount(); + posix_timer_time=0; +} + + +void win_timer_do(void) +{ + DWORD diff; + + // If timer have expired while we where out of this method + // Try to run after lost time. + if (late_ticks > 0) + { + late_ticks--; + posix_timer_time+=TIME_INTERVAL; + return; + } + + + diff = GetTickCount() - posix_timer_time - offset_time; + if( diff>TIME_INTERVAL && (diff<(1<<31))) + { + late_ticks = diff/TIME_INTERVAL; + g_warning("we must catchup %i ticks.",late_ticks); + return; + } + + WaitForSingleObject(TimeEvent,TIME_TIMEOUT); + return; +} + + +void win_timer_close(void) +{ + timeKillEvent(timerId); +} + +RtpTimer toto; + +RtpTimer posix_timer={ 0, + win_timer_init, + win_timer_do, + win_timer_close, + {0,TIME_INTERVAL * 1000}}; + + +#endif // _WIN32 diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtcp.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtcp.c new file mode 100644 index 00000000..78599ae5 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtcp.c @@ -0,0 +1,294 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/*************************************************************************** + * rtcp.c + * + * Wed Dec 1 11:45:30 2004 + * Copyright 2004 Simon Morlat + * Email simon dot morlat at linphone dot org + ****************************************************************************/ + +#include <rtpsession.h> +#include <rtcp.h> + +extern gint ortp_rtcp_send (RtpSession * session, mblk_t * m); + + +void rtcp_common_header_init(rtcp_common_header_t *ch, RtpSession *s,int type, int rc, int bytes_len){ + rtcp_common_header_set_version(ch,2); + rtcp_common_header_set_padbit(ch,0); + rtcp_common_header_set_packet_type(ch,type); + rtcp_common_header_set_rc(ch,rc); /* as we don't yet support multi source receiving */ + rtcp_common_header_set_length(ch,(bytes_len/4)-1); +} + +mblk_t *sdes_chunk_new(guint32 ssrc){ + mblk_t *m=allocb(RTCP_SDES_CHUNK_DEFAULT_SIZE,0); + sdes_chunk_t *sc=(sdes_chunk_t*)m->b_rptr; + sc->csrc=htonl(ssrc); + m->b_wptr+=sizeof(sc->csrc); + return m; +} + + +mblk_t * sdes_chunk_append_item(mblk_t *m, rtcp_sdes_type_t sdes_type, const gchar *content) +{ + if ( content ) + { + sdes_item_t si; + si.item_type=sdes_type; + si.len=MIN(strlen(content),RTCP_SDES_MAX_STRING_SIZE); + m=appendb(m,(char*)&si,RTCP_SDES_ITEM_HEADER_SIZE,FALSE); + m=appendb(m,content,si.len,FALSE); + } + return m; +} + +void sdes_chunk_set_ssrc(mblk_t *m, guint32 ssrc){ + sdes_chunk_t *sc=(sdes_chunk_t*)m->b_rptr; + sc->csrc=htonl(ssrc); +} + +#define sdes_chunk_get_ssrc(m) ntohl(((sdes_chunk_t*)((m)->b_rptr))->csrc) + +mblk_t * sdes_chunk_pad(mblk_t *m){ + return appendb(m,NULL,0,TRUE); +} + +void rtp_session_set_source_description(RtpSession *session, + const gchar *cname, const gchar *name, const gchar *email, const gchar *phone, + const gchar *loc, const gchar *tool, const gchar *note){ + mblk_t *chunk = sdes_chunk_new(session->send_ssrc); + mblk_t *m=chunk; + const gchar *_cname=cname; + if (_cname==NULL) + { + _cname="Unknown"; + } + chunk=sdes_chunk_append_item(chunk, RTCP_SDES_CNAME, _cname); + chunk=sdes_chunk_append_item(chunk, RTCP_SDES_NAME, name); + chunk=sdes_chunk_append_item(chunk, RTCP_SDES_EMAIL, email); + chunk=sdes_chunk_append_item(chunk, RTCP_SDES_PHONE, phone); + chunk=sdes_chunk_append_item(chunk, RTCP_SDES_LOC, loc); + chunk=sdes_chunk_append_item(chunk, RTCP_SDES_TOOL, tool); + chunk=sdes_chunk_append_item(chunk, RTCP_SDES_NOTE, note); + chunk=sdes_chunk_pad(chunk); + rtp_session_lock(session); + if (session->sd!=NULL) freemsg(session->sd); + session->sd=m; + rtp_session_unlock(session); +} + +void +rtp_session_add_contributing_source(RtpSession *session, guint32 csrc, + const gchar *cname, const gchar *name, const gchar *email, const gchar *phone, + const gchar *loc, const gchar *tool, const gchar *note) +{ + mblk_t *chunk = sdes_chunk_new(csrc); + mblk_t *m=chunk; + gchar *_cname=(gchar*)cname; + if (_cname==NULL) + { + _cname="toto"; + } + chunk=sdes_chunk_append_item(chunk, RTCP_SDES_CNAME, cname); + chunk=sdes_chunk_append_item(chunk, RTCP_SDES_NAME, name); + chunk=sdes_chunk_append_item(chunk, RTCP_SDES_EMAIL, email); + chunk=sdes_chunk_append_item(chunk, RTCP_SDES_PHONE, phone); + chunk=sdes_chunk_append_item(chunk, RTCP_SDES_LOC, loc); + chunk=sdes_chunk_append_item(chunk, RTCP_SDES_TOOL, tool); + chunk=sdes_chunk_append_item(chunk, RTCP_SDES_NOTE, note); + chunk=sdes_chunk_pad(chunk); + rtp_session_lock(session); + putq(&session->contributing_sources,m); + rtp_session_unlock(session); +} + + + +mblk_t* rtp_session_create_rtcp_sdes_packet(RtpSession *session) +{ + mblk_t *mp=allocb(sizeof(rtcp_common_header_t),0); + rtcp_common_header_t *rtcp; + mblk_t *tmp,*m=mp; + queue_t *q; + int rc=0; + rtcp = (rtcp_common_header_t*)mp->b_wptr; + mp->b_wptr+=sizeof(rtcp_common_header_t); + + /* concatenate all sdes chunks */ + sdes_chunk_set_ssrc(session->sd,session->send_ssrc); + m=concatb(m,dupmsg(session->sd)); + rc++; + + q=&session->contributing_sources; + for (tmp=qbegin(q); !qend(q,tmp); tmp=qnext(q,mp)){ + m=concatb(m,dupmsg(tmp)); + rc++; + } + rtcp_common_header_init(rtcp,session,RTCP_SDES,rc,msgdsize(mp)); + return mp; +} + + +mblk_t *rtcp_create_simple_bye_packet(guint32 ssrc, const gchar *reason) +{ + gint strsize=0; + gint packet_size; + mblk_t *mp; + rtcp_bye_t *rtcp; + packet_size = RTCP_BYE_HEADER_SIZE + 1 + strsize; + if (reason!=NULL) + strsize=MIN(strlen(reason),RTCP_BYE_REASON_MAX_STRING_SIZE); + mp = allocb(packet_size, 0); + + rtcp = (rtcp_bye_t*)mp->b_rptr; + + rtcp_common_header_init(&rtcp->ch,NULL,RTCP_BYE,1,packet_size); + rtcp->ssrc[0] = htonl(ssrc); + mp->b_wptr += packet_size; + /* append the reason if any*/ + if (reason!=NULL) + appendb(mp,reason,strsize,FALSE); + return mp; +} + +void rtp_session_remove_contributing_sources(RtpSession *session, guint32 ssrc) +{ + queue_t *q=&session->contributing_sources; + mblk_t *tmp; + for (tmp=qbegin(q); !qend(q,tmp); tmp=qnext(q,tmp)){ + guint32 csrc=sdes_chunk_get_ssrc(tmp); + if (csrc==ssrc) { + remq(q,tmp); + break; + } + } + tmp=rtcp_create_simple_bye_packet(ssrc, NULL); + ortp_rtcp_send(session,tmp); +} + +void sender_info_init(sender_info_t *info, RtpSession *session){ + struct timeval tv; + guint32 tmp; + gettimeofday(&tv,NULL); + info->ntp_timestamp_msw=htonl(tv.tv_sec); + tmp=(guint32)((double)tv.tv_usec*(double)(1LL<<32)*1.0e-6); + info->ntp_timestamp_lsw=htonl(tmp); + info->rtp_timestamp=htonl(session->rtp.snd_last_ts); + info->senders_packet_count=htonl(session->rtp.stats.packet_sent); + info->senders_octet_count=htonl(session->rtp.stats.sent); +} + + + +void report_block_init(report_block_t *b, RtpSession *session){ + guint packet_loss=0; + guint8 loss_fraction=0; + RtpStream *stream=&session->rtp; + guint32 delay_snc_last_sr=0; + + /* compute the statistics */ + /*printf("hwrcv_extseq.one=%u, hwrcv_seq_at_last_SR=%u hwrcv_since_last_SR=%u\n", + stream->hwrcv_extseq.one, + stream->hwrcv_seq_at_last_SR, + stream->hwrcv_since_last_SR + );*/ + if (stream->hwrcv_seq_at_last_SR!=0){ + packet_loss=(stream->hwrcv_extseq.one - stream->hwrcv_seq_at_last_SR) - stream->hwrcv_since_last_SR; + stream->stats.cum_packet_loss+=packet_loss; + loss_fraction=(int)(256.0*(float)packet_loss/(float)stream->hwrcv_since_last_SR); + } + /* reset them */ + stream->hwrcv_since_last_SR=0; + stream->hwrcv_seq_at_last_SR=stream->hwrcv_extseq.one; + + if (stream->last_rcv_SR_time.tv_sec!=0){ + struct timeval now; + gfloat delay; + gettimeofday(&now,NULL); + delay=((now.tv_sec-stream->last_rcv_SR_time.tv_sec)*1e6 ) + (now.tv_usec-stream->last_rcv_SR_time.tv_usec); + delay=delay*65536*1e-6; + delay_snc_last_sr=(guint32) delay; + } + + b->ssrc=htonl(session->recv_ssrc); + b->fraction_lost=loss_fraction; + b->cum_num_packet_lost=hton24(stream->stats.cum_packet_loss); + b->interarrival_jitter=htonl((guint32) stream->jittctl.inter_jitter); + b->ext_high_seq_num_rec=htonl(stream->hwrcv_extseq.one); + b->lsr=htonl(stream->last_rcv_SR_ts); + b->delay_snc_last_sr=htonl(delay_snc_last_sr); +} + + + +int rtcp_sr_init(RtpSession *session, char *buf, int size){ + rtcp_sr_t *sr=(rtcp_sr_t*)buf; + if (size<sizeof(rtcp_sr_t)) return -1; + rtcp_common_header_init(&sr->ch,session,RTCP_SR,1,sizeof(rtcp_sr_t)); + sr->ssrc=htonl(session->send_ssrc); + sender_info_init(&sr->si,session); + report_block_init(&sr->rb[0],session); + return sizeof(rtcp_sr_t); +} + +int rtcp_rr_init(RtpSession *session, char *buf, int size){ + rtcp_rr_t *rr=(rtcp_rr_t*)buf; + if (size<sizeof(rtcp_rr_t)) return -1; + rtcp_common_header_init(&rr->ch,session,RTCP_RR,1,sizeof(rtcp_sr_t)); + rr->ssrc=htonl(session->send_ssrc); + report_block_init(&rr->rb[0],session); + return sizeof(rtcp_sr_t); +} + + +void __rtp_session_rtcp_process(RtpSession *session){ + mblk_t *cm=NULL; + mblk_t *sdes=NULL; + if (session->mode==RTP_SESSION_SENDONLY || session->mode==RTP_SESSION_SENDRECV){ + /* first make a SR packet */ + cm=allocb(sizeof(rtcp_sr_t),0); + cm->b_wptr+=rtcp_sr_init(session,cm->b_wptr,sizeof(rtcp_sr_t)); + /* make a SDES packet */ + sdes=rtp_session_create_rtcp_sdes_packet(session); + /* link them */ + cm->b_cont=sdes; + }else{ + /* make a RR packet */ + cm=allocb(sizeof(rtcp_rr_t),0); + cm->b_wptr+=rtcp_rr_init(session,cm->b_wptr,sizeof(rtcp_rr_t)); + /* if we are recv-only do we need to add SDES packet ? I don't think so + as we are not a source */ + } + /* send the compound packet */ + ortp_rtcp_send(session,cm); + ortp_debug("Rtcp compound message sent."); +} + +void rtp_session_rtcp_process(RtpSession *session){ + RtpStream *st=&session->rtp; + if (st->rcv_last_app_ts - st->last_rtcp_report_snt_r > st->rtcp_report_snt_interval + || st->snd_last_ts - st->last_rtcp_report_snt_s > st->rtcp_report_snt_interval){ + st->last_rtcp_report_snt_r=st->rcv_last_app_ts; + st->last_rtcp_report_snt_s=st->snd_last_ts; + __rtp_session_rtcp_process(session); + } +} diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtcp.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtcp.h new file mode 100644 index 00000000..574bcf91 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtcp.h @@ -0,0 +1,167 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#ifndef RTCP_H +#define RTCP_H + +#include <rtpport.h> + +#define RTCP_MAX_RECV_BUFSIZE 1024 + +#define RTCP_SENDER_INFO_SIZE 20 +#define RTCP_REPORT_BLOCK_SIZE 24 +#define RTCP_COMMON_HEADER_SIZE 4 +#define RTCP_SSRC_FIELD_SIZE 4 + + +/* RTCP common header */ + +typedef enum { + RTCP_SR = 200, + RTCP_RR = 201, + RTCP_SDES = 202, + RTCP_BYE = 203, + RTCP_APP = 204 +} rtcp_type_t; + + +typedef struct rtcp_common_header +{ +#ifdef WORDS_BIGENDIAN + guint16 version:2; + guint16 padbit:1; + guint16 rc:5; + guint16 packet_type:8; +#else + guint16 rc:5; + guint16 padbit:1; + guint16 version:2; + guint16 packet_type:8; +#endif + guint16 length:16; +} rtcp_common_header_t; + +#define rtcp_common_header_set_version(ch,v) (ch)->version=v +#define rtcp_common_header_set_padbit(ch,p) (ch)->padbit=p +#define rtcp_common_header_set_rc(ch,rc) (ch)->rc=rc +#define rtcp_common_header_set_packet_type(ch,pt) (ch)->packet_type=pt +#define rtcp_common_header_set_length(ch,l) (ch)->length=htons(l) + +#define rtcp_common_header_get_version(ch,v) ((ch)->version) +#define rtcp_common_header_get padbit(ch,p) ((ch)->padbit) +#define rtcp_common_header_get_rc(ch,rc) ((ch)->rc) +#define rtcp_common_header_get_packet_type(ch,pt) ((ch)->packet_type) +#define rtcp_common_header_get_length(ch,l) ntohs((ch)->length) + + +/* SR or RR packets */ + +typedef struct sender_info +{ + guint32 ntp_timestamp_msw; + guint32 ntp_timestamp_lsw; + guint32 rtp_timestamp; + guint32 senders_packet_count; + guint32 senders_octet_count; +} sender_info_t; + +typedef struct report_block +{ + guint32 ssrc; + guint32 fraction_lost:8; + guint32 cum_num_packet_lost:24; /*cumulative number of packet lost*/ + guint32 ext_high_seq_num_rec; /*extended highest sequence number received */ + guint32 interarrival_jitter; + guint32 lsr; /*last SR */ + guint32 delay_snc_last_sr; /*delay since last sr*/ +} report_block_t; + + +/* SDES packets */ + +typedef enum { + RTCP_SDES_END = 0, + RTCP_SDES_CNAME = 1, + RTCP_SDES_NAME = 2, + RTCP_SDES_EMAIL = 3, + RTCP_SDES_PHONE = 4, + RTCP_SDES_LOC = 5, + RTCP_SDES_TOOL = 6, + RTCP_SDES_NOTE = 7, + RTCP_SDES_PRIV = 8, + RTCP_SDES_MAX = 9 +} rtcp_sdes_type_t; + +typedef struct sdes_chunk +{ + guint32 csrc; +} sdes_chunk_t; + +typedef struct sdes_item +{ + guint8 item_type; + guint8 len; + gchar content[1]; +} sdes_item_t; + +#define RTCP_SDES_MAX_STRING_SIZE 255 +#define RTCP_SDES_ITEM_HEADER_SIZE 2 +#define RTCP_SDES_CHUNK_DEFAULT_SIZE 1024 +#define RTCP_SDES_CHUNK_HEADER_SIZE (sizeof(sdes_chunk_t)) + +/* RTCP bye packet */ + +typedef struct rtcp_bye_reason +{ + guint8 len; + gchar content[1]; +} rtcp_bye_reason_t; + +typedef struct rtcp_bye +{ + rtcp_common_header_t ch; + guint32 ssrc[1]; /* the bye may contain several ssrc/csrc */ +} rtcp_bye_t; +#define RTCP_BYE_HEADER_SIZE sizeof(rtcp_bye_t) +#define RTCP_BYE_REASON_MAX_STRING_SIZE 255 + +#define rtcp_bye_set_ssrc(b,pos,ssrc) (b)->ssrc[pos]=htonl(ssrc) +#define rtcp_bye_get_ssrc(b,pos) ntohl((b)->ssrc[pos]) + + +typedef struct rtcp_sr{ + rtcp_common_header_t ch; + guint32 ssrc; + sender_info_t si; + report_block_t rb[1]; +} rtcp_sr_t; + +typedef struct rtcp_rr{ + rtcp_common_header_t ch; + guint32 ssrc; + report_block_t rb[1]; +} rtcp_rr_t; + +struct _RtpSession; +void rtp_session_rtcp_process(struct _RtpSession *s); + +#define RTCP_DEFAULT_REPORT_INTERVAL 5 + +#endif diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtcpparse.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtcpparse.c new file mode 100644 index 00000000..77e38245 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtcpparse.c @@ -0,0 +1,218 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + This source code file was written by Nicola Baldo as an extension of + the oRTP library. Copyright (C) 2005 Nicola Baldo nicola@baldo.biz + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include <ortp.h> + + + +void report_block_parse(RtpSession *session, report_block_t *rb, struct timeval rcv_time_tv) +{ + rb->ssrc = ntohl(rb->ssrc); + + if ( rb->ssrc != session->send_ssrc ) + + { + ortp_debug("Received rtcp report block related to unknown ssrc (not from us)... discarded"); + return; + } + + else + + { + guint32 rcv_time_msw; + guint32 rcv_time_lsw; + guint32 rcv_time; + double rtt; + + rcv_time_msw = rcv_time_tv.tv_sec; + rcv_time_lsw = (guint32) ((double)rcv_time_tv.tv_usec*(double)(1LL<<32)*1.0e-6); + rcv_time = (rcv_time_msw<<16) | (rcv_time_lsw >> 16); + + rb->cum_num_packet_lost = ntoh24(rb->cum_num_packet_lost); + rb->ext_high_seq_num_rec = ntohl(rb->ext_high_seq_num_rec); + rb->interarrival_jitter = ntohl(rb->interarrival_jitter); + rb->lsr = ntohl(rb->lsr); + rb->delay_snc_last_sr = ntohl(rb->delay_snc_last_sr); + + + /* calculating Round Trip Time*/ + if (rb->lsr != 0) + { + rtt = (double) (rcv_time - rb->delay_snc_last_sr - rb->lsr); + rtt = rtt/65536; + //printf("RTT = %f s\n",rtt); + } + + } + +} + + +void rtcp_parse(RtpSession *session, mblk_t *mp) +{ + rtcp_common_header_t *rtcp; + int msgsize; + int rtcp_pk_size; + RtpStream *rtpstream=&session->rtp; + struct timeval rcv_time_tv; + + + gettimeofday(&rcv_time_tv,NULL); + + g_return_if_fail(mp!=NULL); + + msgsize=mp->b_wptr-mp->b_rptr; + + + + if (msgsize < RTCP_COMMON_HEADER_SIZE) + { + ortp_debug("Receiving too short rtcp packet... discarded"); + return; + } + + rtcp=(rtcp_common_header_t *)mp->b_rptr; + + + /* compound rtcp packet can be composed by more than one rtcp message */ + while (msgsize >= RTCP_COMMON_HEADER_SIZE) + + { + + if (rtcp->version!=2) + { + ortp_debug("Receiving rtcp packet with version number !=2...discarded"); + return; + } + + /* convert header data from network order to host order */ + rtcp->length = ntohs(rtcp->length); + + + switch (rtcp->packet_type) + + { + + case RTCP_SR: + + { + rtcp_sr_t *sr = (rtcp_sr_t *) rtcp; + report_block_t *rb; + int i; + + if ( ntohl(sr->ssrc) != session->recv_ssrc ) + { + ortp_debug("Receiving rtcp sr packet from unknown ssrc.. discarded"); + return; + } + + if (msgsize < RTCP_COMMON_HEADER_SIZE + RTCP_SSRC_FIELD_SIZE + RTCP_SENDER_INFO_SIZE + (RTCP_REPORT_BLOCK_SIZE*sr->ch.rc)) + { + ortp_debug("Receiving too short rtcp sr packet... discarded"); + return; + } + + /* parsing RTCP Sender Info */ + sr->si.ntp_timestamp_msw = ntohl(sr->si.ntp_timestamp_msw); + sr->si.ntp_timestamp_lsw = ntohl(sr->si.ntp_timestamp_lsw); + sr->si.rtp_timestamp = ntohl(sr->si.rtp_timestamp); + sr->si.senders_packet_count = ntohl(sr->si.senders_packet_count); + sr->si.senders_octet_count = ntohl(sr->si.senders_octet_count); + + /* saving data to fill LSR and DLSR field in next RTCP report to be transmitted */ + rtpstream->last_rcv_SR_ts = (sr->si.ntp_timestamp_msw << 16) | (sr->si.ntp_timestamp_lsw >> 16); + rtpstream->last_rcv_SR_time.tv_usec = rcv_time_tv.tv_usec; + rtpstream->last_rcv_SR_time.tv_sec = rcv_time_tv.tv_sec; + + + /* parsing all RTCP report blocks */ + for (i=0; i<sr->ch.rc; i++) + { + rb = &(sr->rb[i]); + report_block_parse(session, rb, rcv_time_tv); + } + + } + break; + + + + case RTCP_RR: + + { + rtcp_rr_t *rr = (rtcp_rr_t *) rtcp; + report_block_t *rb; + int i; + + if ( ntohl(rr->ssrc) != session->recv_ssrc ) + { + ortp_debug("Receiving rtcp rr packet from unknown ssrc.. discarded"); + return; + } + + if (msgsize < RTCP_COMMON_HEADER_SIZE + RTCP_SSRC_FIELD_SIZE + (RTCP_REPORT_BLOCK_SIZE*rr->ch.rc)) + { + ortp_debug("Receiving too short rtcp sr packet... discarded"); + return; + } + + /* parsing all RTCP report blocks */ + for (i=0; i<rr->ch.rc; i++) + { + rb = &(rr->rb[i]); + report_block_parse(session, rb, rcv_time_tv); + } + + } + break; + + + case RTCP_SDES: + /* to be implemented */ + break; + + + case RTCP_BYE: + /* to be implemented */ + break; + + + case RTCP_APP: + /* to be implemented */ + break; + + + default: + + ortp_debug("Receiving unknown rtcp packet type... discarded"); + return; + + } + + + rtcp_pk_size = ((rtcp->length)+1)*4; /* current RTCP packet size, in octets */ + msgsize -= rtcp_pk_size; /* size of unparsed portion of UDP packet, in octets */ + rtcp = (rtcp_common_header_t *) (rtcp_pk_size + (char *) rtcp); /* pointer to next RTCP packet in current UDP packet */ + + } +} diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtp.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtp.h new file mode 100644 index 00000000..625d2111 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtp.h @@ -0,0 +1,90 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#ifndef RTP_H +#define RTP_H + +#include <rtpport.h> + + + + +#define RTP_MAX_RQ_SIZE 100 /* max number of packet allowed to be enqueued */ + +#define IPMAXLEN 20 +#define UDP_MAX_SIZE 65536 +#define RTP_FIXED_HEADER_SIZE 12 +#define RTP_DEFAULT_JITTER_TIME 80 /*miliseconds*/ + + + +typedef struct rtp_header +{ +#ifdef WORDS_BIGENDIAN + guint16 version:2; + guint16 padbit:1; + guint16 extbit:1; + guint16 cc:4; + guint16 markbit:1; + guint16 paytype:7; +#else + guint16 cc:4; + guint16 extbit:1; + guint16 padbit:1; + guint16 version:2; + guint16 paytype:7; + guint16 markbit:1; +#endif + guint16 seq_number; + guint32 timestamp; + guint32 ssrc; + guint32 csrc[16]; +} rtp_header_t; + + + + +typedef struct rtp_stats +{ + guint64 packet_sent; + guint64 sent; /* bytes sent */ + guint64 recv; /* bytes received and delivered in time to the application */ + guint64 hw_recv; /* bytes of udp packets received */ + guint64 packet_recv; /* number of packets received */ + guint64 unavaillable; /* packets not availlable when they were queried */ + guint64 outoftime; /* number of packets that were received too late */ + guint64 skipped; /* number of packets skipped (that the application never queried + or that need to be skipped in order to compensate a clock slide (see adaptive jitter control)) */ + guint64 cum_packet_loss; /* cumulative number of packet lost */ + guint64 bad; /* packets that did not appear to be RTP */ + guint64 discarded; /* incoming packets discarded because the queue exceeds its max size */ +} rtp_stats_t; + +#define RTP_TIMESTAMP_IS_NEWER_THAN(ts1,ts2) \ + ((guint32)((guint32)(ts1) - (guint32)(ts2))< (guint32)(1<<31)) + +#define RTP_TIMESTAMP_IS_STRICTLY_NEWER_THAN(ts1,ts2) \ + ( ((guint32)((guint32)(ts1) - (guint32)(ts2))< (guint32)(1<<31)) && (ts1)!=(ts2) ) + +#define TIME_IS_NEWER_THAN(t1,t2) RTP_TIMESTAMP_IS_NEWER_THAN(t1,t2) + +#define TIME_IS_STRICTLY_NEWER_THAN(t1,t2) RTP_TIMESTAMP_IS_STRICTLY_NEWER_THAN(t1,t2) + +#endif diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpmod.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpmod.c new file mode 100644 index 00000000..50aeef10 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpmod.c @@ -0,0 +1,122 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + + + +#include <rtp.h> +#include "rtpmod.h" + +#define RTP_SEQ_IS_GREATER(seq1,seq2)\ + ((guint16)((guint16)(seq1) - (guint16)(seq2))< (guint16)(1<<15)) + +/* put an rtp packet in queue. It is called by rtp_parse()*/ +void rtp_putq(queue_t *q, mblk_t *mp) +{ + mblk_t *tmp; + rtp_header_t *rtp=(rtp_header_t*)mp->b_rptr,*tmprtp; + /* insert message block by increasing time stamp order : the last (at the bottom) + message of the queue is the newest*/ + ortp_debug("rtp_putq(): Enqueuing packet with ts=%i and seq=%i",rtp->timestamp,rtp->seq_number); + + if (qempty(q)) { + putq(q,mp); + return; + } + tmp=qlast(q); + /* we look at the queue from bottom to top, because enqueued packets have a better chance + to be enqueued at the bottom, since there are surely newer */ + while (!qend(q,tmp)) + { + tmprtp=(rtp_header_t*)tmp->b_rptr; + ortp_debug("rtp_putq(): Seeing packet with seq=%i",tmprtp->seq_number); + + if (rtp->seq_number == tmprtp->seq_number) + { + /* this is a duplicated packet. Don't queue it */ + ortp_debug("rtp_putq: duplicated message."); + freemsg(mp); + return; + }else if (RTP_SEQ_IS_GREATER(rtp->seq_number,tmprtp->seq_number)){ + + insq(q,tmp->b_next,mp); + return; + } + tmp=tmp->b_prev; + } + /* this packet is the oldest, it has to be + placed on top of the queue */ + insq(q,qfirst(q),mp); + +} + + + +mblk_t *rtp_getq(queue_t *q,guint32 timestamp, int *rejected) +{ + mblk_t *tmp,*ret=NULL,*old; + rtp_header_t *tmprtp; + guint32 oldest; + guint32 ts_found=0; + + *rejected=0; + ortp_debug("rtp_getq(): Timestamp %i wanted.",timestamp); + + if (qempty(q)) + { + /*ortp_debug("rtp_getq: q is empty.");*/ + return NULL; + } + /* prevent somebody to ask for a timestamp that is older than the oldest of the queue */ + oldest=((rtp_header_t*) qfirst(q)->b_rptr)->timestamp; + if (RTP_TIMESTAMP_IS_STRICTLY_NEWER_THAN(oldest,timestamp)) + { + ortp_debug("rtp_getq(): asking for too old packet ! oldest=%i",oldest); + return NULL; + } + ret=NULL; + old=NULL; + /* return the packet with ts just equal or older than the asked timestamp */ + while ((tmp=qfirst(q))!=NULL) + { + tmprtp=(rtp_header_t*)tmp->b_rptr; + ortp_debug("rtp_getq: Seeing packet with ts=%i",tmprtp->timestamp); + if ( RTP_TIMESTAMP_IS_NEWER_THAN(timestamp,tmprtp->timestamp) ) + { + if (ret!=NULL && tmprtp->timestamp==ts_found) { + /* we've found two packets with same timestamp. return the first one */ + break; + } + if (old!=NULL) { + ortp_debug("rtp_getq: discarding too old packet with ts=%i",ts_found); + (*rejected)++; + freemsg(old); + } + ret=getq(q); /* dequeue the packet, since it has an interesting timestamp*/ + ts_found=tmprtp->timestamp; + ortp_debug("rtp_getq: Found packet with ts=%i",tmprtp->timestamp); + old=ret; + } + else + { + break; + } + } + return ret; +} diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpmod.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpmod.h new file mode 100644 index 00000000..e675394d --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpmod.h @@ -0,0 +1,31 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#ifndef RTPMOD_H +#define RTPMOD_H + +#include <rtpport.h> +#include <str_utils.h> +#include <rtp.h> + +void rtp_putq(queue_t *q, mblk_t *mp); +mblk_t *rtp_getq(queue_t *q,guint32 timestamp, int *rejected); + +#endif diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpparse.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpparse.c new file mode 100644 index 00000000..50ecba97 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpparse.c @@ -0,0 +1,159 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include <ortp.h> +#include "rtpmod.h" +#include "jitterctl.h" + + +void split_and_queue(queue_t *q, int maxrqsz, mblk_t *mp, rtp_header_t *rtp, int *discarded) +{ + mblk_t *mdata,*tmp; + int header_size; + *discarded=0; + header_size=RTP_FIXED_HEADER_SIZE+ (4*rtp->cc); + if ((mp->b_wptr - mp->b_rptr)==header_size){ + ortp_debug("Rtp packet contains no data."); + (*discarded)++; + freemsg(mp); + return; + } + /* creates a new mblk_t to be linked with the rtp header*/ + mdata=dupb(mp); + + mp->b_wptr=mp->b_rptr+header_size; + mdata->b_rptr+=header_size; + /* link proto with data */ + mp->b_cont=mdata; + /* and then add the packet to the queue */ + + rtp_putq(q,mp); + /* make some checks: q size must not exceed RtpStream::max_rq_size */ + while (q->q_mcount > maxrqsz) + { + /* remove the oldest mblk_t */ + tmp=getq(q); + if (mp!=NULL) + { + ortp_debug("rtp_putq: Queue is full. Discarding message with ts=%i",((rtp_header_t*)mp->b_rptr)->timestamp); + freemsg(tmp); + (*discarded)++; + } + } +} + +void rtp_parse(RtpSession *session, mblk_t *mp, guint32 local_str_ts) +{ + gint i; + rtp_header_t *rtp; + int msgsize; + RtpStream *rtpstream=&session->rtp; + rtp_stats_t *stats=&rtpstream->stats; + + g_return_if_fail(mp!=NULL); + + msgsize=msgdsize(mp); + ortp_global_stats.hw_recv+=msgsize; + stats->hw_recv+=msgsize; + ortp_global_stats.packet_recv++; + stats->packet_recv++; + + session->rtp.hwrcv_since_last_SR++; + + rtp=(rtp_header_t*)mp->b_rptr; + if (rtp->version!=2) + { + ortp_debug("Receiving rtp packet with version number !=2...discarded"); + stats->bad++; + ortp_global_stats.bad++; + freemsg(mp); + return; + } + + /* convert all header data from network order to host order */ + rtp->seq_number=ntohs(rtp->seq_number); + rtp->timestamp=ntohl(rtp->timestamp); + rtp->ssrc=ntohl(rtp->ssrc); + /* convert csrc if necessary */ + if (rtp->cc*sizeof(guint32) > (msgsize-RTP_FIXED_HEADER_SIZE)){ + ortp_debug("Receiving too short rtp packet."); + stats->bad++; + ortp_global_stats.bad++; + freemsg(mp); + return; + } + for (i=0;i<rtp->cc;i++) + rtp->csrc[i]=ntohl(rtp->csrc[i]); + if (session->recv_ssrc!=0) + { + /*the ssrc is set, so we must check it */ + if (session->recv_ssrc!=rtp->ssrc){ + /*ortp_debug("rtp_parse: bad ssrc - %i",rtp->ssrc);*/ + session->recv_ssrc=rtp->ssrc; + rtp_signal_table_emit(&session->on_ssrc_changed); + } + }else session->recv_ssrc=rtp->ssrc; + + /* update some statistics */ + if (rtp->seq_number>rtpstream->hwrcv_extseq.split.lo){ + rtpstream->hwrcv_extseq.split.lo=rtp->seq_number; + }else if (rtp->seq_number<200 && rtpstream->hwrcv_extseq.split.lo>((1<<16) - 200)){ + /* this is a check for sequence number looping */ + rtpstream->hwrcv_extseq.split.lo=rtp->seq_number; + rtpstream->hwrcv_extseq.split.hi++; + } + + + /* check for possible telephone events */ + if (rtp->paytype==session->telephone_events_pt){ + split_and_queue(&session->rtp.tev_rq,session->rtp.max_rq_size,mp,rtp,&i); + stats->discarded+=i; + ortp_global_stats.discarded+=i; + return; + } + + if (!(session->flags & RTP_SESSION_RECV_SYNC)){ + gint32 slide=0; + gint32 safe_delay=0; + jitter_control_new_packet(&session->rtp.jittctl,rtp->timestamp,local_str_ts,&slide,&safe_delay); + + session->rtp.rcv_diff_ts=session->rtp.hwrcv_diff_ts + slide - safe_delay; + ortp_debug(" rcv_diff_ts=%i", session->rtp.rcv_diff_ts); + + /* detect timestamp important jumps in the future, to workaround stupid rtp senders */ + if (RTP_TIMESTAMP_IS_NEWER_THAN(rtp->timestamp,session->rtp.rcv_last_ts+session->rtp.ts_jump)){ + ortp_debug("rtp_parse: timestamp jump ?"); + rtp_signal_table_emit2(&session->on_timestamp_jump,&rtp->timestamp); + } + else if (RTP_TIMESTAMP_IS_NEWER_THAN(session->rtp.rcv_last_ts,rtp->timestamp)){ + /* avoid very old packet to enqueued, because the user is no more supposed to get them */ + ortp_debug("rtp_parse: silently discarding very old packet (ts=%i)",rtp->timestamp); + freemsg(mp); + stats->outoftime++; + ortp_global_stats.outoftime++; + return; + } + + } + + split_and_queue(&session->rtp.rq,session->rtp.max_rq_size,mp,rtp,&i); + stats->discarded+=i; + ortp_global_stats.discarded+=i; +} diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpport.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpport.h new file mode 100644 index 00000000..65e48530 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpport.h @@ -0,0 +1,308 @@ +/* + The oRTP LinPhone RTP library intends to provide basics for a RTP stack. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +/* this file is responsible of the portability of the stack */ + +#ifndef RTPPORT_H +#define RTPPORT_H + +#ifdef UGLIB_H +#define HAVE_GLIB +#endif + +#ifndef _WIN32 /* do not include ortp-config.h when we are on win32 */ +# ifdef _ORTP_SOURCE +# include <ortp-config.h> +# else +# include <ortp-config.h> +# endif +#else + #include "ortp-config-win32.h" +#endif + +#define INT_TO_POINTER(truc) ((gpointer)(long)(truc)) +#define POINTER_TO_INT(truc) ((int)(long)(truc)) + +/* defines things that should be defined when we have not glib */ +#ifndef HAVE_GLIB + +#include <errno.h> +#include <sys/types.h> +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif + +/* integer types */ +typedef uint64_t guint64; +typedef uint16_t guint16; +typedef uint32_t guint32; +typedef signed short gint16; +typedef int32_t gint32; +typedef unsigned int guint; +typedef int gint; +typedef char gchar; +typedef unsigned char guchar; +typedef unsigned char guint8; +typedef void* gpointer; +typedef int gboolean; +typedef double gdouble; +typedef float gfloat; + +#define TRUE 1 +#define FALSE 0 + + +/*misc*/ +#define g_return_if_fail(expr) if (!(expr)) {printf("%s:%i- assertion" #expr "failed\n",__FILE__,__LINE__); return;} +#define g_return_val_if_fail(expr,ret) if (!(expr)) {printf("%s:%i- assertion" #expr "failed\n",__FILE__,__LINE__); return (ret);} + +#include <unistd.h> +#include <stdio.h> +#include <stdarg.h> + +typedef enum { + /* GLib log levels */ + G_LOG_LEVEL_ERROR = 1 << 2, /* always fatal */ + G_LOG_LEVEL_CRITICAL = 1 << 3, + G_LOG_LEVEL_WARNING = 1 << 4, + G_LOG_LEVEL_MESSAGE = 1 << 5, + G_LOG_LEVEL_MASK = ~0 + +} GLogLevelFlags; + +#ifndef G_LOG_DOMAIN +#define G_LOG_DOMAIN ((const gchar*)"") +#endif +#ifdef __cplusplus +extern "C" { +#endif + +void g_log(const gchar *log_domain,GLogLevelFlags log_level,const gchar *format,...); +void g_logv(const gchar *log_domain,GLogLevelFlags log_level,const gchar *format,va_list args); +typedef void (*GLogFunc) (const gchar *log_domain, + GLogLevelFlags log_level, + const gchar *message, + gpointer user_data); +static inline void g_warning(const gchar *fmt,...) +{ + va_list args; + va_start (args, fmt); + g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, fmt, args); + va_end (args); +} +static inline void g_error(const gchar *fmt,...) +{ + va_list args; + va_start (args, fmt); + g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR, fmt, args); + va_end (args); +} +static inline void g_message(const gchar *fmt,...) +{ + va_list args; + va_start (args, fmt); + g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, fmt, args); + va_end (args); +} +/* in order to simplify, domain is ignored when using the folowing function, ie all logs will go through your handler +whatever the domain is */ +void g_log_set_handler(const gchar *domain, GLogLevelFlags levels, GLogFunc func, gpointer ud); + +#ifdef __cplusplus +} +#endif + +#endif /* HAVE_GLIB */ + + +#if defined(TIME_WITH_SYS_TIME) +#include <time.h> +#include <sys/time.h> +#elif defined(HAVE_SYS_TIME_H) +#include <sys/time.h> +#endif + + +#ifdef HAVE_GLIB + +#ifndef UGLIB_H +#include <glib.h> +#endif +#include <string.h> + + +#else /* not HAVE_GLIB */ +/* things that in glib, but should only be defined when we are not in the HPUX kernel. */ +#include <stdlib.h> +#include <pthread.h> +#include <sched.h> +#include <string.h> + +#ifdef ENABLE_MEMCHECK +extern gint ortp_allocations; +#endif + +/* memory allocation functions */ +static inline void * g_malloc(int sz) +{ + void *p=malloc(sz); + if (p==NULL) { + printf("g_malloc: Failed to allocate %i bytes: %s.\n",sz,strerror(errno)); + abort(); + } +#ifdef ENABLE_MEMCHECK + ortp_allocations++; +#endif + return p; +} + +static inline void * g_malloc0(int sz) +{ + void *p=malloc(sz); + if (p==NULL) { + printf("g_malloc: Failed to allocate %i bytes: %s.\n",sz,strerror(errno)); + abort(); + } + memset(p,0,sz); +#ifdef ENABLE_MEMCHECK + ortp_allocations++; +#endif + return p; +} + +#define g_new(type,count) (type *)g_malloc(sizeof(type)*(count)) +#define g_new0(type, count) (type *)g_malloc0(sizeof(type)*(count)) +#define g_realloc(p,sz) realloc((p),(sz)) +static inline void g_free(void *p) +{ +#ifdef ENABLE_MEMCHECK + ortp_allocations--; +#endif + free(p); +} + +#define g_strdup(machin) strdup(machin) + +typedef pthread_mutex_t GMutex; +static inline GMutex * g_mutex_new() +{ + pthread_mutex_t *mutex=g_new(pthread_mutex_t,1); + pthread_mutex_init(mutex,NULL); + return mutex; +} +typedef enum +{ + G_THREAD_PRIORITY_LOW, + G_THREAD_PRIORITY_NORMAL, + G_THREAD_PRIORITY_HIGH, + G_THREAD_PRIORITY_URGENT +} GThreadPriority; +typedef pthread_t GThread; +typedef gpointer (*GThreadFunc)(gpointer data); +static inline GThread *g_thread_create(GThreadFunc func, gpointer data, gboolean joinable, void **error){ + GThread *thread=g_new(GThread,1); + pthread_create(thread,NULL,func,data); + return thread; +} + +static inline void g_thread_join(GThread *thread){ + pthread_join(*thread,NULL); + g_free(thread); +} + +static inline void g_thread_set_priority(GThread *thread,GThreadPriority prio){ + if (prio>G_THREAD_PRIORITY_NORMAL){ + /* this is unsupported on HPUX */ + /* + struct sched_param param; + param.sched_priority=1; + sched_setscheduler(*thread,SCHED_RR,¶m); + */ + } +} + +#define g_mutex_lock(mutex) pthread_mutex_lock((mutex)) +#define g_mutex_unlock(mutex) pthread_mutex_unlock((mutex)) +#define g_mutex_free(mutex) pthread_mutex_destroy((mutex));g_free((mutex)) + +typedef pthread_cond_t GCond; +static inline GCond * g_cond_new() +{ + pthread_cond_t *cond=g_new(pthread_cond_t,1); + pthread_cond_init(cond,NULL); + return cond; +} +#define g_cond_wait(cond,mutex) pthread_cond_wait((cond),(mutex)) +#define g_cond_signal(cond) pthread_cond_signal((cond)) +#define g_cond_broadcast(cond) pthread_cond_broadcast((cond)) +#define g_cond_free(cond) pthread_cond_destroy((cond)); g_free((cond)) + +#define g_thread_init(vtable) +#define g_thread_supported() (1) + +#endif /* HAVE_GLIB */ + + +#ifndef RTP_DEBUG +#define ortp_debug(...) +#else +#define ortp_debug g_message +#endif + +#ifdef _WIN32 +extern char *getSocketError(); +#define getSocketErrorCode() WSAGetLastError () +#else +#define getSocketError() strerror(errno) +#define getSocketErrorCode() (errno) +#endif + +#ifdef UGLIB_H +#undef HAVE_GLIB +#endif + +#undef MIN +#define MIN(a,b) (((a)>(b)) ? (b) : (a)) +#undef MAX +#define MAX(a,b) (((a)>(b)) ? (a) : (b)) + +typedef struct _dwsplit_t{ +#ifdef WORDS_BIGENDIAN + guint16 hi; + guint16 lo; +#else + guint16 lo; + guint16 hi; +#endif +} dwsplit_t; + +typedef union{ + dwsplit_t split; + guint32 one; +} poly32_t; + +#ifdef WORDS_BIGENDIAN +#define hton24(x) (x) +#else +#define hton24(x) ((( (x) & 0x00ff0000) >>16) | (( (x) & 0x000000ff) <<16) | ( (x) & 0x0000ff00) ) +#endif +#define ntoh24(x) hton24(x) + +#endif /*RTPPORT_H*/ diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpsession.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpsession.c new file mode 100644 index 00000000..de6b2e7d --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpsession.c @@ -0,0 +1,1954 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include <ortp.h> +#include <telephonyevents.h> +#include "rtpmod.h" +#include "jitterctl.h" +#include "scheduler.h" +#include "port_fct.h" +#include "utils.h" + +#include <fcntl.h> +#include <errno.h> +#include <stdlib.h> +#include <stdio.h> + +#ifndef _WIN32 +# include <sys/types.h> +# include <sys/socket.h> +# include <netinet/in.h> +# include <arpa/inet.h> +# ifdef INET6 +# include <netdb.h> +# endif +#else +# include <winsock2.h> +# include "errno-win32.h" +#endif + + +#if defined(HAVE_POLL_H) +#include <poll.h> +#elif defined(HAVE_SYS_POLL_H) +#include <sys/poll.h> +#endif +#ifdef HAVE_SYS_UIO_H +#include <sys/uio.h> +#define USE_SENDMSG 1 +#endif + + + +void wait_point_init(WaitPoint *wp){ + wp->lock=g_mutex_new(); + wp->cond=g_cond_new(); + wp->time=0; + wp->wakeup=FALSE; +} +void wait_point_uninit(WaitPoint *wp){ + g_cond_free(wp->cond); + g_mutex_free(wp->lock); +} + +#define wait_point_lock(wp) g_mutex_lock((wp)->lock) +#define wait_point_unlock(wp) g_mutex_unlock((wp)->lock) + +void wait_point_wakeup_at(WaitPoint *wp, guint32 t, gboolean dosleep){ + wp->time=t; + wp->wakeup=TRUE; + if (dosleep) g_cond_wait(wp->cond,wp->lock); +} + + +gboolean wait_point_check(WaitPoint *wp, guint32 t){ + gboolean ok=FALSE; + + if (wp->wakeup){ + if (TIME_IS_NEWER_THAN(t,wp->time)){ + wp->wakeup=FALSE; + ok=TRUE; + + } + } + return ok; +} +#define wait_point_wakeup(wp) g_cond_signal((wp)->cond); + +extern void rtp_parse(RtpSession *session, mblk_t *mp, guint32 local_str_ts); + + +static guint32 guint32_random(){ + return random(); +} + +void +rtp_session_init (RtpSession * session, gint mode) +{ + memset (session, 0, sizeof (RtpSession)); + session->lock = g_mutex_new (); + session->rtp.max_rq_size = RTP_MAX_RQ_SIZE; + session->mode = mode; + if ((mode == RTP_SESSION_RECVONLY) || (mode == RTP_SESSION_SENDRECV)) + { + rtp_session_set_flag (session, RTP_SESSION_RECV_SYNC); + rtp_session_set_flag (session, RTP_SESSION_RECV_NOT_STARTED); + + } + if ((mode == RTP_SESSION_SENDONLY) || (mode == RTP_SESSION_SENDRECV)) + { + rtp_session_set_flag (session, RTP_SESSION_SEND_NOT_STARTED); + rtp_session_set_flag (session, RTP_SESSION_SEND_SYNC); + session->send_ssrc=guint32_random(); + /* set default source description */ + rtp_session_set_source_description(session,"unknown@unknown",NULL,NULL, + NULL,NULL,"oRTP-" ORTP_VERSION,"This is free sofware (LGPL) !"); + } + session->telephone_events_pt=-1; /* not defined a priori */ + rtp_session_set_profile (session, &av_profile); /*the default profile to work with */ + session->payload_type=0;/* default to something */ + qinit(&session->rtp.rq); + qinit(&session->rtp.tev_rq); + qinit(&session->contributing_sources); + /* init signal tables */ + rtp_signal_table_init (&session->on_ssrc_changed, session,"ssrc_changed"); + rtp_signal_table_init (&session->on_payload_type_changed, session,"payload_type_changed"); + rtp_signal_table_init (&session->on_telephone_event, session,"telephone-event"); + rtp_signal_table_init (&session->on_telephone_event_packet, session,"telephone-event_packet"); + rtp_signal_table_init (&session->on_timestamp_jump,session,"timestamp_jump"); + rtp_signal_table_init (&session->on_network_error,session,"network_error"); + wait_point_init(&session->send_wp); + wait_point_init(&session->recv_wp); + rtp_session_set_jitter_compensation(session,RTP_DEFAULT_JITTER_TIME); + rtp_session_enable_adaptive_jitter_compensation(session,FALSE); + rtp_session_set_time_jump_limit(session,5000); + session->max_buf_size = UDP_MAX_SIZE; +} + +/** + *rtp_session_new: + *@mode: One of the #RtpSessionMode flags. + * + * Creates a new rtp session. + * If the session is able to send data (RTP_SESSION_SENDONLY or RTP_SESSION_SENDRECV), then a + * random SSRC number is choosed for the outgoing stream. + * + *Returns: the newly created rtp session. +**/ + +RtpSession * +rtp_session_new (gint mode) +{ + RtpSession *session; + session = g_malloc (sizeof (RtpSession)); + rtp_session_init (session, mode); + return session; +} + +/** + *rtp_session_set_scheduling_mode: + *@session: a rtp session. + *@yesno: a boolean to indicate the scheduling mode. + * + * Sets the scheduling mode of the rtp session. If @yesno is TRUE, the rtp session is in + * the scheduled mode, that means that you can use session_set_select() to block until it's time + * to receive or send on this session according to the timestamp passed to the respective functions. + * You can also use blocking mode (see rtp_session_set_blocking_mode() ), to simply block within + * the receive and send functions. + * If @yesno is FALSE, the ortp scheduler will not manage those sessions, meaning that blocking mode + * and the use of session_set_select() for this session are disabled. + * +**/ + +void +rtp_session_set_scheduling_mode (RtpSession * session, gint yesno) +{ + if (yesno) + { + RtpScheduler *sched; + sched = ortp_get_scheduler (); + if (sched != NULL) + { + rtp_session_set_flag (session, RTP_SESSION_SCHEDULED); + session->sched = sched; + rtp_scheduler_add_session (sched, session); + } + else + g_warning + ("rtp_session_set_scheduling_mode: Cannot use scheduled mode because the " + "scheduler is not started. Use ortp_scheduler_init() before."); + } + else + rtp_session_unset_flag (session, RTP_SESSION_SCHEDULED); +} + + +/** + *rtp_session_set_blocking_mode: + *@session: a rtp session + *@yesno: a boolean + * + * Using this function implies that you previously enabled scheduled mode on the session + * (see rtp_session_set_scheduling_mode() ). + * rtp_session_set_blocking_mode() defines the behaviour of the rtp_session_recv_with_ts() and + * rtp_session_send_with_ts() functions. If @yesno is TRUE, rtp_session_recv_with_ts() + * will block until it is time for the packet to be received, according to the timestamp + * passed to the function. After this time, the function returns. + * For rtp_session_send_with_ts(), it will block until it is time for the packet to be sent. + * If @yesno is FALSE, then the two functions will return immediately. + * +**/ +void +rtp_session_set_blocking_mode (RtpSession * session, gint yesno) +{ + if (yesno) + rtp_session_set_flag (session, RTP_SESSION_BLOCKING_MODE); + else + rtp_session_unset_flag (session, RTP_SESSION_BLOCKING_MODE); +} + +/** + *rtp_session_set_profile: + *@session: a rtp session + *@profile: a rtp profile + * + * Set the RTP profile to be used for the session. By default, all session are created by + * rtp_session_new() are initialized with the AV profile, as defined in RFC 1890. The application + * can set any other profile instead using that function. + * + * +**/ + +void +rtp_session_set_profile (RtpSession * session, RtpProfile * profile) +{ + session->profile = profile; + rtp_session_telephone_events_supported(session); +} + + +/** + *rtp_session_signal_connect: + *@session: a rtp session + *@signal: the name of a signal + *@cb: a #RtpCallback + *@user_data: a pointer to any data to be passed when invoking the callback. + * + * This function provides the way for an application to be informed of various events that + * may occur during a rtp session. @signal is a string identifying the event, and @cb is + * a user supplied function in charge of processing it. The application can register + * several callbacks for the same signal, in the limit of #RTP_CALLBACK_TABLE_MAX_ENTRIES. + * Here are name and meaning of supported signals types: + * + * "ssrc_changed" : the SSRC of the incoming stream has changed. + * + * "payload_type_changed" : the payload type of the incoming stream has changed. + * + * "telephone-event_packet" : a telephone-event rtp packet (RFC2833) is received. + * + * "telephone-event" : a telephone event has occured. This is a high-level shortcut for "telephone-event_packet". + * + * "network_error" : a network error happened on a socket. Arguments of the callback functions are + * a const char * explaining the error, an int errno error code and the user_data as usual. + * + * "timestamp_jump" : we have received a packet with timestamp in far future compared to last timestamp received. + * The farness of far future is set by rtp_sesssion_set_time_jump_limit() + * + * Returns: 0 on success, -EOPNOTSUPP if the signal does not exists, -1 if no more callbacks + * can be assigned to the signal type. +**/ +int +rtp_session_signal_connect (RtpSession * session, const char *signal, + RtpCallback cb, gpointer user_data) +{ + OList *elem; + for (elem=session->signal_tables;elem!=NULL;elem=o_list_next(elem)){ + RtpSignalTable *s=(RtpSignalTable*) elem->data; + if (strcmp(signal,s->signal_name)==0){ + return rtp_signal_table_add(s,cb,user_data); + } + } + g_warning ("rtp_session_signal_connect: inexistant signal %s",signal); + return -1; +} + + +/** + *rtp_session_signal_disconnect_by_callback: + *@session: a rtp session + *@signal: a signal name + *@cb: a callback function. + * + * Removes callback function @cb to the list of callbacks for signal @signal. + * + *Returns: 0 on success, -ENOENT if the callbacks was not found. +**/ + +int +rtp_session_signal_disconnect_by_callback (RtpSession * session, const gchar *signal, + RtpCallback cb) +{ + OList *elem; + for (elem=session->signal_tables;elem!=NULL;elem=o_list_next(elem)){ + RtpSignalTable *s=(RtpSignalTable*) elem->data; + if (strcmp(signal,s->signal_name)==0){ + return rtp_signal_table_remove_by_callback(s,cb); + } + } + g_warning ("rtp_session_signal_connect: inexistant signal %s",signal); + return -1; +} + +/** + *rtp_session_set_local_addr: + *@session: a rtp session freshly created. + *@addr: a local IP address in the xxx.xxx.xxx.xxx form. + *@port: a local port. + * + * Specify the local addr to be use to listen for rtp packets or to send rtp packet from. + * In case where the rtp session is send-only, then it is not required to call this function: + * when calling rtp_session_set_remote_addr(), if no local address has been set, then the + * default INADRR_ANY (0.0.0.0) IP address with a random port will be used. Calling + * rtp_sesession_set_local_addr() is mandatory when the session is recv-only or duplex. + * + * Returns: 0 on success. +**/ + +gint +rtp_session_set_local_addr (RtpSession * session, const gchar * addr, gint port) +{ + gint err; + gint optval = 1; +#ifdef INET6 + char num[8]; + struct addrinfo hints, *res0, *res; +#endif + + if (session->rtp.socket>0) { + /* dont try to rebind, close socket before */ + close_socket(session->rtp.socket); + close_socket(session->rtcp.socket); + session->rtp.socket=0; + session->rtcp.socket=0; + } + +#ifdef INET6 + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + snprintf(num, sizeof(num), "%d",port); + err = getaddrinfo(addr,num, &hints, &res0); + if (err!=0) { + g_warning ("Error: %s", gai_strerror(err)); + return err; + } + + for (res = res0; res; res = res->ai_next) { + session->rtp.socket = socket(res->ai_family, res->ai_socktype, 0); + if (session->rtp.socket < 0) + continue; + + err = setsockopt (session->rtp.socket, SOL_SOCKET, SO_REUSEADDR, + (void*)&optval, sizeof (optval)); + if (err < 0) + { + g_warning ("Fail to set rtp address reusable: %s.", getSocketError()); + } + + session->rtp.socktype=res->ai_family; + memcpy(&session->rtp.loc_addr, res->ai_addr, res->ai_addrlen); + err = bind (session->rtp.socket, res->ai_addr, res->ai_addrlen); + if (err != 0) + { + g_warning ("Fail to bind rtp socket to port %i: %s.", port, getSocketError()); + close_socket (session->rtp.socket); + continue; + } +#ifndef __hpux + switch (res->ai_family) + { + case AF_INET: + if (IN_MULTICAST(ntohl(((struct sockaddr_in *) res->ai_addr)->sin_addr.s_addr))) + { + struct ip_mreq mreq; + mreq.imr_multiaddr.s_addr = ((struct sockaddr_in *) res->ai_addr)->sin_addr.s_addr; + mreq.imr_interface.s_addr = INADDR_ANY; + err = setsockopt(session->rtp.socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); + if (err < 0) + { + g_warning ("Fail to join address group: %s.", getSocketError()); + close_socket (session->rtp.socket); + continue; + } + } + break; + case AF_INET6: + if (IN6_IS_ADDR_MULTICAST(&(((struct sockaddr_in6 *) res->ai_addr)->sin6_addr))) + { + struct ipv6_mreq mreq; + mreq.ipv6mr_multiaddr = ((struct sockaddr_in6 *) res->ai_addr)->sin6_addr; + mreq.ipv6mr_interface = 0; + err = setsockopt(session->rtp.socket, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)); + if (err < 0) + { + g_warning ("Fail to join address group: %s.", getSocketError()); + close_socket (session->rtp.socket); + continue; + } + } + break; + } +#endif + break; + } + freeaddrinfo(res0); + if (session->rtp.socket < 0){ + if (session->mode==RTP_SESSION_RECVONLY) g_warning("Could not create rtp socket with address %s: %s",addr,getSocketError()); + return -1; + } + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + snprintf(num, sizeof(num), "%d", (port + 1)); + + err = getaddrinfo(addr, num, &hints, &res0); + if (err!=0) { + g_warning ("Error: %s", gai_strerror(err)); + return err; + } + + for (res = res0; res; res = res->ai_next) { + session->rtcp.socket = socket(res->ai_family, res->ai_socktype, 0); + + if (session->rtcp.socket < 0) + continue; + + err = setsockopt (session->rtcp.socket, SOL_SOCKET, SO_REUSEADDR, + (void*)&optval, sizeof (optval)); + if (err < 0) + { + g_warning ("Fail to set rtcp address reusable: %s.",getSocketError()); + } + session->rtcp.socktype=res->ai_family; + memcpy( &session->rtcp.loc_addr, res->ai_addr, res->ai_addrlen); + err = bind (session->rtcp.socket, res->ai_addr, res->ai_addrlen); + if (err != 0) + { + g_warning ("Fail to bind rtp socket to port %i: %s.", port, getSocketError()); + close_socket (session->rtp.socket); + close_socket (session->rtcp.socket); + continue; + } +#ifndef __hpux + switch (res->ai_family) + { + case AF_INET: + if (IN_MULTICAST(ntohl(((struct sockaddr_in *) res->ai_addr)->sin_addr.s_addr))) + { + struct ip_mreq mreq; + mreq.imr_multiaddr.s_addr = ((struct sockaddr_in *) res->ai_addr)->sin_addr.s_addr; + mreq.imr_interface.s_addr = INADDR_ANY; + err = setsockopt(session->rtcp.socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); + if (err < 0) + { + g_warning ("Fail to join address group: %s.", getSocketError()); + close_socket (session->rtp.socket); + close_socket (session->rtcp.socket); + continue; + } + } + break; + case AF_INET6: + if (IN6_IS_ADDR_MULTICAST(&(((struct sockaddr_in6 *) res->ai_addr)->sin6_addr))) + { + struct ipv6_mreq mreq; + mreq.ipv6mr_multiaddr = ((struct sockaddr_in6 *) res->ai_addr)->sin6_addr; + mreq.ipv6mr_interface = 0; + err = setsockopt(session->rtcp.socket, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)); + if (err < 0) + { + g_warning ("Fail to join address group: %s.", getSocketError()); + close_socket (session->rtp.socket); + close_socket (session->rtcp.socket); + continue; + } + } + break; + } +#endif + + break; + } + freeaddrinfo(res0); + if (session->rtp.socket < 0){ + g_warning("Could not create rtcp socket with address %s: %s",addr,getSocketError()); + return -1; + } +#else + session->rtp.loc_addr.sin_family = AF_INET; + + err = inet_aton (addr, &session->rtp.loc_addr.sin_addr); + + if (err < 0) + { + g_warning ("Error in socket address:%s.", getSocketError()); + return err; + } + session->rtp.loc_addr.sin_port = htons (port); + + session->rtp.socket = socket (PF_INET, SOCK_DGRAM, 0); + g_return_val_if_fail (session->rtp.socket > 0, -1); + + err = setsockopt (session->rtp.socket, SOL_SOCKET, SO_REUSEADDR, + (void*)&optval, sizeof (optval)); + if (err < 0) + { + g_warning ("Fail to set rtp address reusable: %s.",getSocketError()); + } + + err = bind (session->rtp.socket, + (struct sockaddr *) &session->rtp.loc_addr, + sizeof (struct sockaddr_in)); + + if (err != 0) + { + g_warning ("Fail to bind rtp socket to port %i: %s.", port, getSocketError()); + close_socket (session->rtp.socket); + return -1; + } + memcpy (&session->rtcp.loc_addr, &session->rtp.loc_addr, + sizeof (struct sockaddr_in)); + session->rtcp.loc_addr.sin_port = htons (port + 1); + session->rtcp.socket = socket (PF_INET, SOCK_DGRAM, 0); + g_return_val_if_fail (session->rtcp.socket > 0, -1); + + err = setsockopt (session->rtcp.socket, SOL_SOCKET, SO_REUSEADDR, + (void*)&optval, sizeof (optval)); + if (err < 0) + { + g_warning ("Fail to set rtcp address reusable: %s.",getSocketError()); + } + + err = bind (session->rtcp.socket, + (struct sockaddr *) &session->rtcp.loc_addr, + sizeof (struct sockaddr_in)); + if (err != 0) + { + g_warning ("Fail to bind rtcp socket to port %i: %s.", port + 1, getSocketError()); + close_socket (session->rtp.socket); + close_socket (session->rtcp.socket); + return -1; + } +#ifndef __hpux + if (IN_MULTICAST(ntohl(session->rtp.loc_addr.sin_addr.s_addr))) + { + struct ip_mreq mreq; + mreq.imr_multiaddr.s_addr = session->rtp.loc_addr.sin_addr.s_addr; + mreq.imr_interface.s_addr = INADDR_ANY; + err = setsockopt(session->rtp.socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); + if (err == 0) + err = setsockopt(session->rtcp.socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); + if (err < 0) + { + g_warning ("Fail to join address group: %s.", getSocketError()); + close_socket (session->rtp.socket); + close_socket (session->rtcp.socket); + return -1; + } + } +#endif +#endif + /* set RTP socket options */ + set_non_blocking_socket (session->rtp.socket); + /* set RTCP socket options */ + set_non_blocking_socket (session->rtcp.socket); + return 0; +} + + +/** + *rtp_session_set_remote_addr: + *@session: a rtp session freshly created. + *@addr: a local IP address in the xxx.xxx.xxx.xxx form. + *@port: a local port. + * + * Sets the remote address of the rtp session, ie the destination address where rtp packet + * are sent. If the session is recv-only or duplex, it also sets the origin of incoming RTP + * packets. Rtp packets that don't come from addr:port are discarded. + * + * Returns: 0 on success. +**/ + +gint +rtp_session_set_remote_addr (RtpSession * session, const gchar * addr, gint port) +{ + gint err; +#ifdef INET6 + struct addrinfo hints, *res0, *res; + char num[8]; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + snprintf(num, sizeof(num), "%d", port); + err = getaddrinfo(addr, num, &hints, &res0); + if (err) { + g_warning ("Error in socket address: %s", gai_strerror(err)); + return err; + } +#endif + + if (session->rtp.socket == 0) + { + int retry; + /* the session has not its socket bound, do it */ + g_message ("Setting random local addresses."); + for (retry=0;retry<10;retry++) + { + int localport; + do + { + localport = (rand () + 5000) & 0xfffe; + } + while ((localport < 5000) || (localport > 0xffff)); +#ifdef INET6 + /* bind to an address type that matches the destination address */ + if (res0->ai_addr->sa_family==AF_INET6) + err = rtp_session_set_local_addr (session, "::", localport); + else err=rtp_session_set_local_addr (session, "0.0.0.0", localport); +#else + err = rtp_session_set_local_addr (session, "0.0.0.0", localport); +#endif + + if (err == 0) + break; + } + if (retry == 10){ + g_warning("rtp_session_set_remote_addr: Could not find a random local address for socket !"); + return -1; + } + } + + +#ifdef INET6 + err=1; + for (res = res0; res; res = res->ai_next) { + /* set a destination address that has the same type as the local address */ + if (res->ai_family==session->rtp.socktype ) { + memcpy( &session->rtp.rem_addr, res->ai_addr, res->ai_addrlen); + session->rtp.addrlen=res->ai_addrlen; + err=0; + break; + } + } + freeaddrinfo(res0); + if (err) { + g_warning("Could not set destination for RTP socket to %s:%i.",addr,port); + return -1; + } + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + snprintf(num, sizeof(num), "%d", (port + 1)); + err = getaddrinfo(addr, num, &hints, &res0); + if (err) { + g_warning ("Error: %s", gai_strerror(err)); + return err; + } + err=1; + for (res = res0; res; res = res->ai_next) { + /* set a destination address that has the same type as the local address */ + if (res->ai_family==session->rtp.socktype ) { + err=0; + memcpy( &session->rtcp.rem_addr, res->ai_addr, res->ai_addrlen); + session->rtcp.addrlen=res->ai_addrlen; + break; + } + } + freeaddrinfo(res0); + if (err) { + g_warning("Could not set destination for RCTP socket to %s:%i.",addr,port+1); + return -1; + } +#else + session->rtp.addrlen=sizeof(session->rtp.rem_addr); + session->rtp.rem_addr.sin_family = AF_INET; + + err = inet_aton (addr, &session->rtp.rem_addr.sin_addr); + if (err < 0) + { + g_warning ("Error in socket address:%s.", getSocketError()); + return err; + } + session->rtp.rem_addr.sin_port = htons (port); + + memcpy (&session->rtcp.rem_addr, &session->rtp.rem_addr, + sizeof (struct sockaddr_in)); + session->rtcp.rem_addr.sin_port = htons (port + 1); + session->rtcp.addrlen=sizeof(session->rtp.rem_addr); +#endif +#ifndef NOCONNECT + if (session->mode == RTP_SESSION_SENDONLY) + { + err = connect (session->rtp.socket, + (struct sockaddr *) &session->rtp.rem_addr, +#ifdef INET6 + session->rtp.addrlen); +#else + sizeof (struct sockaddr_in)); +#endif + if (err != 0) + { + g_message ("Can't connect rtp socket: %s.",getSocketError()); + return err; + } + err = connect (session->rtcp.socket, + (struct sockaddr *) &session->rtcp.rem_addr, +#ifdef INET6 + session->rtcp.addrlen); +#else + sizeof (struct sockaddr_in)); +#endif + if (err != 0) + { + g_message ("Can't connect rtp socket: %s.",getSocketError()); + return err; + } + } +#endif + return 0; +} + +void rtp_session_set_sockets(RtpSession *session, gint rtpfd, gint rtcpfd) +{ + if (rtpfd>0) set_non_blocking_socket(rtpfd); + if (rtcpfd>0) set_non_blocking_socket(rtcpfd); + session->rtp.socket=rtpfd; + session->rtcp.socket=rtcpfd; + session->flags|=RTP_SESSION_USING_EXT_SOCKETS; +} + +/** + *rtp_session_flush_sockets: + *@session: a rtp session + * + * Flushes the sockets for all pending incoming packets. + * This can be usefull if you did not listen to the stream for a while + * and wishes to start to receive again. During the time no receive is made + * packets get bufferised into the internal kernel socket structure. + * +**/ +void rtp_session_flush_sockets(RtpSession *session){ + char trash[4096]; +#ifdef INET6 + struct sockaddr_storage from; +#else + struct sockaddr from; +#endif + socklen_t fromlen=sizeof(from); + if (session->rtp.socket>0){ + while (recvfrom(session->rtp.socket,(void*)trash,sizeof(trash),0,(struct sockaddr *)&from,&fromlen)>0){}; + } + if (session->rtcp.socket>0){ + while (recvfrom(session->rtcp.socket,(void*)trash,sizeof(trash),0,(struct sockaddr*)&from,&fromlen)>0){}; + } +} + +/** + *rtp_session_set_seq_number: + *@session: a rtp session freshly created. + *@addr: a 16 bit unsigned number. + * + * sets the initial sequence number of a sending session. + * +**/ +void rtp_session_set_seq_number(RtpSession *session, guint16 seq){ + session->rtp.snd_seq=seq; +} + + +guint16 rtp_session_get_seq_number(RtpSession *session){ + return session->rtp.snd_seq; +} + + +#ifdef USE_SENDMSG +#define MAX_IOV 10 +static gint rtp_sendmsg(int sock,mblk_t *m, struct sockaddr *rem_addr, int addr_len){ + int error; + struct msghdr msg; + struct iovec iov[MAX_IOV]; + int iovlen; + for(iovlen=0; iovlen<MAX_IOV && m!=NULL; m=m->b_cont,iovlen++){ + iov[iovlen].iov_base=m->b_rptr; + iov[iovlen].iov_len=m->b_wptr-m->b_rptr; + } + msg.msg_name=(void*)rem_addr; + msg.msg_namelen=addr_len; + msg.msg_iov=&iov[0]; + msg.msg_iovlen=iovlen; + msg.msg_control=NULL; + msg.msg_controllen=0; + msg.msg_flags=0; + + error=sendmsg(sock,&msg,0); + return error; +} +#endif + +static gint +ortp_rtp_send (RtpSession * session, mblk_t * m) +{ + gint error; + int i; + rtp_header_t *hdr; + + hdr = (rtp_header_t *) m->b_rptr; + /* perform host to network conversions */ + hdr->ssrc = htonl (hdr->ssrc); + hdr->timestamp = htonl (hdr->timestamp); + hdr->seq_number = htons (hdr->seq_number); + for (i = 0; i < hdr->cc; i++) + hdr->csrc[i] = htonl (hdr->csrc[i]); + +#ifdef USE_SENDMSG + if (session->flags & RTP_SESSION_USING_EXT_SOCKETS){ + error=rtp_sendmsg(session->rtp.socket,m,(struct sockaddr *)NULL,0); + }else { + error=rtp_sendmsg(session->rtp.socket,m,(struct sockaddr *) &session->rtp.rem_addr, + session->rtp.addrlen); + } +#else + if (m->b_cont!=NULL){ + mblk_t *newm=msgpullup(m,-1); + freemsg(m); + m=newm; + } + if (session->flags & RTP_SESSION_USING_EXT_SOCKETS){ + error=send(session->rtp.socket, m->b_rptr, (m->b_wptr - m->b_rptr),0); + }else error = sendto (session->rtp.socket, m->b_rptr, + (m->b_wptr - m->b_rptr), 0, + (struct sockaddr *) &session->rtp.rem_addr, + session->rtp.addrlen); +#endif + if (error < 0){ + if (session->on_network_error.count>0){ + rtp_signal_table_emit3(&session->on_network_error,(gpointer)"Error sending RTP packet",INT_TO_POINTER(getSocketErrorCode())); + }else g_warning ("Error sending rtp packet: %s ; socket=%i", getSocketError(), session->rtp.socket); + } + freemsg (m); + return error; +} + +gint +ortp_rtcp_send (RtpSession * session, mblk_t * m) +{ + gint error=0; + gboolean using_ext_socket=(session->flags & RTP_SESSION_USING_EXT_SOCKETS)!=0; + if ( (using_ext_socket && session->rtcp.socket>0 ) || session->rtcp.addrlen>0){ + +#ifndef USE_SENDMSG + if (m->b_cont!=NULL){ + mblk_t *newm=msgpullup(m,-1); + freemsg(m); + m=newm; + } +#endif + if (using_ext_socket && session->rtcp.socket>0 ){ +#ifdef USE_SENDMSG + error=rtp_sendmsg(session->rtcp.socket,m,(struct sockaddr *)NULL,0); +#else + error=send(session->rtcp.socket, m->b_rptr, (m->b_wptr - m->b_rptr),0); +#endif + }else { +#ifdef USE_SENDMSG + error=rtp_sendmsg(session->rtcp.socket,m,(struct sockaddr *) &session->rtcp.rem_addr, + session->rtcp.addrlen); +#else + error = sendto (session->rtcp.socket, m->b_rptr, + (m->b_wptr - m->b_rptr), 0, + (struct sockaddr *) &session->rtcp.rem_addr, + session->rtcp.addrlen); +#endif + } + + if (error < 0){ + if (session->on_network_error.count>0){ + rtp_signal_table_emit3(&session->on_network_error,(gpointer)"Error sending RTCP packet",INT_TO_POINTER(getSocketErrorCode())); + }else g_warning ("Error sending rtcp packet: %s ; socket=%i", getSocketError(), session->rtcp.socket); + } + }else g_warning("Cannot send rtcp report because I don't know the remote address."); + freemsg (m); + return error; +} + + +/** + *rtp_session_set_ssrc: + *@session: a rtp session. + *@ssrc: an unsigned 32bit integer representing the synchronisation source identifier (SSRC). + * + * Sets the SSRC for the outgoing stream. + * If not done, a random ssrc is used. + * +**/ +void +rtp_session_set_ssrc (RtpSession * session, guint32 ssrc) +{ + session->send_ssrc = ssrc; +} + +/* this function initialize all session parameter's that depend on the payload type */ +static void payload_type_changed(RtpSession *session, PayloadType *pt){ + jitter_control_set_payload(&session->rtp.jittctl,pt); + session->rtp.rtcp_report_snt_interval=RTCP_DEFAULT_REPORT_INTERVAL*pt->clock_rate; + rtp_session_set_time_jump_limit(session,session->rtp.time_jump); +} + +/** + *rtp_session_set_payload_type: + *@session: a rtp session + *@paytype: the payload type + * + * Sets the payload type of the rtp session. It decides of the payload types written in the + * of the rtp header for the outgoing stream, if the session is SENDRECV or SENDONLY. + * For the incoming stream, it sets the waited payload type. If that value does not match + * at any time this waited value, then the application can be informed by registering + * for the "payload_type_changed" signal, so that it can make the necessary changes + * on the downstream decoder that deals with the payload of the packets. + * + *Returns: 0 on success, -1 if the payload is not defined. +**/ + +int +rtp_session_set_payload_type (RtpSession * session, int paytype) +{ + PayloadType *pt; + session->payload_type = paytype; + pt=rtp_profile_get_payload(session->profile,paytype); + if (pt!=NULL){ + payload_type_changed(session,pt); + } + return 0; +} + +int rtp_session_get_payload_type(RtpSession *session){ + return session->payload_type; +} + + +/** + *rtp_session_set_payload_type_with_string: + *@session: a rtp session + *@paytype: the payload type + * + * Sets the payload type of the rtp session. It decides of the payload types written in the + * of the rtp header for the outgoing stream, if the session is SENDRECV or SENDONLY. + * Unlike #rtp_session_set_payload_type(), it takes as argument a string referencing the + * payload type (mime type). + * For the incoming stream, it sets the waited payload type. If that value does not match + * at any time this waited value, then the application can be informed by registering + * for the "payload_type_changed" signal, so that it can make the necessary changes + * on the downstream decoder that deals with the payload of the packets. + * + *Returns: 0 on success, -1 if the payload is not defined. +**/ + +int +rtp_session_set_payload_type_with_string (RtpSession * session, const char * mime) +{ + int pt; + pt=rtp_profile_get_payload_number_from_mime(session->profile,mime); + if (pt<0) { + g_warning("%s is not a know mime string within the rtpsession's profile.",mime); + return -1; + } + rtp_session_set_payload_type(session,pt); + return 0; +} + + +/** + *rtp_session_create_packet: + *@session: a rtp session. + *@header_size: the rtp header size. For standart size (without extensions), it is #RTP_FIXED_HEADER_SIZE + *@payload :data to be copied into the rtp packet. + *@payload_size : size of data carried by the rtp packet. + * + * Allocates a new rtp packet. In the header, ssrc and payload_type according to the session's + * context. Timestamp and seq number are not set, there will be set when the packet is going to be + * sent with rtp_session_sendm_with_ts(). + * + *Returns: a rtp packet in a mblk_t (message block) structure. +**/ +mblk_t * rtp_session_create_packet(RtpSession *session,gint header_size, const char *payload, gint payload_size) +{ + mblk_t *mp; + gint msglen=header_size+payload_size; + rtp_header_t *rtp; + + mp=allocb(msglen,BPRI_MED); + rtp=(rtp_header_t*)mp->b_rptr; + rtp->version = 2; + rtp->padbit = 0; + rtp->extbit = 0; + rtp->markbit= 0; + rtp->cc = 0; + rtp->paytype = session->payload_type; + rtp->ssrc = session->send_ssrc; + rtp->timestamp = 0; /* set later, when packet is sended */ + rtp->seq_number = 0; /*set later, when packet is sended */ + /*copy the payload */ + mp->b_wptr+=header_size; + memcpy(mp->b_wptr,payload,payload_size); + mp->b_wptr+=payload_size; + return mp; +} + +/** + *rtp_session_create_packet_with_data: + *@session: a rtp session. + *@payload : the data to be sent with this packet + *@payload_size : size of data + *@freefn : a function that will be called when the payload buffer is no more needed. + * + * Creates a new rtp packet using the given payload buffer (no copy). The header will be allocated separetely. + * In the header, ssrc and payload_type according to the session's + * context. Timestamp and seq number are not set, there will be set when the packet is going to be + * sent with rtp_session_sendm_with_ts(). + * oRTP will send this packet using libc's sendmsg() (if this function is availlable!) so that there will be no + * packet concatenation involving copies to be done in user-space. + * @freefn can be NULL, in that case payload will be kept untouched. + * + *Returns: a rtp packet in a mblk_t (message block) structure. +**/ + +mblk_t * rtp_session_create_packet_with_data(RtpSession *session, char *payload, gint payload_size, void (*freefn)(void*)) +{ + mblk_t *mp,*mpayload; + gint header_size=RTP_FIXED_HEADER_SIZE; /* revisit when support for csrc is done */ + rtp_header_t *rtp; + + mp=allocb(header_size,BPRI_MED); + rtp=(rtp_header_t*)mp->b_rptr; + rtp->version = 2; + rtp->padbit = 0; + rtp->extbit = 0; + rtp->markbit= 0; + rtp->cc = 0; + rtp->paytype = session->payload_type; + rtp->ssrc = session->send_ssrc; + rtp->timestamp = 0; /* set later, when packet is sended */ + rtp->seq_number = 0; /*set later, when packet is sended */ + mp->b_wptr+=header_size; + /* create a mblk_t around the user supplied payload buffer */ + mpayload=allocb_with_buf(payload,payload_size,BPRI_MED,freefn); + mpayload->b_wptr+=payload_size; + /* link it with the header */ + mp->b_cont=mpayload; + return mp; +} + + +/** + *rtp_session_create_packet_in_place: + *@session: a rtp session. + *@buffer: a buffer that contains first just enough place to write a RTP header, then the data to send. + *@size : the size of the buffer + *@freefn : a function that will be called once the buffer is no more needed (the data has been sent). + * + * Creates a new rtp packet using the buffer given in arguments (no copy). + * In the header, ssrc and payload_type according to the session's + * context. Timestamp and seq number are not set, there will be set when the packet is going to be + * sent with rtp_session_sendm_with_ts(). + * @freefn can be NULL, in that case payload will be kept untouched. + * + *Returns: a rtp packet in a mblk_t (message block) structure. +**/ +mblk_t * rtp_session_create_packet_in_place(RtpSession *session,char *buffer, gint size, void (*freefn)(void*) ) +{ + mblk_t *mp; + rtp_header_t *rtp; + + mp=allocb_with_buf(buffer,size,BPRI_MED,freefn); + + rtp=(rtp_header_t*)mp->b_rptr; + rtp->version = 2; + rtp->padbit = 0; + rtp->extbit = 0; + rtp->markbit= 0; + rtp->cc = 0; + rtp->paytype = session->payload_type; + rtp->ssrc = session->send_ssrc; + rtp->timestamp = 0; /* set later, when packet is sended */ + rtp->seq_number = 0; /*set later, when packet is sended */ + return mp; +} + + +/** + *rtp_session_sendm_with_ts: + *@session : a rtp session. + *@mp : a rtp packet presented as a mblk_t. + *@timestamp: the timestamp of the data to be sent. Refer to the rfc to know what it is. + * + * Send the rtp datagram @mp to the destination set by rtp_session_set_remote_addr() + * with timestamp @timestamp. For audio data, the timestamp is the number + * of the first sample resulting of the data transmitted. See rfc1889 for details. + * The packet (@mp) is freed once it is sended. + * + *Returns: the number of bytes sent over the network. +**/ +gint +rtp_session_sendm_with_ts (RtpSession * session, mblk_t *mp, guint32 timestamp) +{ + rtp_header_t *rtp; + guint32 packet_time; + gint error = 0; + gint payloadsize; + RtpScheduler *sched=session->sched; + RtpStream *stream=&session->rtp; + + if (session->flags & RTP_SESSION_SEND_NOT_STARTED) + { + session->rtp.snd_ts_offset = timestamp; + if (session->flags & RTP_SESSION_SCHEDULED) + { + session->rtp.snd_time_offset = sched->time_; + } + rtp_session_unset_flag (session,RTP_SESSION_SEND_NOT_STARTED); + } + /* if we are in blocking mode, then suspend the process until the scheduler it's time to send the + * next packet */ + /* if the timestamp of the packet queued is older than current time, then you we must + * not block */ + if (session->flags & RTP_SESSION_SCHEDULED) + { + packet_time = + rtp_session_ts_to_time (session, + timestamp - + session->rtp.snd_ts_offset) + + session->rtp.snd_time_offset; + /*g_message("rtp_session_send_with_ts: packet_time=%i time=%i",packet_time,sched->time_);*/ + wait_point_lock(&session->send_wp); + if (TIME_IS_STRICTLY_NEWER_THAN (packet_time, sched->time_)) + { + wait_point_wakeup_at(&session->send_wp,packet_time,(session->flags & RTP_SESSION_BLOCKING_MODE)!=0); + session_set_clr(&sched->w_sessions,session); /* the session has written */ + } + else session_set_set(&sched->w_sessions,session); /*to indicate select to return immediately */ + wait_point_unlock(&session->send_wp); + } + + + rtp=(rtp_header_t*)mp->b_rptr; + + payloadsize = msgdsize(mp) - RTP_FIXED_HEADER_SIZE - (rtp->cc*sizeof(guint32)); + rtp_session_lock (session); + + /* set a seq number */ + rtp->seq_number=session->rtp.snd_seq; + rtp->timestamp=timestamp; + session->rtp.snd_seq++; + session->rtp.snd_last_ts = timestamp; + + + ortp_global_stats.sent += payloadsize; + stream->stats.sent += payloadsize; + ortp_global_stats.packet_sent++; + stream->stats.packet_sent++; + + error = ortp_rtp_send (session, mp); + rtp_session_rtcp_process(session); + rtp_session_unlock (session); + + return error; +} + + +/** + *rtp_session_send_with_ts: + *@session: a rtp session. + *@buffer: a buffer containing the data to be sent in a rtp packet. + *@len: the length of the data buffer, in bytes. + *@userts: the timestamp of the data to be sent. Refer to the rfc to know what it is. + * + * Send a rtp datagram to the destination set by rtp_session_set_remote_addr() containing + * the data from @buffer with timestamp @userts. This is a high level function that uses + * rtp_session_create_packet() and rtp_session_sendm_with_ts() to send the data. + * + * + *Returns: the number of bytes sent over the network. +**/ +gint +rtp_session_send_with_ts (RtpSession * session, const gchar * buffer, gint len, + guint32 userts) +{ + mblk_t *m; + int err; +#ifdef USE_SENDMSG + m=rtp_session_create_packet_with_data(session,(gchar*)buffer,len,NULL); +#else + m = rtp_session_create_packet(session,RTP_FIXED_HEADER_SIZE,(gchar*)buffer,len); +#endif + err=rtp_session_sendm_with_ts(session,m,userts); + return err; +} + + +static gint +rtp_recv (RtpSession * session, guint32 user_ts) +{ + gint error; + struct sockaddr remaddr; + socklen_t addrlen = sizeof (remaddr); + char *p; + mblk_t *mp; + RtpStream *stream=&session->rtp; + + if (session->rtp.socket<1) return -1; /*session has no sockets for the moment*/ + + + while (1) + { + if (session->rtp.cached_mp==NULL) + session->rtp.cached_mp = allocb (session->max_buf_size, 0); + mp=session->rtp.cached_mp; + if (session->flags & RTP_SESSION_USING_EXT_SOCKETS){ + error=recv(session->rtp.socket,mp->b_wptr,session->max_buf_size,0); + }else error = recvfrom (session->rtp.socket, mp->b_wptr, + session->max_buf_size, 0, + (struct sockaddr *) &remaddr, + &addrlen); + if (error > 0) + { + if (error<RTP_FIXED_HEADER_SIZE){ + g_warning("Packet too small to be a rtp packet (%i)!",error); + stream->stats.bad++; + ortp_global_stats.bad++; + /* don't free, it will be reused next time */ + }else{ + /* resize the memory allocated to fit the udp message */ + + p = g_realloc (mp->b_wptr, error); + if (p != mp->b_wptr) + ortp_debug("The recv area has moved during reallocation."); + mp->b_datap->db_base = mp->b_rptr = + mp->b_wptr = p; + mp->b_wptr += error; + mp->b_datap->db_lim = mp->b_wptr; + /* then parse the message and put on queue */ + rtp_parse (session, mp, user_ts + session->rtp.hwrcv_diff_ts); + session->rtp.cached_mp=NULL; + } + } + else + { + if (error == 0) + { + g_warning + ("rtp_recv: strange... recv() returned zero."); + } + else if (errno!=EWOULDBLOCK && errno!=EAGAIN) + { + if (session->on_network_error.count>0){ + rtp_signal_table_emit3(&session->on_network_error,(gpointer)"Error receiving RTP packet",INT_TO_POINTER(getSocketErrorCode())); + }else g_warning("Error receiving RTP packet: %s.",getSocketError()); + } + /* don't free the cached_mp, it will be reused next time */ + return -1; /* avoids an infinite loop ! */ + } + } + return error; +} + +extern void rtcp_parse(RtpSession *session, mblk_t *mp); + +static gint +rtcp_recv (RtpSession * session) +{ + gint error; + struct sockaddr remaddr; + socklen_t addrlen=0; + char *p; + mblk_t *mp; + + + if (session->rtcp.socket<1) return -1; /*session has no rtcp sockets for the moment*/ + + + while (1) + { + if (session->rtcp.cached_mp==NULL) + session->rtcp.cached_mp = allocb (RTCP_MAX_RECV_BUFSIZE, 0); + + mp=session->rtcp.cached_mp; + if (session->flags & RTP_SESSION_USING_EXT_SOCKETS){ + error=recv(session->rtcp.socket,mp->b_wptr,RTCP_MAX_RECV_BUFSIZE,0); + }else { + addrlen=sizeof (remaddr); + error=recvfrom (session->rtcp.socket, mp->b_wptr, + RTCP_MAX_RECV_BUFSIZE, 0, + (struct sockaddr *) &remaddr, + &addrlen); + } + if (error > 0) + { + /* resize the memory allocated to fit the udp message */ + + p = g_realloc (mp->b_wptr, error); + if (p != mp->b_wptr) + ortp_debug("The recv area has moved during reallocation."); + mp->b_datap->db_base = mp->b_rptr = + mp->b_wptr = p; + mp->b_wptr += error; + mp->b_datap->db_lim = mp->b_wptr; + /* then parse the message */ + rtcp_parse (session, mp); + freemsg(mp); + session->rtcp.cached_mp=NULL; + if (addrlen>0){ + /* store the sender rtcp address to send him receiver reports */ + memcpy(&session->rtcp.rem_addr,&remaddr,addrlen); + } + } + else + { + if (error == 0) + { + g_warning + ("rtcp_recv: strange... recv() returned zero."); + } + else if (errno!=EWOULDBLOCK && errno!=EAGAIN) + { + if (session->on_network_error.count>0){ + rtp_signal_table_emit3(&session->on_network_error,(gpointer)"Error receiving RTCP packet",INT_TO_POINTER(getSocketErrorCode())); + }else g_warning("Error receiving RTCP packet: %s.",getSocketError()); + } + /* don't free the cached_mp, it will be reused next time */ + return -1; /* avoids an infinite loop ! */ + } + } + return error; +} + + +static void payload_type_changed_incoming(RtpSession *session, int paytype){ + /* check if we support this payload type */ + PayloadType *pt=rtp_profile_get_payload(session->profile,paytype); + if (pt!=0){ + g_message ("rtp_parse: payload type changed to %i(%s) !", + paytype,pt->mime_type); + session->payload_type = paytype; + payload_type_changed(session,pt); + rtp_signal_table_emit (&session->on_payload_type_changed); + }else{ + g_warning("Receiving packet with unknown payload type %i.",paytype); + } +} + + +/** + *rtp_session_recvm_with_ts: + *@session: a rtp session. + *@user_ts: a timestamp. + * + * Try to get a rtp packet presented as a mblk_t structure from the rtp session. + * The @user_ts parameter is relative to the first timestamp of the incoming stream. In other + * words, the application does not have to know the first timestamp of the stream, it can + * simply call for the first time this function with @user_ts=0, and then incrementing it + * as it want. The RtpSession takes care of synchronisation between the stream timestamp + * and the user timestamp given here. + * + *Returns: a rtp packet presented as a mblk_t. +**/ + +mblk_t * +rtp_session_recvm_with_ts (RtpSession * session, guint32 user_ts) +{ + mblk_t *mp = NULL; + rtp_header_t *rtp; + guint32 ts; + guint32 packet_time; + RtpScheduler *sched=session->sched; + RtpStream *stream=&session->rtp; + gint rejected=0; + + /* if we are scheduled, remember the scheduler time at which the application has + * asked for its first timestamp */ + + if (session->flags & RTP_SESSION_RECV_NOT_STARTED) + { + + session->rtp.rcv_query_ts_offset = user_ts; + if (session->flags & RTP_SESSION_SCHEDULED) + { + session->rtp.rcv_time_offset = sched->time_; + //g_message("setting snd_time_offset=%i",session->rtp.snd_time_offset); + } + rtp_session_unset_flag (session,RTP_SESSION_RECV_NOT_STARTED); + } + session->rtp.rcv_last_app_ts = user_ts; + rtp_recv (session, user_ts); + rtcp_recv(session); + /* check for telephone event first */ + /* first lock the session */ + rtp_session_lock (session); + mp=getq(&session->rtp.tev_rq); + if (mp!=NULL){ + rtp_signal_table_emit2(&session->on_telephone_event_packet,(gpointer)mp); + if (session->on_telephone_event.count>0){ + rtp_session_check_telephone_events(session,mp); + } + freemsg(mp); + mp=NULL; + } + + /* then now try to return a media packet, if possible */ + /* first condition: if the session is starting, don't return anything + * until the queue size reaches jitt_comp */ + + if (session->flags & RTP_SESSION_RECV_SYNC) + { + rtp_header_t *oldest, *newest; + queue_t *q = &session->rtp.rq; + if (qempty(q)) + { + ortp_debug ("Queue is empty."); + goto end; + } + oldest = (rtp_header_t *) qfirst(q)->b_rptr; + newest = (rtp_header_t *) qlast(q)->b_rptr; + if ((guint32) (newest->timestamp - oldest->timestamp) < + session->rtp.jittctl.jitt_comp_ts) + { + ortp_debug("Not enough packet bufferised."); + goto end; + } + /* enough packet bufferised */ + mp = getq (&session->rtp.rq); + rtp = (rtp_header_t *) mp->b_rptr; + session->rtp.rcv_ts_offset = rtp->timestamp; + /* remember the timestamp offset between the stream timestamp (random) + * and the user timestamp, that very often starts at zero */ + session->rtp.rcv_diff_ts = rtp->timestamp - user_ts; + /* remember the difference between the last received on the socket timestamp and the user timestamp */ + session->rtp.hwrcv_diff_ts=session->rtp.rcv_diff_ts + session->rtp.jittctl.jitt_comp_ts; + session->rtp.rcv_last_ret_ts = user_ts; /* just to have an init value */ + session->rtp.rcv_last_ts = rtp->timestamp; + session->recv_ssrc = rtp->ssrc; + /* delete the recv synchronisation flag */ + rtp_session_unset_flag (session, RTP_SESSION_RECV_SYNC); + ortp_debug("Returning FIRST packet with ts=%i, hwrcv_diff_ts=%i, rcv_diff_ts=%i", rtp->timestamp, + session->rtp.hwrcv_diff_ts,session->rtp.rcv_diff_ts); + + goto end; + } + /* else this the normal case */ + /*calculate the stream timestamp from the user timestamp */ + ts = user_ts + session->rtp.rcv_diff_ts; + session->rtp.rcv_last_ts = ts; + mp = rtp_getq (&session->rtp.rq, ts,&rejected); + + stream->stats.skipped+=rejected; + ortp_global_stats.skipped+=rejected; + + /* perhaps we can now make some checks to see if a resynchronization is needed */ + /* TODO */ + goto end; + + end: + if (mp != NULL) + { + int msgsize = msgdsize (mp); /* evaluate how much bytes (including header) is received by app */ + guint32 packet_ts; + ortp_global_stats.recv += msgsize; + stream->stats.recv += msgsize; + rtp = (rtp_header_t *) mp->b_rptr; + packet_ts=rtp->timestamp; + ortp_debug("Returning mp with ts=%i", packet_ts); + /* check for payload type changes */ + if (session->payload_type != rtp->paytype) + { + payload_type_changed_incoming(session, rtp->paytype); + } + /* patch the packet so that it has a timestamp compensated by the + adaptive jitter buffer mechanism */ + if (session->rtp.jittctl.adaptive){ + rtp->timestamp-=session->rtp.jittctl.corrective_slide; + /*printf("Returned packet has timestamp %u, with clock slide compensated it is %u\n",packet_ts,rtp->timestamp);*/ + } + } + else + { + ortp_debug ("No mp for timestamp queried"); + stream->stats.unavaillable++; + ortp_global_stats.unavaillable++; + } + rtp_session_rtcp_process(session); + rtp_session_unlock (session); + + if (session->flags & RTP_SESSION_SCHEDULED) + { + /* if we are in blocking mode, then suspend the calling process until timestamp + * wanted expires */ + /* but we must not block the process if the timestamp wanted by the application is older + * than current time */ + packet_time = + rtp_session_ts_to_time (session, + user_ts - + session->rtp.rcv_query_ts_offset) + + session->rtp.rcv_time_offset; + ortp_debug ("rtp_session_recvm_with_ts: packet_time=%i, time=%i",packet_time, sched->time_); + wait_point_lock(&session->recv_wp); + if (TIME_IS_STRICTLY_NEWER_THAN (packet_time, sched->time_)) + { + wait_point_wakeup_at(&session->recv_wp,packet_time, (session->flags & RTP_SESSION_BLOCKING_MODE)!=0); + session_set_clr(&sched->r_sessions,session); + } + else session_set_set(&sched->r_sessions,session); /*to unblock _select() immediately */ + wait_point_unlock(&session->recv_wp); + } + return mp; +} + + +gint msg_to_buf (mblk_t * mp, char *buffer, gint len) +{ + gint rlen = len; + mblk_t *m, *mprev; + gint mlen; + m = mp->b_cont; + mprev = mp; + while (m != NULL) + { + mlen = m->b_wptr - m->b_rptr; + if (mlen <= rlen) + { + mblk_t *consumed = m; + memcpy (buffer, m->b_rptr, mlen); + /* go to next mblk_t */ + mprev->b_cont = m->b_cont; + m = m->b_cont; + consumed->b_cont = NULL; + freeb (consumed); + buffer += mlen; + rlen -= mlen; + } + else + { /*if mlen>rlen */ + memcpy (buffer, m->b_rptr, rlen); + m->b_rptr += rlen; + return len; + } + } + return len - rlen; +} + +/** + *rtp_session_recv_with_ts: + *@session: a rtp session. + *@buffer: a user supplied buffer to write the data. + *@len: the length in bytes of the user supplied buffer. + *@time: the timestamp wanted. + *@have_more: the address of an integer to indicate if more data is availlable for the given timestamp. + * + * Tries to read the bytes of the incoming rtp stream related to timestamp @time. In case + * where the user supplied buffer @buffer is not large enough to get all the data + * related to timestamp @time, then *( @have_more) is set to 1 to indicate that the application + * should recall the function with the same timestamp to get more data. + * + * When the rtp session is scheduled (see rtp_session_set_scheduling_mode() ), and the + * blocking mode is on (see rtp_session_set_blocking_mode() ), then the calling thread + * is suspended until the timestamp given as argument expires, whatever a received packet + * fits the query or not. + * + * Important note: it is clear that the application cannot know the timestamp of the first + * packet of the incoming stream, because it can be random. The @time timestamp given to the + * function is used relatively to first timestamp of the stream. In simple words, 0 is a good + * value to start calling this function. + * + * This function internally calls rtp_session_recvm_with_ts() to get a rtp packet. The content + * of this packet is then copied into the user supplied buffer in an intelligent manner: + * the function takes care of the size of the supplied buffer and the timestamp given in + * argument. Using this function it is possible to read continous audio data (e.g. pcma,pcmu...) + * with for example a standart buffer of size of 160 with timestamp incrementing by 160 while the incoming + * stream has a different packet size. + * + *Returns: if a packet was availlable with the corresponding timestamp supplied in argument + * then the number of bytes written in the user supplied buffer is returned. If no packets + * are availlable, either because the sender has not started to send the stream, or either + * because silence packet are not transmitted, or either because the packet was lost during + * network transport, then the function returns zero. +**/ +gint rtp_session_recv_with_ts (RtpSession * session, gchar * buffer, + gint len, guint32 time, gint * have_more) +{ + mblk_t *mp; + gint rlen = len; + gint wlen, mlen; + guint32 ts_int = 0; /*the length of the data returned in the user supplied buffer, in TIMESTAMP UNIT */ + PayloadType *payload; + RtpStream *stream=&session->rtp; + + *have_more = 0; + + mp = rtp_session_recvm_with_ts (session, time); + payload =rtp_profile_get_payload (session->profile, + session->payload_type); + if (payload==NULL){ + g_warning("rtp_session_recv_with_ts: unable to recv an unsupported payload."); + if (mp!=NULL) freemsg(mp); + return -1; + } + if (!(session->flags & RTP_SESSION_RECV_SYNC)) + { + //ortp_debug("time=%i rcv_last_ret_ts=%i",time,session->rtp.rcv_last_ret_ts); + if (RTP_TIMESTAMP_IS_STRICTLY_NEWER_THAN + (time, session->rtp.rcv_last_ret_ts)) + { + /* the user has missed some data previously, so we are going to give him now. */ + /* we must tell him to call the function once again with the same timestamp + * by setting *have_more=1 */ + *have_more = 1; + } + if (payload->type == PAYLOAD_AUDIO_CONTINUOUS) + { + ts_int = (len * payload->bits_per_sample) >> 3; + session->rtp.rcv_last_ret_ts += ts_int; + //ortp_debug("ts_int=%i",ts_int); + } + else + ts_int = 0; + } + else return 0; + + /* try to fill the user buffer */ + while (1) + { + + if (mp != NULL) + { + mlen = msgdsize (mp->b_cont); + wlen = msg_to_buf (mp, buffer, rlen); + buffer += wlen; + rlen -= wlen; + ortp_debug("mlen=%i wlen=%i rlen=%i", mlen, wlen, + rlen); + /* do we fill all the buffer ? */ + if (rlen > 0) + { + /* we did not fill all the buffer */ + freemsg (mp); + /* if we have continuous audio, try to get other packets to fill the buffer, + * ie continue the loop */ + //ortp_debug("User buffer not filled entirely"); + if (ts_int > 0) + { + time = session->rtp.rcv_last_ret_ts; + ortp_debug("Need more: will ask for %i.", + time); + } + else + return len - rlen; + } + else if (mlen > wlen) + { + int unread = + mlen - wlen + (mp->b_wptr - + mp->b_rptr); + /* not enough space in the user supplied buffer */ + /* we re-enqueue the msg with its updated read pointers for next time */ + ortp_debug ("Re-enqueuing packet."); + rtp_session_lock (session); + rtp_putq (&session->rtp.rq, mp); + rtp_session_unlock (session); + /* quite ugly: I change the stats ... */ + ortp_global_stats.recv -= unread; + stream->stats.recv -= unread; + return len; + } + else + { + /* the entire packet was written to the user buffer */ + freemsg (mp); + return len; + } + } + else + { + /* fill with a zero pattern (silence) */ + if (payload->pattern_length != 0) + { + int i = 0, j = 0; + while (i < rlen) + { + buffer[i] = payload->zero_pattern[j]; + i++; + j++; + if (j <= payload->pattern_length) + j = 0; + } + return len; + } + *have_more = 0; + return 0; + } + mp = rtp_session_recvm_with_ts (session, time); + payload = rtp_profile_get_payload (session->profile, + session->payload_type); + if (payload==NULL){ + g_warning("rtp_session_recv_with_ts: unable to recv an unsupported payload."); + if (mp!=NULL) freemsg(mp); + return -1; + } + } + return -1; +} +/** + *rtp_session_get_current_send_ts: + *@session: a rtp session. + * + * When the rtp session is scheduled and has started to send packets, this function + * computes the timestamp that matches to the present time. Using this function can be + * usefull when sending discontinuous streams. Some time can be elapsed between the end + * of a stream burst and the begin of a new stream burst, and the application may be not + * not aware of this elapsed time. In order to get a valid (current) timestamp to pass to + * #rtp_session_send_with_ts() or #rtp_session_sendm_with_ts(), the application may + * use rtp_session_get_current_send_ts(). + * + *Returns: the current send timestamp for the rtp session. +**/ +guint32 rtp_session_get_current_send_ts(RtpSession *session) +{ + guint32 userts; + guint32 session_time; + RtpScheduler *sched=session->sched; + PayloadType *payload; + g_return_val_if_fail (session->payload_type<128, 0); + payload=rtp_profile_get_payload(session->profile,session->payload_type); + g_return_val_if_fail(payload!=NULL, 0); + if ( (session->flags & RTP_SESSION_SCHEDULED)==0 ){ + g_warning("can't guess current timestamp because session is not scheduled."); + return 0; + } + session_time=sched->time_-session->rtp.snd_time_offset; + userts= (guint32)( ( (gdouble)(session_time) * (gdouble) payload->clock_rate )/ 1000.0) + + session->rtp.snd_ts_offset; + return userts; +} + +/** + *rtp_session_get_current_recv_ts: + *@session: a rtp session. + * + * Same thing as rtp_session_get_current_send_ts() except that it's for an incoming stream. + * Works only on scheduled mode. + * + * Returns: the theoritical that would have to be receive now. + * +**/ +guint32 rtp_session_get_current_recv_ts(RtpSession *session){ + guint32 userts; + guint32 session_time; + RtpScheduler *sched=ortp_get_scheduler(); + PayloadType *payload; + g_return_val_if_fail (session->payload_type<128, 0); + payload=rtp_profile_get_payload(session->profile,session->payload_type); + g_return_val_if_fail(payload!=NULL, 0); + if ( (session->flags & RTP_SESSION_SCHEDULED)==0 ){ + g_warning("can't guess current timestamp because session is not scheduled."); + return 0; + } + session_time=sched->time_-session->rtp.rcv_time_offset; + userts= (guint32)( ( (gdouble)(session_time) * (gdouble) payload->clock_rate )/ 1000.0) + + session->rtp.rcv_ts_offset; + return userts; +} + +/** + *rtp_session_set_time_jump_limit: + *@session: the rtp session + *@ts_step: a time interval in miliseconds + * + * oRTP has the possibility to inform the application through a callback registered + * with rtp_session_signal_connect about crazy incoming RTP stream that jumps from + * a timestamp N to N+<some crazy value>. This lets the opportunity for the application + * to reset the session in order to resynchronize, or any other action like stopping the call + * and reporting an error. +**/ +void rtp_session_set_time_jump_limit(RtpSession *session, gint milisecs){ + guint32 ts; + session->rtp.time_jump=milisecs; + ts=rtp_session_time_to_ts(session,milisecs); + if (ts==0) session->rtp.ts_jump=1<<31; /* do not detect ts jump */ + else session->rtp.ts_jump=ts; +} + +void rtp_session_uninit (RtpSession * session) +{ + /* first of all remove the session from the scheduler */ + if (session->flags & RTP_SESSION_SCHEDULED) + { + rtp_scheduler_remove_session (session->sched,session); + } + /*flush all queues */ + flushq (&session->rtp.rq, FLUSHALL); + + /* close sockets */ + close_socket (session->rtp.socket); + close_socket (session->rtcp.socket); + + wait_point_uninit(&session->send_wp); + wait_point_uninit(&session->recv_wp); + g_mutex_free (session->lock); + session->lock=NULL; + if (session->current_tev!=NULL) freemsg(session->current_tev); + if (session->rtp.cached_mp!=NULL) freemsg(session->rtp.cached_mp); + if (session->rtcp.cached_mp!=NULL) freemsg(session->rtcp.cached_mp); + if (session->sd!=NULL) freemsg(session->sd); +} + +/** + *rtp_session_reset: + *@session: a rtp session. + * + * Reset the session: local and remote addresses are kept unchanged but the internal + * queue for ordering and buffering packets is flushed, the session is ready to be + * re-synchronised to another incoming stream. + * +**/ +void rtp_session_reset (RtpSession * session) +{ + + if (session->flags & RTP_SESSION_SCHEDULED) rtp_session_lock (session); + + flushq (&session->rtp.rq, FLUSHALL); + rtp_session_set_flag (session, RTP_SESSION_RECV_SYNC); + rtp_session_set_flag (session, RTP_SESSION_SEND_SYNC); + rtp_session_set_flag (session, RTP_SESSION_RECV_NOT_STARTED); + rtp_session_set_flag (session, RTP_SESSION_SEND_NOT_STARTED); + //session->ssrc=0; + session->rtp.snd_time_offset = 0; + session->rtp.snd_ts_offset = 0; + session->rtp.snd_rand_offset = 0; + session->rtp.snd_last_ts = 0; + session->rtp.rcv_time_offset = 0; + session->rtp.rcv_ts_offset = 0; + session->rtp.rcv_query_ts_offset = 0; + session->rtp.rcv_diff_ts = 0; + session->rtp.rcv_ts = 0; + session->rtp.rcv_last_ts = 0; + session->rtp.rcv_last_app_ts = 0; + session->rtp.hwrcv_extseq.one = 0; + session->rtp.hwrcv_since_last_SR=0; + session->rtp.snd_seq = 0; + rtp_stats_reset(&session->rtp.stats); + jitter_control_init(&session->rtp.jittctl,-1,NULL); + + if (session->flags & RTP_SESSION_SCHEDULED) rtp_session_unlock (session); + +} + +/** + *rtp_session_destroy: + *@session: a rtp session. + * + * Destroys a rtp session. + * +**/ +void rtp_session_destroy (RtpSession * session) +{ + rtp_session_uninit (session); + g_free (session); +} + +guint32 rtp_session_time_to_ts(RtpSession *session, gint time){ + PayloadType *payload; + g_return_val_if_fail (session->payload_type < 127, 0); + payload = + rtp_profile_get_payload (session->profile, + session->payload_type); + if (payload == NULL) + { + g_warning + ("rtp_session_ts_to_t: use of unsupported payload type."); + return 0; + } + /* the return value is in milisecond */ + return (double)payload->clock_rate*(double)time/1000.0; +} + +/* function used by the scheduler only:*/ +guint32 rtp_session_ts_to_time (RtpSession * session, guint32 timestamp) +{ + PayloadType *payload; + g_return_val_if_fail (session->payload_type < 127, 0); + payload = + rtp_profile_get_payload (session->profile, + session->payload_type); + if (payload == NULL) + { + g_warning + ("rtp_session_ts_to_t: use of unsupported payload type."); + return 0; + } + /* the return value is in milisecond */ + return (guint32) (1000.0 * + ((double) timestamp / + (double) payload->clock_rate)); +} + + +/* time is the number of miliseconds elapsed since the start of the scheduler */ +void rtp_session_process (RtpSession * session, guint32 time, RtpScheduler *sched) +{ + wait_point_lock(&session->send_wp); + if (wait_point_check(&session->send_wp,time)){ + session_set_set(&sched->w_sessions,session); + wait_point_wakeup(&session->send_wp); + } + wait_point_unlock(&session->send_wp); + + wait_point_lock(&session->recv_wp); + if (wait_point_check(&session->recv_wp,time)){ + session_set_set(&sched->r_sessions,session); + wait_point_wakeup(&session->recv_wp); + } + wait_point_unlock(&session->recv_wp); +} + + +void rtp_session_make_time_distorsion(RtpSession *session, gint milisec) +{ + session->rtp.snd_time_offset+=milisec; +} + + +/* packet api */ + +void rtp_add_csrc(mblk_t *mp, guint32 csrc) +{ + rtp_header_t *hdr=(rtp_header_t*)mp->b_rptr; + hdr->csrc[hdr->cc]=csrc; + hdr->cc++; +} diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpsession.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpsession.h new file mode 100644 index 00000000..e7702000 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpsession.h @@ -0,0 +1,287 @@ + /* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef RTPSESSION_H +#define RTPSESSION_H + + +#include <rtpport.h> +#include <rtp.h> +#include <payloadtype.h> +#include <sessionset.h> +#include <rtcp.h> +#include <str_utils.h> +#include <rtpsignaltable.h> + +#include <stdio.h> + + +#ifndef _WIN32 +# include <sys/types.h> +# include <sys/socket.h> +# include <errno.h> +# include <netinet/in.h> +# ifdef _XOPEN_SOURCE_EXTENDED +# include <arpa/inet.h> +# endif +# include <unistd.h> +# include <sys/time.h> +#else +# include <winsock2.h> +#endif /* _WIN32 */ + + + +typedef enum { + RTP_SESSION_RECVONLY, + RTP_SESSION_SENDONLY, + RTP_SESSION_SENDRECV +} RtpSessionMode; + + + +typedef enum { + RTP_SESSION_RECV_SYNC=1, /* the rtp session is synchronising in the incoming stream */ + RTP_SESSION_SEND_SYNC=1<<1, /* the rtp session is synchronising in the outgoing stream */ + RTP_SESSION_SCHEDULED=1<<2, /* the rtp session has to be scheduled */ + RTP_SESSION_BLOCKING_MODE=1<<3, /* in blocking mode */ + RTP_SESSION_RECV_NOT_STARTED=1<<4, /* the application has not started to try to recv */ + RTP_SESSION_SEND_NOT_STARTED=1<<5, /* the application has not started to send something */ + RTP_SESSION_IN_SCHEDULER=1<<6, /* the rtp session is in the scheduler list */ + RTP_SESSION_USING_EXT_SOCKETS=1<<7 /* the session is using externaly supplied sockets */ +}RtpSessionFlags; + + +typedef struct _JitterControl +{ + gint jitt_comp; /* the user jitt_comp in miliseconds*/ + gint jitt_comp_ts; /* the jitt_comp converted in rtp time (same unit as timestamp) */ + gint adapt_jitt_comp_ts; + float slide; + float jitter; + gint count; + gint olddiff; + float inter_jitter; /* interarrival jitter as defined in the RFC */ + gint corrective_step; + gint corrective_slide; + gboolean adaptive; +} JitterControl; + +typedef struct _WaitPoint +{ + GMutex *lock; + GCond *cond; + guint32 time; + gboolean wakeup; +} WaitPoint; + +typedef struct _RtpStream +{ + gint socket; + gint socktype; + gint max_rq_size; + gint time_jump; + guint32 ts_jump; + queue_t rq; + queue_t tev_rq; + mblk_t *cached_mp; +#ifdef INET6 + struct sockaddr_storage loc_addr; + struct sockaddr_storage rem_addr; +#else + struct sockaddr_in loc_addr; + struct sockaddr_in rem_addr; +#endif + int addrlen; + JitterControl jittctl; + guint32 snd_time_offset;/*the scheduler time when the application send its first timestamp*/ + guint32 snd_ts_offset; /* the first application timestamp sent by the application */ + guint32 snd_rand_offset; /* a random number added to the user offset to make the stream timestamp*/ + guint32 snd_last_ts; /* the last stream timestamp sended */ + guint32 rcv_time_offset; /*the scheduler time when the application ask for its first timestamp*/ + guint32 rcv_ts_offset; /* the first stream timestamp */ + guint32 rcv_query_ts_offset; /* the first user timestamp asked by the application */ + guint32 rcv_diff_ts; /* difference between the first user timestamp and first stream timestamp */ + guint32 hwrcv_diff_ts; + guint32 rcv_ts; /* to be unused */ + guint32 rcv_last_ts; /* the last stream timestamp got by the application */ + guint32 rcv_last_app_ts; /* the last application timestamp asked by the application */ + guint32 rcv_last_ret_ts; /* the timestamp of the last sample returned (only for continuous audio)*/ + poly32_t hwrcv_extseq; /* last received on socket extended sequence number */ + guint32 hwrcv_seq_at_last_SR; + guint hwrcv_since_last_SR; + guint32 last_rcv_SR_ts; /* NTP timestamp (middle 32 bits) of last received SR */ + struct timeval last_rcv_SR_time; /* time at which last SR was received */ + guint16 snd_seq; /* send sequence number */ + guint32 last_rtcp_report_snt_r; /* the time of the last rtcp report sent, in recv timestamp unit */ + guint32 last_rtcp_report_snt_s; /* the time of the last rtcp report sent, in send timestamp unit */ + guint32 rtcp_report_snt_interval; /* the interval in timestamp unit between rtcp report sent */ + rtp_stats_t stats; +}RtpStream; + +typedef struct _RtcpStream +{ + gint socket; + gint socktype; + mblk_t *cached_mp; +#ifdef INET6 + struct sockaddr_storage loc_addr; + struct sockaddr_storage rem_addr; +#else + struct sockaddr_in loc_addr; + struct sockaddr_in rem_addr; +#endif + int addrlen; +} RtcpStream; + +typedef struct _RtpSession RtpSession; + + + +struct _RtpSession +{ + RtpSession *next; /* next RtpSession, when the session are enqueued by the scheduler */ + RtpProfile *profile; + WaitPoint recv_wp; + WaitPoint send_wp; + GMutex *lock; + guint32 send_ssrc; + guint32 recv_ssrc; + gint payload_type; + gint max_buf_size; + RtpSignalTable on_ssrc_changed; + RtpSignalTable on_payload_type_changed; + RtpSignalTable on_telephone_event_packet; + RtpSignalTable on_telephone_event; + RtpSignalTable on_timestamp_jump; + RtpSignalTable on_network_error; + struct _OList *signal_tables; + RtpStream rtp; + RtcpStream rtcp; + RtpSessionMode mode; + struct _RtpScheduler *sched; + guint32 flags; + gint mask_pos; /* the position in the scheduler mask of RtpSession */ + gpointer user_data; + + /* telephony events extension */ + gint telephone_events_pt; /* the payload type used for telephony events */ + mblk_t *current_tev; /* the pending telephony events */ + mblk_t *sd; + queue_t contributing_sources; +}; + + + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*private */ +void rtp_session_init(RtpSession *session, gint mode); +#define rtp_session_lock(session) g_mutex_lock(session->lock) +#define rtp_session_unlock(session) g_mutex_unlock(session->lock) +#define rtp_session_set_flag(session,flag) (session)->flags|=(flag) +#define rtp_session_unset_flag(session,flag) (session)->flags&=~(flag) +void rtp_session_uninit(RtpSession *session); + +/* public API */ +RtpSession *rtp_session_new(gint mode); +void rtp_session_set_scheduling_mode(RtpSession *session, gint yesno); +void rtp_session_set_blocking_mode(RtpSession *session, gint yesno); +void rtp_session_set_profile(RtpSession *session,RtpProfile *profile); +#define rtp_session_get_profile(session) (session)->profile +int rtp_session_signal_connect(RtpSession *session,const gchar *signal, RtpCallback cb, gpointer user_data); +int rtp_session_signal_disconnect_by_callback(RtpSession *session,const gchar *signal, RtpCallback cb); +void rtp_session_set_ssrc(RtpSession *session, guint32 ssrc); +void rtp_session_set_seq_number(RtpSession *session, guint16 seq); +guint16 rtp_session_get_seq_number(RtpSession *session); +void rtp_session_set_jitter_compensation(RtpSession *session, int milisec); +void rtp_session_enable_adaptive_jitter_compensation(RtpSession *session, gboolean val); +gboolean rtp_session_adaptive_jitter_compensation_enabled(RtpSession *session); +void rtp_session_set_time_jump_limit(RtpSession *session, gint miliseconds); +int rtp_session_set_local_addr(RtpSession *session,const gchar *addr, gint port); +gint rtp_session_set_remote_addr(RtpSession *session,const gchar *addr, gint port); +/* alternatively to the set_remote_addr() and set_local_addr(), an application can give +a valid socket (potentially connect()ed )to be used by the RtpSession */ +void rtp_session_set_sockets(RtpSession *session, gint rtpfd, gint rtcpfd); +int rtp_session_set_payload_type(RtpSession *session, int paytype); +int rtp_session_get_payload_type(RtpSession *session); +int rtp_session_set_payload_type_with_string (RtpSession * session, const char * mime); +/*low level recv and send functions */ +mblk_t * rtp_session_recvm_with_ts (RtpSession * session, guint32 user_ts); +mblk_t * rtp_session_create_packet(RtpSession *session,gint header_size, const char *payload, gint payload_size); +mblk_t * rtp_session_create_packet_with_data(RtpSession *session, char *payload, gint payload_size, void (*freefn)(void*)); +mblk_t * rtp_session_create_packet_in_place(RtpSession *session,char *buffer, gint size, void (*freefn)(void*) ); +gint rtp_session_sendm_with_ts (RtpSession * session, mblk_t *mp, guint32 userts); +/* high level recv and send functions */ +gint rtp_session_recv_with_ts(RtpSession *session, gchar *buffer, gint len, guint32 time, gint *have_more); +gint rtp_session_send_with_ts(RtpSession *session, const gchar *buffer, gint len, guint32 userts); + + +guint32 rtp_session_get_current_send_ts(RtpSession *session); +guint32 rtp_session_get_current_recv_ts(RtpSession *session); +void rtp_session_flush_sockets(RtpSession *session); +void rtp_session_reset(RtpSession *session); +void rtp_session_destroy(RtpSession *session); + +#define rtp_session_get_stats(session) (&(session)->stats) +#define rtp_session_reset_stats(session) memset(&(session)->stats,0,sizeof(rtp_stats_t)) +#define rtp_session_set_data(session,data) (session)->user_data=(data) +#define rtp_session_get_data(session,data) ((session)->user_data) + +#define rtp_session_max_buf_size_set(session,bufsize) (session)->max_buf_size=(bufsize) + +/* in use with the scheduler to convert a timestamp in scheduler time unit (ms) */ +guint32 rtp_session_ts_to_time(RtpSession *session,guint32 timestamp); +guint32 rtp_session_time_to_ts(RtpSession *session, gint time); +/* this function aims at simulating senders with "imprecise" clocks, resulting in +rtp packets sent with timestamp uncorrelated with the system clock . +This is only availlable to sessions working with the oRTP scheduler */ +void rtp_session_make_time_distorsion(RtpSession *session, gint milisec); + +/*RTCP functions */ +void rtp_session_set_source_description(RtpSession *session, const gchar *cname, + const gchar *name, const gchar *email, const gchar *phone, + const gchar *loc, const gchar *tool, const gchar *note); +void rtp_session_add_contributing_source(RtpSession *session, guint32 csrc, + const gchar *cname, const gchar *name, const gchar *email, const gchar *phone, + const gchar *loc, const gchar *tool, const gchar *note); +void rtp_session_remove_contributing_sources(RtpSession *session, guint32 csrc); +mblk_t* rtp_session_create_rtcp_sdes_packet(RtpSession *session); + + +/* packet api */ +/* the first argument is a mblk_t. The header is supposed to be not splitted */ +#define rtp_set_markbit(mp,value) ((rtp_header_t*)((mp)->b_rptr))->markbit=(value) +#define rtp_set_seqnumber(mp,seq) ((rtp_header_t*)((mp)->b_rptr))->seq_number=(seq) +#define rtp_set_timestamp(mp,ts) ((rtp_header_t*)((mp)->b_rptr))->timestamp=(ts) +#define rtp_set_ssrc(mp,_ssrc) ((rtp_header_t*)((mp)->b_rptr))->ssrc=(_ssrc) +void rtp_add_csrc(mblk_t *mp,guint32 csrc); +#define rtp_set_payload_type(mp,pt) ((rtp_header_t*)((mp)->b_rptr))->paytype=(pt) + + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpsignaltable.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpsignaltable.c new file mode 100644 index 00000000..35b19ae3 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpsignaltable.c @@ -0,0 +1,98 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + + +#include <rtpsession.h> +#include "utils.h" + + +void rtp_signal_table_init(RtpSignalTable *table,RtpSession *session, char *signal_name) +{ + memset(table,0,sizeof(RtpSignalTable)); + table->session=session; + table->signal_name=signal_name; + session->signal_tables=o_list_append(session->signal_tables,(gpointer)table); +} + +int rtp_signal_table_add(RtpSignalTable *table,RtpCallback cb, gpointer user_data) +{ + gint i; + + for (i=0;i<RTP_CALLBACK_TABLE_MAX_ENTRIES;i++){ + if (table->callback[i]==NULL){ + table->callback[i]=cb; + table->user_data[i]=user_data; + table->count++; + return 0; + } + } + return -1; +} + +void rtp_signal_table_emit(RtpSignalTable *table) +{ + gint i,c; + + for (i=0,c=0;c<table->count;i++){ + if (table->callback[i]!=NULL){ + c++; /*I like it*/ + table->callback[i](table->session,table->user_data[i]); + } + } +} + +void rtp_signal_table_emit2(RtpSignalTable *table, gpointer arg) +{ + gint i,c; + + for (i=0,c=0;c<table->count;i++){ + if (table->callback[i]!=NULL){ + c++; /*I like it*/ + table->callback[i](table->session,arg,table->user_data[i]); + } + } +} + +void rtp_signal_table_emit3(RtpSignalTable *table, gpointer arg1, gpointer arg2) +{ + gint i,c; + + for (i=0,c=0;c<table->count;i++){ + if (table->callback[i]!=NULL){ + c++; /*I like it*/ + table->callback[i](table->session,arg1,arg2,table->user_data[i]); + } + } +} + +int rtp_signal_table_remove_by_callback(RtpSignalTable *table,RtpCallback cb) +{ + gint i; + + for (i=0;i<RTP_CALLBACK_TABLE_MAX_ENTRIES;i++){ + if (table->callback[i]==cb){ + table->callback[i]=NULL; + table->user_data[i]=NULL; + table->count--; + return 0; + } + } + return -1; +} diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpsignaltable.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpsignaltable.h new file mode 100644 index 00000000..c6cbe960 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtpsignaltable.h @@ -0,0 +1,47 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#define RTP_CALLBACK_TABLE_MAX_ENTRIES 5 + +typedef void (*RtpCallback)(struct _RtpSession *, ...); + +struct _RtpSignalTable +{ + RtpCallback callback[RTP_CALLBACK_TABLE_MAX_ENTRIES]; + gpointer user_data[RTP_CALLBACK_TABLE_MAX_ENTRIES]; + struct _RtpSession *session; + const char *signal_name; + gint count; +}; + +typedef struct _RtpSignalTable RtpSignalTable; + +void rtp_signal_table_init(RtpSignalTable *table,struct _RtpSession *session, char *signal_name); + +int rtp_signal_table_add(RtpSignalTable *table,RtpCallback cb, gpointer user_data); + +void rtp_signal_table_emit(RtpSignalTable *table); + +/* emit but with a second arg */ +void rtp_signal_table_emit2(RtpSignalTable *table, gpointer arg); + +/* emit but with a third arg */ +void rtp_signal_table_emit3(RtpSignalTable *table, gpointer arg1, gpointer arg2); + +int rtp_signal_table_remove_by_callback(RtpSignalTable *table,RtpCallback cb); diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtptimer.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtptimer.c new file mode 100644 index 00000000..6ac57e72 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtptimer.c @@ -0,0 +1,32 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "rtptimer.h" + +void rtp_timer_set_interval(RtpTimer *timer, struct timeval *interval) +{ + if (timer->state==RTP_TIMER_RUNNING){ + g_warning("Cannot change timer interval while it is running.\n"); + return; + } + timer->interval.tv_sec=interval->tv_sec; + timer->interval.tv_usec=interval->tv_usec; +} + + diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtptimer.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtptimer.h new file mode 100644 index 00000000..081e0892 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/rtptimer.h @@ -0,0 +1,52 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef RTPTIMER_H +#define RTPTIMER_H + +#ifndef _WIN32 +#include <sys/time.h> +#else +#include <time.h> +#include "winsock2.h" +#endif + +#include <rtpport.h> + + +typedef void (*RtpTimerFunc)(void); + +struct _RtpTimer +{ + gint state; +#define RTP_TIMER_RUNNING 1 +#define RTP_TIMER_STOPPED 0 + RtpTimerFunc timer_init; + RtpTimerFunc timer_do; + RtpTimerFunc timer_uninit; + struct timeval interval; +}; + +typedef struct _RtpTimer RtpTimer; + +void rtp_timer_set_interval(RtpTimer *timer, struct timeval *interval); + +extern RtpTimer posix_timer; + +#endif diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/scheduler.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/scheduler.c new file mode 100644 index 00000000..17ff6748 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/scheduler.c @@ -0,0 +1,235 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _WIN32 /* do not include ortp-config.h when we are on win32 */ + #include <rtpport.h> + #include <sched.h> + #include <unistd.h> + #include <errno.h> +#else + #include "ortp-config-win32.h" +#endif + + + +#include "scheduler.h" + +// To avoid warning during compile +extern void rtp_session_process (RtpSession * session, guint32 time, RtpScheduler *sched); + + +void rtp_scheduler_init(RtpScheduler *sched) +{ + sched->list=0; + sched->time_=0; + /* default to the posix timer */ + rtp_scheduler_set_timer(sched,&posix_timer); + sched->lock=g_mutex_new(); + //sched->unblock_select_mutex=g_mutex_new(); + sched->unblock_select_cond=g_cond_new(); + sched->max_sessions=sizeof(SessionSet)*8; + session_set_init(&sched->all_sessions); + sched->all_max=0; + session_set_init(&sched->r_sessions); + sched->r_max=0; + session_set_init(&sched->w_sessions); + sched->w_max=0; + session_set_init(&sched->e_sessions); + sched->e_max=0; +} + +RtpScheduler * rtp_scheduler_new() +{ + RtpScheduler *sched=g_malloc(sizeof(RtpScheduler)); + memset(sched,0,sizeof(RtpScheduler)); + rtp_scheduler_init(sched); + return sched; +} + +void rtp_scheduler_set_timer(RtpScheduler *sched,RtpTimer *timer) +{ + if (sched->thread_running){ + g_warning("Cannot change timer while the scheduler is running !!"); + return; + } + sched->timer=timer; + /* report the timer increment */ + sched->timer_inc=(timer->interval.tv_usec/1000) + (timer->interval.tv_sec*1000); +} + +void rtp_scheduler_start(RtpScheduler *sched) +{ + if (sched->thread_running==0){ + sched->thread_running=1; + g_mutex_lock(sched->lock); + sched->thread=g_thread_create((GThreadFunc)rtp_scheduler_schedule,(gpointer)sched,TRUE,NULL); + g_cond_wait(sched->unblock_select_cond,sched->lock); + g_mutex_unlock(sched->lock); + } + else g_warning("Scheduler thread already running."); + +} +void rtp_scheduler_stop(RtpScheduler *sched) +{ + if (sched->thread_running==1) + { + sched->thread_running=0; + g_thread_join(sched->thread); + } + else g_warning("Scheduler thread is not running."); +} + +void rtp_scheduler_destroy(RtpScheduler *sched) +{ + if (sched->thread_running) rtp_scheduler_stop(sched); + g_mutex_free(sched->lock); + //g_mutex_free(sched->unblock_select_mutex); + g_cond_free(sched->unblock_select_cond); + g_free(sched); +} + +gpointer rtp_scheduler_schedule(gpointer psched) +{ + RtpScheduler *sched=(RtpScheduler*) psched; + RtpTimer *timer=sched->timer; + RtpSession *current; + int err; + + /* try to get the real time priority by getting root*/ +#ifndef _WIN32 +#ifdef HAVE_SETEUID + err=seteuid(0); +#else + err=setuid(0); +#endif + if (err<0) g_message("Could not get root euid: %s",strerror(errno)); +#endif + g_message("scheduler: trying to reach real time kernel scheduling..."); + + /* take this lock to prevent the thread to start until g_thread_create() returns + because we need sched->thread to be initialized */ + g_mutex_lock(sched->lock); + g_cond_signal(sched->unblock_select_cond); /* unblock the starting thread */ + g_mutex_unlock(sched->lock); + g_thread_set_priority(sched->thread,G_THREAD_PRIORITY_HIGH); + timer->timer_init(); + while(sched->thread_running) + { + /* do the processing here: */ + + g_mutex_lock(sched->lock); + + current=sched->list; + /* processing all scheduled rtp sessions */ + while (current!=NULL) + { + ortp_debug("scheduler: processing session=%p.\n",current); + rtp_session_process(current,sched->time_,sched); + current=current->next; + } + /* wake up all the threads that are sleeping in _select() */ + g_cond_broadcast(sched->unblock_select_cond); + g_mutex_unlock(sched->lock); + + /* now while the scheduler is going to sleep, the other threads can compute their + result mask and see if they have to leave, or to wait for next tick*/ + //g_message("scheduler: sleeping."); + timer->timer_do(); + sched->time_+=sched->timer_inc; + } + /* when leaving the thread, stop the timer */ + timer->timer_uninit(); + return NULL; +} + +void rtp_scheduler_add_session(RtpScheduler *sched, RtpSession *session) +{ + RtpSession *oldfirst; + int i; + if (session->flags & RTP_SESSION_IN_SCHEDULER){ + /* the rtp session is already scheduled, so return silently */ + return; + } + rtp_scheduler_lock(sched); + /* enqueue the session to the list of scheduled sessions */ + oldfirst=sched->list; + sched->list=session; + session->next=oldfirst; + if (sched->max_sessions==0){ + g_error("rtp_scheduler_add_session: max_session=0 !"); + } + /* find a free pos in the session mask*/ + for (i=0;i<sched->max_sessions;i++){ + if (!ORTP_FD_ISSET(i,&sched->all_sessions.rtpset)){ + session->mask_pos=i; + session_set_set(&sched->all_sessions,session); + /* make a new session scheduled not blockable if it has not started*/ + if (session->flags & RTP_SESSION_RECV_NOT_STARTED) + session_set_set(&sched->r_sessions,session); + if (session->flags & RTP_SESSION_SEND_NOT_STARTED) + session_set_set(&sched->w_sessions,session); + if (i>sched->all_max){ + sched->all_max=i; + } + break; + } + } + + rtp_session_set_flag(session,RTP_SESSION_IN_SCHEDULER); + rtp_scheduler_unlock(sched); +} + +void rtp_scheduler_remove_session(RtpScheduler *sched, RtpSession *session) +{ + RtpSession *tmp; + int cond=1; + g_return_if_fail(session!=NULL); + if (!(session->flags & RTP_SESSION_IN_SCHEDULER)){ + /* the rtp session is not scheduled, so return silently */ + return; + } + + rtp_scheduler_lock(sched); + tmp=sched->list; + if (tmp==session){ + sched->list=tmp->next; + rtp_session_unset_flag(session,RTP_SESSION_IN_SCHEDULER); + session_set_clr(&sched->all_sessions,session); + rtp_scheduler_unlock(sched); + return; + } + /* go the position of session in the list */ + while(cond){ + if (tmp!=NULL){ + if (tmp->next==session){ + tmp->next=tmp->next->next; + cond=0; + } + else tmp=tmp->next; + }else { + /* the session was not found ! */ + g_warning("rtp_scheduler_remove_session: the session was not found in the scheduler list!"); + cond=0; + } + } + rtp_session_unset_flag(session,RTP_SESSION_IN_SCHEDULER); + /* delete the bit in the mask */ + session_set_clr(&sched->all_sessions,session); + rtp_scheduler_unlock(sched); +} diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/scheduler.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/scheduler.h new file mode 100644 index 00000000..91cde6a9 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/scheduler.h @@ -0,0 +1,70 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef SCHEDULER_H +#define SCHEDULER_H + +#include <rtpsession.h> +#include <sessionset.h> +#include "rtptimer.h" +#include "port_fct.h" + + +struct _RtpScheduler { + + RtpSession *list; /* list of scheduled sessions*/ + SessionSet all_sessions; /* mask of scheduled sessions */ + gint all_max; /* the highest pos in the all mask */ + SessionSet r_sessions; /* mask of sessions that have a recv event */ + gint r_max; + SessionSet w_sessions; /* mask of sessions that have a send event */ + gint w_max; + SessionSet e_sessions; /* mask of session that have error event */ + gint e_max; + gint max_sessions; /* the number of position in the masks */ + /* GMutex *unblock_select_mutex; */ + GCond *unblock_select_cond; + GMutex *lock; + GThread *thread; + gint thread_running; + struct _RtpTimer *timer; + guint32 time_; /*number of miliseconds elapsed since the start of the thread */ + guint32 timer_inc; /* the timer increment in milisec */ +}; + +typedef struct _RtpScheduler RtpScheduler; + +RtpScheduler * rtp_scheduler_new(); +void rtp_scheduler_set_timer(RtpScheduler *sched,RtpTimer *timer); +void rtp_scheduler_start(RtpScheduler *sched); +void rtp_scheduler_stop(RtpScheduler *sched); +void rtp_scheduler_destroy(RtpScheduler *sched); + +void rtp_scheduler_add_session(RtpScheduler *sched, RtpSession *session); +void rtp_scheduler_remove_session(RtpScheduler *sched, RtpSession *session); + +gpointer rtp_scheduler_schedule(gpointer sched); + +#define rtp_scheduler_lock(sched) g_mutex_lock((sched)->lock) +#define rtp_scheduler_unlock(sched) g_mutex_unlock((sched)->lock) + +/* void rtp_scheduler_add_set(RtpScheduler *sched, SessionSet *set); */ + +RtpScheduler * ortp_get_scheduler(); +#endif diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/sessionset.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/sessionset.c new file mode 100644 index 00000000..7b5ad921 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/sessionset.c @@ -0,0 +1,187 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <ortp.h> +#include <sessionset.h> +#include "scheduler.h" + +/** + *session_set_init: + *@ss: a SessionSet statically allocated. + * + * Initializes a session set. It is unusefull to call this function on a session set object + * returned by session_set_new(). + * +**/ + + +/** + *session_set_new: + * + * Allocates and initialize a new empty session set. + * + *Returns: the session set. +**/ +SessionSet * session_set_new() +{ + SessionSet *set=g_malloc(sizeof(SessionSet)); + session_set_init(set); + return set; +} + + +/** + *session_set_destroy: + *@set: a SessionSet + * Destroys a session set. + * +**/ + +void session_set_destroy(SessionSet *set) +{ + g_free(set); +} + +gint session_set_and(SessionSet *sched_set, gint maxs, SessionSet *user_set, SessionSet *result_set) +{ + guint32 *mask1,*mask2,*mask3; + gint i=0; + gint j,ret=0; + mask1=(guint32*)&sched_set->rtpset; + mask2=(guint32*)&user_set->rtpset; + mask3=(guint32*)&result_set->rtpset; + while(i<maxs+1){ + *mask3=(*mask1) & (*mask2); /* computes the AND between the two masks*/ + /* and unset the sessions that have been found from the sched_set */ + *mask1=(*mask1) & (~(*mask3)); + if ((*mask3)!=0){ + for (j=0;j<32;j++){ + if ( ((*mask3)>>j) & 1){ + ret++; + } + } + } + i+=32; + mask1++; + mask2++; + mask3++; + } + //printf("session_set_and: ret=%i\n",ret); + return ret; +} + +/** + *session_set_select: + *@recvs: a set of rtp sessions to be watched for read events + *@sends: a set of rtp sessions to be watched for write events + *@errors: a set of rtp sessions to be watched for errors + * + * This function performs similarly as libc select() function, but performs on #RtpSession + * instead of file descriptors. + * session_set_select() suspends the calling process until some events arrive on one of the + * three sets passed in argument. Two of the sets can be NULL. + * The first set @recvs is interpreted as a set of RtpSession waiting for receive events: + * a new buffer (perhaps empty) is availlable on one or more sessions of the set, or the last + * receive operation with rtp_session_recv_with_ts() would have finished if it were in + * blocking mode. + * The second set is interpreted as a set of RtpSession waiting for send events, i.e. the last + * rtp_session_send_with_ts() call on a session would have finished if it were in blocking mode. + * + * When some events arrived on some of sets, then the function returns and sets are changed + * to indicate the sessions where events happened. + * Sessions can be added to sets using session_set_set(), a session has to be tested to be + * part of a set using session_set_is_set(). + * + *Returns: the number of sessions on which the selected events happened. +**/ +int session_set_select(SessionSet *recvs, SessionSet *sends, SessionSet *errors) +{ + gint ret=0,bits; + SessionSet temp; + RtpScheduler *sched=ortp_get_scheduler(); + + /*lock the scheduler to not read the masks while they are being modified by the scheduler*/ + rtp_scheduler_lock(sched); + + while(1){ + /* computes the SessionSet intersection (in the other words mask intersection) between + the mask given by the user and scheduler masks */ + if (recvs!=NULL){ + bits=session_set_and(&sched->r_sessions,sched->all_max,recvs,&temp); + if (bits>0){ + ret+=bits; + /* copy the result set in the given user set */ + session_set_copy(recvs,&temp); + } + } + if (sends!=NULL){ + bits=session_set_and(&sched->w_sessions,sched->all_max,sends,&temp); + if (bits>0){ + ret+=bits; + /* copy the result set in the given user set */ + session_set_copy(sends,&temp); + } + } + if (errors!=NULL){ + bits=session_set_and(&sched->e_sessions,sched->all_max,errors,&temp); + if (bits>0){ + ret+=bits; + /* copy the result set in the given user set */ + session_set_copy(errors,&temp); + } + } + if (ret>0){ + /* there are set file descriptors, return immediately */ + //printf("There are %i sessions set, returning.\n",ret); + rtp_scheduler_unlock(sched); + return ret; + } + //printf("There are %i sessions set.\n",ret); + /* else we wait until the next loop of the scheduler*/ + g_cond_wait(sched->unblock_select_cond,sched->lock); + } + + return -1; +} + +/** + *session_set_set: + *@ss: a set (#SessionSet object) + *@rtpsession: a rtp session + * + * This macro adds rtp session @_session to set @_set. +**/ + +/** + *session_set_is_set: + *@ss: a set (#SessionSet object) + *@rtpsession: a rtp session + * + * This macro tests if @_session is part of @_set. 1 is returned if true, 0 else. +**/ + +/** + *session_set_clr: + *@ss: a set of sessions. + *@rtpsession: a rtp session. + * + * Removes the @_session from the _set. + * + * +**/ diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/sessionset.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/sessionset.h new file mode 100644 index 00000000..623b9d10 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/sessionset.h @@ -0,0 +1,102 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef SESSIONSET_H +#define SESSIONSET_H + + +#include <rtpsession.h> + + +#ifndef _WIN32 +/* UNIX */ +#include <sys/time.h> +#include <sys/types.h> +#include <unistd.h> + +#define ORTP_FD_SET(d, s) FD_SET(d, s) +#define ORTP_FD_CLR(d, s) FD_CLR(d, s) +#define ORTP_FD_ISSET(d, s) FD_ISSET(d, s) +#define ORTP_FD_ZERO(s) FD_ZERO(s) + +typedef fd_set ortp_fd_set; + + +#else +/* WIN32 */ + +#define ORTP_FD_ZERO(s) \ + do { \ + unsigned int __i; \ + ortp_fd_set *__arr = (s); \ + for (__i = 0; __i < sizeof (ortp_fd_set) / sizeof (ortp__fd_mask); ++__i) \ + ORTP__FDS_BITS (__arr)[__i] = 0; \ + } while (0) +#define ORTP_FD_SET(d, s) (ORTP__FDS_BITS (s)[ORTP__FDELT(d)] |= ORTP__FDMASK(d)) +#define ORTP_FD_CLR(d, s) (ORTP__FDS_BITS (s)[ORTP__FDELT(d)] &= ~ORTP__FDMASK(d)) +#define ORTP_FD_ISSET(d, s) ((ORTP__FDS_BITS (s)[ORTP__FDELT(d)] & ORTP__FDMASK(d)) != 0) + + + +/* The fd_set member is required to be an array of longs. */ +typedef long int ortp__fd_mask; + + +/* Number of bits per word of `fd_set' (some code assumes this is 32). */ +#define ORTP__FD_SETSIZE 1024 + +/* It's easier to assume 8-bit bytes than to get CHAR_BIT. */ +#define ORTP__NFDBITS (8 * sizeof (ortp__fd_mask)) +#define ORTP__FDELT(d) ((d) / ORTP__NFDBITS) +#define ORTP__FDMASK(d) ((ortp__fd_mask) 1 << ((d) % ORTP__NFDBITS)) + + +/* fd_set for select and pselect. */ +typedef struct + { + ortp__fd_mask fds_bits[ORTP__FD_SETSIZE / ORTP__NFDBITS]; +# define ORTP__FDS_BITS(set) ((set)->fds_bits) + } ortp_fd_set; + + +#endif /*end WIN32*/ + +struct _SessionSet +{ + ortp_fd_set rtpset; +}; + + +typedef struct _SessionSet SessionSet; + +SessionSet * session_set_new(); +#define session_set_init(ss) ORTP_FD_ZERO(&(ss)->rtpset) +#define session_set_set(ss,rtpsession) ORTP_FD_SET((rtpsession)->mask_pos,&(ss)->rtpset) +#define session_set_is_set(ss,rtpsession) ORTP_FD_ISSET((rtpsession)->mask_pos,&(ss)->rtpset) +#define session_set_clr(ss,rtpsession) ORTP_FD_CLR((rtpsession)->mask_pos,&(ss)->rtpset) + +#define session_set_copy(dest,src) memcpy(&(dest)->rtpset,&(src)->rtpset,sizeof(ortp_fd_set)) + +void session_set_destroy(SessionSet *set); + + +int session_set_select(SessionSet *recvs, SessionSet *sends, SessionSet *errors); + + +#endif diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/str_utils.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/str_utils.c new file mode 100644 index 00000000..813ea707 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/str_utils.c @@ -0,0 +1,297 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <rtpport.h> +#include <rtp.h> +#include <str_utils.h> + +#include <stdio.h> + +void qinit(queue_t *q){ + mblk_init(&q->_q_first); + mblk_init(&q->_q_last); + q->_q_first.b_next=&q->_q_last; + q->_q_last.b_prev=&q->_q_first; + q->q_mcount=0; +} + +void mblk_init(mblk_t *mp) +{ + mp->b_cont=mp->b_prev=mp->b_next=NULL; + mp->b_rptr=mp->b_wptr=NULL; +} + +mblk_t *allocb(int size, int pri) +{ + mblk_t *mp; + dblk_t *datab; + gchar *buf; + + mp=g_malloc(sizeof(mblk_t)); + mblk_init(mp); + datab=g_malloc(sizeof(dblk_t)); + + buf=g_malloc(size); + + datab->db_base=buf; + datab->db_lim=buf+size; + datab->ref_count=1; + datab->db_freefn=g_free; + + mp->b_datap=datab; + mp->b_rptr=mp->b_wptr=buf; + mp->b_next=mp->b_prev=mp->b_cont=NULL; + return mp; +} + +mblk_t *allocb_with_buf(char *buf, int size, int pri, void (*freefn)(void*) ) +{ + mblk_t *mp; + dblk_t *datab; + + mp=g_malloc(sizeof(mblk_t)); + mblk_init(mp); + datab=g_malloc(sizeof(dblk_t)); + + + datab->db_base=buf; + datab->db_lim=buf+size; + datab->ref_count=1; + datab->db_freefn=freefn; + + mp->b_datap=datab; + mp->b_rptr=mp->b_wptr=buf; + mp->b_next=mp->b_prev=mp->b_cont=NULL; + return mp; +} + + +void freeb(mblk_t *mp) +{ + g_return_if_fail(mp->b_datap!=NULL); + g_return_if_fail(mp->b_datap->db_base!=NULL); + + mp->b_datap->ref_count--; + if (mp->b_datap->ref_count==0) + { + if (mp->b_datap->db_freefn!=NULL) + mp->b_datap->db_freefn(mp->b_datap->db_base); + g_free(mp->b_datap); + } + g_free(mp); +} + +void freemsg(mblk_t *mp) +{ + mblk_t *tmp1,*tmp2; + tmp1=mp; + while(tmp1!=NULL) + { + tmp2=tmp1->b_cont; + freeb(tmp1); + tmp1=tmp2; + } +} + +mblk_t *dupb(mblk_t *mp) +{ + mblk_t *newm; + g_return_val_if_fail(mp->b_datap!=NULL,NULL); + g_return_val_if_fail(mp->b_datap->db_base!=NULL,NULL); + + mp->b_datap->ref_count++; + newm=g_malloc(sizeof(mblk_t)); + mblk_init(newm); + newm->b_datap=mp->b_datap; + newm->b_rptr=mp->b_rptr; + newm->b_wptr=mp->b_wptr; + return newm; +} + +/* duplicates a complex mblk_t */ +mblk_t *dupmsg(mblk_t* m) +{ + mblk_t *newm=NULL,*mp,*prev; + prev=newm=dupb(m); + m=m->b_cont; + while (m!=NULL){ + mp=dupb(m); + prev->b_cont=mp; + prev=mp; + m=m->b_cont; + } + return newm; +} + +void putq(queue_t *q,mblk_t *mp) +{ + q->_q_last.b_prev->b_next=mp; + mp->b_prev=q->_q_last.b_prev; + mp->b_next=&q->_q_last; + q->_q_last.b_prev=mp; + q->q_mcount++; +} + +mblk_t *getq(queue_t *q) +{ + mblk_t *tmp; + tmp=q->_q_first.b_next; + if (tmp==&q->_q_last) return NULL; + q->_q_first.b_next=tmp->b_next; + tmp->b_next->b_prev=&q->_q_first; + tmp->b_prev=NULL; + tmp->b_next=NULL; + q->q_mcount--; + return tmp; +} + +/* insert mp in q just before emp */ +void insq(queue_t *q,mblk_t *emp, mblk_t *mp) +{ + if (emp==NULL){ + putq(q,mp); + return; + } + q->q_mcount++; + emp->b_prev->b_next=mp; + mp->b_prev=emp->b_prev; + emp->b_prev=mp; + mp->b_next=emp; +} + +void remq(queue_t *q, mblk_t *mp){ + q->q_mcount--; + mp->b_prev->b_next=mp->b_next; + mp->b_next->b_prev=mp->b_prev; + mp->b_next=NULL; + mp->b_prev=NULL; +} + +/* remove and free all messages in the q */ +void flushq(queue_t *q, int how) +{ + mblk_t *mp; + + while ((mp=getq(q))!=NULL) + { + freemsg(mp); + } +} + +gint msgdsize(mblk_t *mp) +{ + gint msgsize=0; + while(mp!=NULL){ + msgsize+=mp->b_wptr-mp->b_rptr; + mp=mp->b_cont; + } + return msgsize; +} + +mblk_t * msgpullup(mblk_t *mp,int len) +{ + mblk_t *newm; + gint msgsize=msgdsize(mp); + gint rlen; + gint mlen; + + + if ((len==-1) || (len>msgsize)) len=msgsize; + rlen=len; + newm=allocb(len,BPRI_MED); + + while(mp!=NULL){ + mlen=mp->b_wptr-mp->b_rptr; + if (rlen>=mlen) + { + memcpy(newm->b_wptr,mp->b_rptr,mlen); + rlen-=mlen; + newm->b_wptr+=mlen; + } + else /* rlen < mlen */ + { + memcpy(newm->b_wptr,mp->b_rptr,rlen); + newm->b_wptr+=rlen; + + /* put the end of the original message at the end of the new */ + newm->b_cont=dupmsg(mp); + newm->b_cont->b_rptr+=rlen; + return newm; + } + mp=mp->b_cont; + } + return newm; +} + + +mblk_t *copyb(mblk_t *mp) +{ + mblk_t *newm; + gint len=mp->b_wptr-mp->b_rptr; + newm=allocb(len,BPRI_MED); + memcpy(newm->b_wptr,mp->b_rptr,len); + newm->b_wptr+=len; + return newm; +} + +mblk_t *copymsg(mblk_t *mp) +{ + mblk_t *newm=0,*m; + m=newm=copyb(mp); + mp=mp->b_cont; + while(mp!=NULL){ + m->b_cont=copyb(mp); + m=m->b_cont; + mp=mp->b_cont; + } + return newm; +} + +mblk_t * appendb(mblk_t *mp, const char *data, int size, gboolean pad){ + gint padcnt=0; + int i; + if (pad){ + padcnt= (gint)(4L-( (long)(mp->b_wptr+size) % 4L)) % 4L; + } + if ((mp->b_wptr + size +padcnt) > (char*)mp->b_datap->db_lim){ + /* buffer is not large enough: append a new block (with the same size ?)*/ + int plen=(char*)mp->b_datap->db_lim - (char*) mp->b_datap->db_base; + mp->b_cont=allocb(MAX(plen,size),0); + mp=mp->b_cont; + } + if (size) memcpy(mp->b_wptr,data,size); + mp->b_wptr+=size; + for (i=0;i<padcnt;i++){ + mp->b_wptr[0]=0; + mp->b_wptr++; + } + return mp; +} + +void msgappend(mblk_t *mp, const char *data, int size, gboolean pad){ + while(mp->b_cont!=NULL) mp=mp->b_cont; + appendb(mp,data,size,pad); +} + +mblk_t *concatb(mblk_t *mp, mblk_t *newm){ + while (mp->b_cont!=NULL) mp=mp->b_cont; + mp->b_cont=newm; + while(newm->b_cont!=NULL) newm=newm->b_cont; + return newm; +} diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/str_utils.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/str_utils.h new file mode 100644 index 00000000..b605fc2a --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/str_utils.h @@ -0,0 +1,118 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef STR_UTILS_H +#define STR_UTILS_H + + +#include <rtpport.h> + + +typedef struct msgb +{ + struct msgb *b_prev; + struct msgb *b_next; + struct msgb *b_cont; + struct datab *b_datap; + char *b_rptr; + char *b_wptr; +} mblk_t; + +typedef struct datab +{ + char *db_base; + char *db_lim; + void (*db_freefn)(void*); + guint ref_count; +} dblk_t; + +typedef struct _queue +{ + mblk_t _q_first; + mblk_t _q_last; + gint q_mcount; /*number of packet in the q */ +} queue_t; + +#ifdef __cplusplus +extern "C" { +#endif + +void qinit(queue_t *q); + +void putq(queue_t *q, mblk_t *m); +mblk_t * getq(queue_t *q); + +void insq(queue_t *q,mblk_t *emp, mblk_t *mp); + +void remq(queue_t *q, mblk_t *mp); + +void mblk_init(mblk_t *mp); + +/* allocates a mblk_t, that points to a datab_t, that points to a buffer of size size. */ +mblk_t *allocb(gint size,gint unused); +#define BPRI_MED 0 + +/* allocates a mblk_t, that points to a datab_t, that points to buf; buf will be freed using freefn */ +mblk_t *allocb_with_buf(char *buf, int size, int pri, void (*freefn)(void*) ); + +/* frees a mblk_t, and if the datab ref_count is 0, frees it and the buffer too */ +void freeb(mblk_t *m); + +/* frees recursively (follow b_cont) a mblk_t, and if the datab +ref_count is 0, frees it and the buffer too */ +void freemsg(mblk_t *mp); + +/* duplicates a mblk_t , buffer is not duplicated*/ +mblk_t *dupb(mblk_t *m); + +/* duplicates a complex mblk_t, buffer is not duplicated */ +mblk_t *dupmsg(mblk_t* m); + +/* remove and free all messages in the q */ +#define FLUSHALL 0 +void flushq(queue_t *q, int how); + +/* returns the size of data of a message */ +gint msgdsize(mblk_t *mp); + +/* concatenates all fragment of a complex message ( a new message is returned, old is untouched*/ +mblk_t * msgpullup(mblk_t *mp,int len); + +/* duplicates a single message, but with buffer included */ +mblk_t *copyb(mblk_t *mp); + +/* duplicates a complex message with buffer included */ +mblk_t *copymsg(mblk_t *mp); + +mblk_t * appendb(mblk_t *mp, const char *data, int size, gboolean pad); +void msgappend(mblk_t *mp, const char *data, int size, gboolean pad); + +mblk_t *concatb(mblk_t *mp, mblk_t *newm); + +#define qempty(q) (&(q)->_q_last==(q)->_q_first.b_next) +#define qfirst(q) ((q)->_q_first.b_next!=&(q)->_q_last ? (q)->_q_first.b_next : NULL) +#define qbegin(q) ((q)->_q_first.b_next) +#define qlast(q) ((q)->_q_last.b_prev!=&(q)->_q_first ? (q)->_q_last.b_prev : NULL) +#define qend(q,mp) ((mp)==&(q)->_q_first || ((mp)==&(q)->_q_last)) +#define qnext(q,mp) ((mp)->b_next) +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/telephonyevents.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/telephonyevents.c new file mode 100644 index 00000000..884226ea --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/telephonyevents.c @@ -0,0 +1,338 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <telephonyevents.h> + + +PayloadType telephone_event={ + PAYLOAD_AUDIO_PACKETIZED, /*type */ + 8000, /*clock rate */ + 0, /* bytes per sample N/A */ + NULL, /* zero pattern N/A*/ + 0, /*pattern_length N/A */ + 0, /* normal_bitrate */ + "telephone-event", + 0 /*flags */ +}; + +/* tell if the session supports telephony events. For this the telephony events payload_type + must be present in the rtp profile used by the session */ +/** + *rtp_session_telephone_events_supported: + *@session : a rtp session + * + * Tells whether telephony events payload type is supported within the context of the rtp + * session. + * + *Returns: the payload type number used for telephony events if found, -1 if not found. +**/ +gint rtp_session_telephone_events_supported(RtpSession *session) +{ + /* search for a telephony event payload in the current profile */ + session->telephone_events_pt=rtp_profile_get_payload_number_from_mime(session->profile,"telephone-event"); + return session->telephone_events_pt; +} + + +/** + *rtp_session_create_telephone_event_packet: + *@session: a rtp session. + *@start: boolean to indicate if the marker bit should be set. + * + * Allocates a new rtp packet to be used to add named telephony events. The application can use + * then rtp_session_add_telephone_event() to add named events to the packet. + * Finally the packet has to be sent with rtp_session_sendm_with_ts(). + * + *Returns: a message block containing the rtp packet if successfull, NULL if the rtp session + *cannot support telephony event (because the rtp profile it is bound to does not include + *a telephony event payload type). +**/ +mblk_t *rtp_session_create_telephone_event_packet(RtpSession *session, int start) +{ + mblk_t *mp; + rtp_header_t *rtp; + + g_return_val_if_fail(session->telephone_events_pt!=-1,NULL); + + mp=allocb(RTP_FIXED_HEADER_SIZE+TELEPHONY_EVENTS_ALLOCATED_SIZE,BPRI_MED); + if (mp==NULL) return NULL; + rtp=(rtp_header_t*)mp->b_rptr; + rtp->version = 2; + rtp->markbit=start; + rtp->padbit = 0; + rtp->extbit = 0; + rtp->cc = 0; + rtp->ssrc = session->send_ssrc; + /* timestamp set later, when packet is sended */ + /*seq number set later, when packet is sended */ + + /*set the payload type */ + rtp->paytype=session->telephone_events_pt; + + /*copy the payload */ + mp->b_wptr+=RTP_FIXED_HEADER_SIZE; + return mp; +} + + +/** + *rtp_session_add_telephone_event: + *@session: a rtp session. + *@packet: a rtp packet as a #mblk_t + *@event: the event type as described in rfc2833, ie one of the TEV_ macros. + *@end: boolean to indicate if the end bit should be set. (end of tone) + *@volume: the volume of the telephony tone, as described in rfc2833 + *@duration:the duration of the telephony tone, in timestamp unit. + * + * Adds a named telephony event to a rtp packet previously allocated using + * rtp_session_create_telephone_event_packet(). + * + *Returns 0 on success. +**/ +gint rtp_session_add_telephone_event(RtpSession *session, + mblk_t *packet, guchar event, gint end, guchar volume, guint16 duration) +{ + mblk_t *mp=packet; + telephone_event_t *event_hdr; + + + /* find the place where to add the new telephony event to the packet */ + while(mp->b_cont!=NULL) mp=mp->b_cont; + /* see if we need to allocate a new mblk_t */ + if ( (long)mp->b_wptr >= (long) mp->b_datap->db_lim){ + mblk_t *newm=allocb(TELEPHONY_EVENTS_ALLOCATED_SIZE,BPRI_MED); + mp->b_cont=newm; + mp=mp->b_cont; + } + if (mp==NULL) return -1; + event_hdr=(telephone_event_t*)mp->b_wptr; + event_hdr->event=event; + event_hdr->R=0; + event_hdr->E=end; + event_hdr->volume=volume; + event_hdr->duration=htons(duration); + mp->b_wptr+=sizeof(telephone_event_t); + return 0; +} +/** + *rtp_session_send_dtmf: + *@session : a rtp session + *@dtmf : a character meaning the dtmf (ex: '1', '#' , '9' ...) + *@userts : the timestamp + * + * This functions creates telephony events packets for @dtmf and sends them. + * It uses rtp_session_create_telephone_event_packet() and + * rtp_session_add_telephone_event() to create them and finally + * rtp_session_sendm_with_ts() to send them. + * + *Returns: 0 if successfull, -1 if the session cannot support telephony events or if the dtmf + * given as argument is not valid. +**/ +gint rtp_session_send_dtmf(RtpSession *session, gchar dtmf, guint32 userts) +{ + mblk_t *m1,*m2,*m3; + int tev_type; + /* create the first telephony event packet */ + switch (dtmf){ + case '1': + tev_type=TEV_DTMF_1; + break; + case '2': + tev_type=TEV_DTMF_2; + break; + case '3': + tev_type=TEV_DTMF_3; + break; + case '4': + tev_type=TEV_DTMF_4; + break; + case '5': + tev_type=TEV_DTMF_5; + break; + case '6': + tev_type=TEV_DTMF_6; + break; + case '7': + tev_type=TEV_DTMF_7; + break; + case '8': + tev_type=TEV_DTMF_8; + break; + case '9': + tev_type=TEV_DTMF_9; + break; + case '*': + tev_type=TEV_DTMF_STAR; + break; + case '0': + tev_type=TEV_DTMF_0; + break; + case '#': + tev_type=TEV_DTMF_POUND; + break; + default: + g_warning("Bad dtmf: %c.",dtmf); + return -1; + } + + m1=rtp_session_create_telephone_event_packet(session,1); + if (m1==NULL) return -1; + rtp_session_add_telephone_event(session,m1,tev_type,0,0,160); + /* create a second packet */ + m2=rtp_session_create_telephone_event_packet(session,0); + if (m2==NULL) return -1; + rtp_session_add_telephone_event(session,m2,tev_type,0,0,320); + + /* create a third and final packet */ + m3=rtp_session_create_telephone_event_packet(session,0); + if (m3==NULL) return -1; + rtp_session_add_telephone_event(session,m3,tev_type,1,0,480); + + /* and now sends them */ + rtp_session_sendm_with_ts(session,m1,userts); + rtp_session_sendm_with_ts(session,m2,userts); + /* the last packet is sent three times in order to improve reliability*/ + m1=copymsg(m3); + m2=copymsg(m3); + /* NOTE: */ + /* we need to copymsg() instead of dupmsg() because the buffers are modified when + the packet is sended because of the host-to-network conversion of timestamp,ssrc, csrc, and + seq number. + It could be avoided by making a copy of the buffer when sending physically the packet, but + it add one more copy for every buffer. + Using iomapped socket, it is possible to avoid the user to kernel copy. + */ + rtp_session_sendm_with_ts(session,m3,userts); + rtp_session_sendm_with_ts(session,m1,userts); + rtp_session_sendm_with_ts(session,m2,userts); + return 0; +} + +/** + *rtp_session_read_telephone_event: + *@session: a rtp session from which telephony events are received. + *@packet: a rtp packet as a mblk_t. + *@tab: the address of a pointer. + * + * Reads telephony events from a rtp packet. *@tab points to the beginning of the event buffer. + * + *Returns: the number of events in the packet if successfull, 0 if the packet did not + * contain telephony events. +**/ +gint rtp_session_read_telephone_event(RtpSession *session, + mblk_t *packet,telephone_event_t **tab) +{ + int datasize; + gint num; + int i; + telephone_event_t *tev; + rtp_header_t *hdr=(rtp_header_t*)packet->b_rptr; + g_return_val_if_fail(packet->b_cont!=NULL,-1); + if (hdr->paytype!=session->telephone_events_pt) return 0; /* this is not tel ev.*/ + datasize=msgdsize(packet); + tev=*tab=(telephone_event_t*)packet->b_cont->b_rptr; + /* convert from network to host order what should be */ + num=datasize/sizeof(telephone_event_t); + for (i=0;i<num;i++) + { + tev[i].duration=ntohs(tev[i].duration); + } + return num; +} + + +static void notify_events_ended(RtpSession *session, telephone_event_t *events, int num){ + int i; + for (i=0;i<num;i++){ + if (events[i].E==1){ + rtp_signal_table_emit2(&session->on_telephone_event,(gpointer)(long)events[i].event); + } + } +} + +/* for high level telephony event callback */ +void rtp_session_check_telephone_events(RtpSession *session, mblk_t *m0) +{ + telephone_event_t *events,*evbuf; + int num; + int i; + mblk_t *mp; + rtp_header_t *hdr; + mblk_t *cur_tev; + + hdr=(rtp_header_t*)m0->b_rptr; + mp=m0->b_cont; + + num=(mp->b_wptr-mp->b_rptr)/sizeof(telephone_event_t); + events=(telephone_event_t*)mp->b_rptr; + + + if (hdr->markbit==1) + { + /* this is a start of new events. Store the event buffer for later use*/ + if (session->current_tev!=NULL) { + freemsg(session->current_tev); + session->current_tev=NULL; + } + session->current_tev=copymsg(m0); + /* handle the case where the events are short enough to end within the packet that has the marker bit*/ + notify_events_ended(session,events,num); + } + /* whatever there is a markbit set or not, we parse the packet and compare it to previously received one */ + cur_tev=session->current_tev; + if (cur_tev!=NULL) + { + /* first compare timestamp, they must be identical */ + if (((rtp_header_t*)cur_tev->b_rptr)->timestamp== + ((rtp_header_t*)m0->b_rptr)->timestamp) + { + evbuf=(telephone_event_t*)cur_tev->b_cont; + for (i=0;i<num;i++) + { + if (events[i].E==1) + { + /* update events that have ended */ + if (evbuf[i].E==0){ + evbuf[i].E=1; + /* this is a end of event, report it */ + rtp_signal_table_emit2(&session->on_telephone_event,(gpointer)(long)events[i].event); + } + } + } + } + else + { + /* timestamp are not identical: this is not the same events*/ + if (session->current_tev!=NULL) { + freemsg(session->current_tev); + session->current_tev=NULL; + } + session->current_tev=dupmsg(m0); + } + } + else + { + /* there is no pending events, but we did not received marked bit packet + either the sending implementation is not compliant, either it has been lost, + we must deal with it anyway.*/ + session->current_tev=copymsg(m0); + /* inform the application if there are tone ends */ + notify_events_ended(session,events,num); + } +} diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/telephonyevents.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/telephonyevents.h new file mode 100644 index 00000000..6f6936d5 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/telephonyevents.h @@ -0,0 +1,98 @@ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef TELEPHONYEVENTS_H +#define TELEPHONYEVENTS_H + + +#include <rtpsession.h> + + +struct _telephone_event +{ +#ifdef WORDS_BIGENDIAN + guint32 event:8; + guint32 E:1; + guint32 R:1; + guint32 volume:6; + guint32 duration:16; +#else + guint32 event:8; + guint32 volume:6; + guint32 R:1; + guint32 E:1; + guint32 duration:16; +#endif +}; + +typedef struct _telephone_event telephone_event_t; + +#ifdef __cplusplus +extern "C" { +#endif + +extern PayloadType telephone_event; + +/* tell if the session supports telephony events. For this the telephony events payload_type + must be present in the rtp profile used by the session */ + +/* low level functions */ +gint rtp_session_telephone_events_supported(RtpSession *session); + +mblk_t *rtp_session_create_telephone_event_packet(RtpSession *session, int start); + +gint rtp_session_add_telephone_event(RtpSession *session, + mblk_t *packet, guchar event, gint end, guchar volume, guint16 duration); + +gint rtp_session_read_telephone_event(RtpSession *session, + mblk_t *packet,telephone_event_t **tab); + +/* high level functions*/ +gint rtp_session_send_dtmf(RtpSession *session, gchar dtmf, guint32 userts); +/* for high level telephony event callback */ +void rtp_session_check_telephone_events(RtpSession *session, mblk_t *m0); + +#ifdef __cplusplus +} +#endif + +/* the size allocated for telephony events packets */ +#define TELEPHONY_EVENTS_ALLOCATED_SIZE (4*sizeof(telephone_event_t)) + +/* list of named events */ +#define TEV_DTMF_0 (0) +#define TEV_DTMF_1 (1) +#define TEV_DTMF_2 (2) +#define TEV_DTMF_3 (3) +#define TEV_DTMF_4 (4) +#define TEV_DTMF_5 (5) +#define TEV_DTMF_6 (6) +#define TEV_DTMF_7 (7) +#define TEV_DTMF_8 (8) +#define TEV_DTMF_9 (9) +#define TEV_DTMF_STAR (10) +#define TEV_DTMF_POUND (11) +#define TEV_DTMF_A (12) +#define TEV_DTMF_B (13) +#define TEV_DTMF_C (14) +#define TEV_DTMF_D (15) +#define TEV_FLASH (16) + + +#endif diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/utils.c b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/utils.c new file mode 100644 index 00000000..1ae601f4 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/utils.c @@ -0,0 +1,44 @@ +/*************************************************************************** + * utils.c + * + * Wed Feb 23 14:15:36 2005 + * Copyright 2005 Simon Morlat + * Email simon.morlat@linphone.org + ****************************************************************************/ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <rtpport.h> +#include "utils.h" + +OList *o_list_new(void *data){ + OList *new_elem=g_new0(OList,1); + new_elem->data=data; + return new_elem; +} + +OList * o_list_append(OList *elem, void * data){ + OList *new_elem=o_list_new(data); + OList *it=elem; + if (elem==NULL) return new_elem; + while (it->next!=NULL) it=o_list_next(it); + it->next=new_elem; + new_elem->prev=it; + return elem; +} diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/utils.h b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/utils.h new file mode 100644 index 00000000..7b71daf8 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/third_party/ortp/utils.h @@ -0,0 +1,43 @@ +/*************************************************************************** + * utils.h + * + * Wed Feb 23 14:15:36 2005 + * Copyright 2005 Simon Morlat + * Email simon.morlat@linphone.org + ****************************************************************************/ +/* + The oRTP library is an RTP (Realtime Transport Protocol - rfc1889) stack. + Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef UTILS_H +#define UTILS_H + +struct _OList { + struct _OList *next; + struct _OList *prev; + void *data; +}; + +typedef struct _OList OList; + + +#define o_list_next(elem) ((elem)->next) + +OList * o_list_append(OList *elem, void * data); + +#endif diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/xmllite/CMakeLists.txt b/kopete/protocols/jabber/jingle/libjingle/talk/xmllite/CMakeLists.txt new file mode 100644 index 00000000..8b2e72d4 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/xmllite/CMakeLists.txt @@ -0,0 +1,28 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_definitions( + -DPOSIX +) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/../.. + ${TQT_INCLUDE_DIRS} +) + + +##### cricketxmllite (static) ################### + +tde_add_library( cricketxmllite STATIC_PIC + SOURCES + qname.cc xmlbuilder.cc xmlconstants.cc xmlelement.cc xmlnsstack.cc + xmlparser.cc xmlprinter.cc +) diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/xmpp/CMakeLists.txt b/kopete/protocols/jabber/jingle/libjingle/talk/xmpp/CMakeLists.txt new file mode 100644 index 00000000..c68cc840 --- /dev/null +++ b/kopete/protocols/jabber/jingle/libjingle/talk/xmpp/CMakeLists.txt @@ -0,0 +1,29 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_definitions( + -DPOSIX +) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/../.. + ${CMAKE_BINARY_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### cricketxmpp (static) ###################### + +tde_add_library( cricketxmpp STATIC_PIC + SOURCES + constants.cc jid.cc saslmechanism.cc xmppclient.cc xmppengineimpl.cc + xmppengineimpl_iq.cc xmpplogintask.cc xmppstanzaparser.cc xmpptask.cc +) diff --git a/kopete/protocols/jabber/jingle/libjingle/talk/xmpp/xmpppassword.h b/kopete/protocols/jabber/jingle/libjingle/talk/xmpp/xmpppassword.h index f431b4e5..7a58cd6c 100644 --- a/kopete/protocols/jabber/jingle/libjingle/talk/xmpp/xmpppassword.h +++ b/kopete/protocols/jabber/jingle/libjingle/talk/xmpp/xmpppassword.h @@ -31,6 +31,8 @@ #include "talk/base/linked_ptr.h" #include "talk/base/scoped_ptr.h" +#include <cstring> + namespace buzz { class XmppPasswordImpl { diff --git a/kopete/protocols/jabber/kioslave/CMakeLists.txt b/kopete/protocols/jabber/kioslave/CMakeLists.txt new file mode 100644 index 00000000..12fa4173 --- /dev/null +++ b/kopete/protocols/jabber/kioslave/CMakeLists.txt @@ -0,0 +1,42 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ${CMAKE_CURRENT_SOURCE_DIR}/../libiris/iris/include + ${CMAKE_CURRENT_SOURCE_DIR}/../libiris/iris/jabber + ${CMAKE_CURRENT_SOURCE_DIR}/../libiris/iris/xmpp-im + ${CMAKE_CURRENT_SOURCE_DIR}/../libiris/cutestuff/util + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + +link_directories( + ${TQT_LIBRARY_DIRS} +) + + +##### other data ################################ + +install( FILES jabberdisco.protocol DESTINATION ${SERVICES_INSTALL_DIR} ) + + +##### kio_jabberdisco (module) ################## + +tde_add_kpart( kio_jabberdisco AUTOMOC + SOURCES jabberdisco.cpp + LINK + jabberclient-static + iris_xmpp_core-static iris_xmpp_im-static iris_jabber-static iris-static + qca-static cutestuff_network-static cutestuff_util-static kio-shared + DESTINATION ${PLUGIN_INSTALL_DIR} +) diff --git a/kopete/protocols/jabber/libiris/CMakeLists.txt b/kopete/protocols/jabber/libiris/CMakeLists.txt new file mode 100644 index 00000000..6c649aa5 --- /dev/null +++ b/kopete/protocols/jabber/libiris/CMakeLists.txt @@ -0,0 +1,14 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_subdirectory( iris ) +add_subdirectory( qca ) +add_subdirectory( cutestuff ) diff --git a/kopete/protocols/jabber/libiris/cutestuff/CMakeLists.txt b/kopete/protocols/jabber/libiris/cutestuff/CMakeLists.txt new file mode 100644 index 00000000..4f8cce38 --- /dev/null +++ b/kopete/protocols/jabber/libiris/cutestuff/CMakeLists.txt @@ -0,0 +1,13 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_subdirectory( network ) +add_subdirectory( util ) diff --git a/kopete/protocols/jabber/libiris/cutestuff/network/CMakeLists.txt b/kopete/protocols/jabber/libiris/cutestuff/network/CMakeLists.txt new file mode 100644 index 00000000..151dd407 --- /dev/null +++ b/kopete/protocols/jabber/libiris/cutestuff/network/CMakeLists.txt @@ -0,0 +1,27 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../util + ${CMAKE_CURRENT_SOURCE_DIR}/../../qca/src + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### cutestuff_network (static) ################ + +tde_add_library( cutestuff_network STATIC_PIC AUTOMOC + SOURCES + bsocket.cpp httpconnect.cpp httppoll.cpp ndns.cpp servsock.cpp + socks.cpp srvresolver.cpp +) diff --git a/kopete/protocols/jabber/libiris/cutestuff/util/CMakeLists.txt b/kopete/protocols/jabber/libiris/cutestuff/util/CMakeLists.txt new file mode 100644 index 00000000..13d55ca8 --- /dev/null +++ b/kopete/protocols/jabber/libiris/cutestuff/util/CMakeLists.txt @@ -0,0 +1,24 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### cutestuff_util (static) ################### + +tde_add_library( cutestuff_util STATIC_PIC AUTOMOC + SOURCES + base64.cpp bytestream.cpp qrandom.cpp safedelete.cpp sha1.cpp + showtextdlg.cpp +) diff --git a/kopete/protocols/jabber/libiris/iris/CMakeLists.txt b/kopete/protocols/jabber/libiris/iris/CMakeLists.txt new file mode 100644 index 00000000..d5062694 --- /dev/null +++ b/kopete/protocols/jabber/libiris/iris/CMakeLists.txt @@ -0,0 +1,15 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_subdirectory( include ) +add_subdirectory( jabber ) +add_subdirectory( xmpp-core ) +add_subdirectory( xmpp-im ) diff --git a/kopete/protocols/jabber/libiris/iris/include/CMakeLists.txt b/kopete/protocols/jabber/libiris/iris/include/CMakeLists.txt new file mode 100644 index 00000000..ff84643b --- /dev/null +++ b/kopete/protocols/jabber/libiris/iris/include/CMakeLists.txt @@ -0,0 +1,24 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### iris (static) ############################# + +tde_moc( SRCS im.h xmpp.h ) + +tde_add_library( iris STATIC_PIC + SOURCES ${SRCS} +) diff --git a/kopete/protocols/jabber/libiris/iris/jabber/CMakeLists.txt b/kopete/protocols/jabber/libiris/iris/jabber/CMakeLists.txt new file mode 100644 index 00000000..e73563f2 --- /dev/null +++ b/kopete/protocols/jabber/libiris/iris/jabber/CMakeLists.txt @@ -0,0 +1,40 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../include + ${CMAKE_CURRENT_SOURCE_DIR}/../xmpp-im + ${CMAKE_CURRENT_SOURCE_DIR}/../xmpp-core + ${CMAKE_CURRENT_SOURCE_DIR}/../../cutestuff/util + ${CMAKE_CURRENT_SOURCE_DIR}/../../cutestuff/network + ${CMAKE_CURRENT_SOURCE_DIR}/../../qca/src + ${CMAKE_BINARY_DIR} + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### iris_jabber (static) ###################### + +add_custom_command( OUTPUT s5b.moc + COMMAND ${TMOC_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/s5b.cpp -o s5b.moc.cpp + COMMAND ${TMOC_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/s5b.h -o s5b.moc.h + COMMAND sed -i -e '/^\#include/d' s5b.moc.cpp + COMMAND cat s5b.moc.h s5b.moc.cpp > s5b.moc + DEPENDS s5b.cpp ) + +set_source_files_properties( s5b.cpp PROPERTIES OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/s5b.moc ) + +tde_add_library( iris_jabber STATIC_PIC AUTOMOC + SOURCES + filetransfer.cpp s5b.cpp xmpp_ibb.cpp xmpp_jidlink.cpp all_mocs.cpp +) diff --git a/kopete/protocols/jabber/libiris/iris/xmpp-core/CMakeLists.txt b/kopete/protocols/jabber/libiris/iris/xmpp-core/CMakeLists.txt new file mode 100644 index 00000000..4361f30e --- /dev/null +++ b/kopete/protocols/jabber/libiris/iris/xmpp-core/CMakeLists.txt @@ -0,0 +1,38 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../include + ${CMAKE_CURRENT_SOURCE_DIR}/../../qca/src + ${CMAKE_CURRENT_SOURCE_DIR}/../../cutestuff/util + ${CMAKE_CURRENT_SOURCE_DIR}/../../cutestuff/network + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### iris_xmpp_core (static) ######################## + +add_custom_command( OUTPUT securestream.moc + COMMAND ${TMOC_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/securestream.cpp -o securestream.moc.cpp + COMMAND ${TMOC_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/securestream.h -o securestream.moc.h + COMMAND sed -i -e '/^\#include/d' securestream.moc.cpp + COMMAND cat securestream.moc.h securestream.moc.cpp > securestream.moc + DEPENDS securestream.cpp ) + +set_source_files_properties( securestream.cpp PROPERTIES OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/securestream.moc ) + +tde_add_library( iris_xmpp_core STATIC_PIC + SOURCES + connector.cpp jid.cpp securestream.cpp tlshandler.cpp hash.cpp + protocol.cpp stream.cpp xmlprotocol.cpp parser.cpp simplesasl.cpp +) diff --git a/kopete/protocols/jabber/libiris/iris/xmpp-im/CMakeLists.txt b/kopete/protocols/jabber/libiris/iris/xmpp-im/CMakeLists.txt new file mode 100644 index 00000000..58a1a034 --- /dev/null +++ b/kopete/protocols/jabber/libiris/iris/xmpp-im/CMakeLists.txt @@ -0,0 +1,37 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../include + ${CMAKE_CURRENT_SOURCE_DIR}/../jabber + ${CMAKE_CURRENT_SOURCE_DIR}/../xmpp-core + ${CMAKE_CURRENT_SOURCE_DIR}/../../cutestuff/util + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### iris_xmpp_im (static) ##################### + +add_custom_command( OUTPUT types.moc + COMMAND ${TMOC_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/types.cpp -o types.moc + COMMAND sed -i -e '/^\#include \"/d' types.moc + DEPENDS types.cpp ) + +set_source_files_properties( types.cpp PROPERTIES OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/types.moc ) + +tde_moc( MOCS xmpp_tasks.h ) + +tde_add_library( iris_xmpp_im STATIC_PIC + SOURCES + client.cpp types.cpp xmpp_tasks.cpp xmpp_vcard.cpp xmpp_xmlcommon.cpp ${MOCS} +) diff --git a/kopete/protocols/jabber/libiris/qca/CMakeLists.txt b/kopete/protocols/jabber/libiris/qca/CMakeLists.txt new file mode 100644 index 00000000..7356f221 --- /dev/null +++ b/kopete/protocols/jabber/libiris/qca/CMakeLists.txt @@ -0,0 +1,12 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_subdirectory( src ) diff --git a/kopete/protocols/jabber/libiris/qca/src/CMakeLists.txt b/kopete/protocols/jabber/libiris/qca/src/CMakeLists.txt new file mode 100644 index 00000000..46de2435 --- /dev/null +++ b/kopete/protocols/jabber/libiris/qca/src/CMakeLists.txt @@ -0,0 +1,22 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### qca (static) ############################## + +tde_add_library( qca STATIC_PIC AUTOMOC + SOURCES qca.cpp +) diff --git a/kopete/protocols/jabber/ui/CMakeLists.txt b/kopete/protocols/jabber/ui/CMakeLists.txt new file mode 100644 index 00000000..a4488d62 --- /dev/null +++ b/kopete/protocols/jabber/ui/CMakeLists.txt @@ -0,0 +1,43 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/../../../libkopete/ui + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ${CMAKE_CURRENT_SOURCE_DIR}/../libiris/iris/include + ${CMAKE_CURRENT_SOURCE_DIR}/../libiris/iris/jabber + ${CMAKE_CURRENT_SOURCE_DIR}/../libiris/iris/xmpp-im + ${CMAKE_CURRENT_SOURCE_DIR}/../libiris/qca/src + ${CMAKE_CURRENT_SOURCE_DIR}/../libiris/cutestuff/util + ${CMAKE_CURRENT_SOURCE_DIR}/../../../libkopete + ${CMAKE_CURRENT_SOURCE_DIR}/../../../libkopete/ui + ${CMAKE_BINARY_DIR} + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### kopetejabberui (static) ################### + +tde_add_library( kopetejabberui STATIC_PIC AUTOMOC + SOURCES + dlgsendraw.ui dlgjabbersendraw.cpp dlgaddcontact.ui + jabberaddcontactpage.cpp dlgvcard.ui dlgjabbervcard.cpp + dlgjabberservices.cpp dlgregister.ui dlgjabberregister.cpp + dlgbrowse.ui dlgjabberbrowse.cpp dlgjabbereditaccountwidget.ui + jabbereditaccountwidget.cpp dlgjabberregisteraccount.ui + jabberregisteraccount.cpp dlgjabberchooseserver.ui + jabberchooseserver.cpp dlgchangepassword.ui + dlgjabberchangepassword.cpp empty.cpp dlgchatroomslist.ui + dlgjabberchatroomslist.cpp dlgchatjoin.ui dlgjabberchatjoin.cpp + dlgservices.ui +) diff --git a/kopete/protocols/meanwhile/CMakeLists.txt b/kopete/protocols/meanwhile/CMakeLists.txt new file mode 100644 index 00000000..994f6e31 --- /dev/null +++ b/kopete/protocols/meanwhile/CMakeLists.txt @@ -0,0 +1,47 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include( ConfigureChecks.cmake ) + +add_subdirectory( ui ) +add_subdirectory( icons ) + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/ui + ${CMAKE_BINARY_DIR}/kopete/libkopete/ui + ${CMAKE_SOURCE_DIR}/kopete/libkopete + ${CMAKE_SOURCE_DIR}/kopete/libkopete/ui + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} + ${MEANWHILE_INCLUDE_DIRS} +) + +link_directories( + ${TQT_LIBRARY_DIRS} +) + + +##### other data ################################ + +install( FILES kopete_meanwhile.desktop DESTINATION ${SERVICES_INSTALL_DIR} ) + + +##### new_target0 (module) ####################### + +tde_add_kpart( new_target0 AUTOMOC + SOURCES + meanwhileprotocol.cpp meanwhileaddcontactpage.cpp + meanwhileeditaccountwidget.cpp meanwhileaccount.cpp + meanwhilecontact.cpp meanwhilesession.cpp meanwhileplugin.cpp + LINK kopetemeanwhileui-static kopete-shared ${MEANWHILE_LIBRARIES} + DESTINATION ${PLUGIN_INSTALL_DIR} +) diff --git a/kopete/protocols/meanwhile/ConfigureChecks.cmake b/kopete/protocols/meanwhile/ConfigureChecks.cmake new file mode 100644 index 00000000..58d8c67f --- /dev/null +++ b/kopete/protocols/meanwhile/ConfigureChecks.cmake @@ -0,0 +1,15 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +pkg_search_module( MEANWHILE meanwhile ) +if( NOT MEANWHILE_FOUND ) + tde_message_fatal( "meanwhile is required, but was not found on your system" ) +endif( ) diff --git a/kopete/protocols/meanwhile/icons/CMakeLists.txt b/kopete/protocols/meanwhile/icons/CMakeLists.txt new file mode 100644 index 00000000..ba51467b --- /dev/null +++ b/kopete/protocols/meanwhile/icons/CMakeLists.txt @@ -0,0 +1,12 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +tde_install_icons( DESTINATION ${DATA_INSTALL_DIR}/kopete/icons ) diff --git a/kopete/protocols/meanwhile/ui/CMakeLists.txt b/kopete/protocols/meanwhile/ui/CMakeLists.txt new file mode 100644 index 00000000..434f849b --- /dev/null +++ b/kopete/protocols/meanwhile/ui/CMakeLists.txt @@ -0,0 +1,27 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_BINARY_DIR}/kopete/libkopete/ui + ${CMAKE_SOURCE_DIR}/kopete/libkopete + ${CMAKE_SOURCE_DIR}/kopete/libkopete/ui + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### kopetemeanwhileui (static) ################ + +tde_add_library( kopetemeanwhileui STATIC_PIC AUTOMOC + SOURCES + empty.cpp meanwhileeditaccountbase.ui meanwhileaddcontactbase.ui +) diff --git a/kopete/protocols/msn/CMakeLists.txt b/kopete/protocols/msn/CMakeLists.txt new file mode 100644 index 00000000..77bd2cc7 --- /dev/null +++ b/kopete/protocols/msn/CMakeLists.txt @@ -0,0 +1,71 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_subdirectory( ui ) +add_subdirectory( icons ) +add_subdirectory( config ) + +if( WITH_WEBCAM ) + add_subdirectory( webcam ) + add_definitions( -DMSN_WEBCAM ) + set( WEBCAM_LIBRARIES mimicwrapper-static kopete_videodevice-shared ${GLIB2_LIBRARIES} ) +endif( ) + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/ui + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/ui + ${CMAKE_CURRENT_SOURCE_DIR}/webcam + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/kopete/libkopete + ${CMAKE_SOURCE_DIR}/kopete/libkopete/ui + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + +link_directories( + ${TQT_LIBRARY_DIRS} +) + + +##### other data ################################ + +install( FILES kopete_msn.desktop DESTINATION ${SERVICES_INSTALL_DIR} ) +install( FILES msnchatui.rc DESTINATION ${DATA_INSTALL_DIR}/kopete_msn ) + + +##### kopete_msn (module) ####################### + +tde_add_kpart( kopete_msn AUTOMOC + SOURCES + dummy.cpp webcam.cpp + LINK kopete_msn_shared-shared + DESTINATION ${PLUGIN_INSTALL_DIR} +) + + +##### kopete_msn_shared (shared) ################ + +tde_add_library( kopete_msn_shared SHARED AUTOMOC + SOURCES + msnprotocol.cpp msnaccount.cpp msnaddcontactpage.cpp msncontact.cpp + msnsocket.cpp msnchatsession.cpp msndebugrawcmddlg.cpp + msnnotifysocket.cpp msnswitchboardsocket.cpp + msnfiletransfersocket.cpp msninvitation.cpp sha1.cpp + msnsecureloginhandler.cpp msnchallengehandler.cpp + dispatcher.cpp p2p.cpp messageformatter.cpp incomingtransfer.cpp + outgoingtransfer.cpp webcam.cpp + VERSION 0.0.0 + LINK + kopetemsnui-static ${WEBCAM_LIBRARIES} kopete-shared + DESTINATION ${LIB_INSTALL_DIR} +) diff --git a/kopete/protocols/msn/config/CMakeLists.txt b/kopete/protocols/msn/config/CMakeLists.txt new file mode 100644 index 00000000..7e0d1337 --- /dev/null +++ b/kopete/protocols/msn/config/CMakeLists.txt @@ -0,0 +1,38 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/kopete/libkopete + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + +link_directories( + ${TQT_LIBRARY_DIRS} +) + + +##### other data ################################ + +install( FILES + kopete_msn_config.desktop + DESTINATION ${SERVICES_INSTALL_DIR}/kconfiguredialog ) + + +##### kcm_kopete_msn (module) ################### + +tde_add_kpart( kcm_kopete_msn AUTOMOC + SOURCES + msnprefs.ui msnpreferences.cpp + LINK kopete-shared + DESTINATION ${PLUGIN_INSTALL_DIR} +) diff --git a/kopete/protocols/msn/icons/CMakeLists.txt b/kopete/protocols/msn/icons/CMakeLists.txt new file mode 100644 index 00000000..ba51467b --- /dev/null +++ b/kopete/protocols/msn/icons/CMakeLists.txt @@ -0,0 +1,12 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +tde_install_icons( DESTINATION ${DATA_INSTALL_DIR}/kopete/icons ) diff --git a/kopete/protocols/msn/ui/CMakeLists.txt b/kopete/protocols/msn/ui/CMakeLists.txt new file mode 100644 index 00000000..bd70ce80 --- /dev/null +++ b/kopete/protocols/msn/ui/CMakeLists.txt @@ -0,0 +1,29 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ${CMAKE_BINARY_DIR}/kopete/libkopete/ui + ${CMAKE_SOURCE_DIR}/kopete/libkopete + ${CMAKE_SOURCE_DIR}/kopete/libkopete/ui + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### kopetemsnui (static) ###################### + +tde_add_library( kopetemsnui STATIC_PIC AUTOMOC + SOURCES + msnadd.ui msndebugrawcommand_base.ui msninfo.ui msneditaccountui.ui + msneditaccountwidget.cpp +) diff --git a/kopete/protocols/msn/webcam/CMakeLists.txt b/kopete/protocols/msn/webcam/CMakeLists.txt new file mode 100644 index 00000000..aafa2d94 --- /dev/null +++ b/kopete/protocols/msn/webcam/CMakeLists.txt @@ -0,0 +1,28 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_subdirectory( libmimic ) + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/kopete/libkopete + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} + ${GLIB2_INCLUDE_DIRS} +) + + +##### mimicwrapper (static) ##################### + +tde_add_library( mimicwrapper STATIC_PIC AUTOMOC + SOURCES mimicwrapper.cpp msnwebcamdialog.cpp + LINK mimic-static +) diff --git a/kopete/protocols/msn/webcam/libmimic/CMakeLists.txt b/kopete/protocols/msn/webcam/libmimic/CMakeLists.txt new file mode 100644 index 00000000..d98fc837 --- /dev/null +++ b/kopete/protocols/msn/webcam/libmimic/CMakeLists.txt @@ -0,0 +1,23 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${GLIB2_INCLUDE_DIRS} +) + + +##### mimic (static) ############################ + +tde_add_library( mimic STATIC_PIC + SOURCES + mimic.c encode.c decode.c bitstring.c vlc_common.c vlc_encode.c + vlc_decode.c fdct_quant.c idct_dequant.c colorspace.c deblock.c +) diff --git a/kopete/protocols/oscar/CMakeLists.txt b/kopete/protocols/oscar/CMakeLists.txt new file mode 100644 index 00000000..bbffa100 --- /dev/null +++ b/kopete/protocols/oscar/CMakeLists.txt @@ -0,0 +1,42 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_subdirectory( liboscar ) +add_subdirectory( aim ) +add_subdirectory( icq ) +add_subdirectory( icons ) + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/liboscar + ${CMAKE_SOURCE_DIR}/kopete/libkopete + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + +link_directories( + ${TQT_LIBRARY_DIRS} +) + + +##### kopete_oscar (shared) ##################### + +tde_add_library( kopete_oscar SHARED AUTOMOC + SOURCES + oscaraccount.cpp oscarcontact.cpp oscarmyselfcontact.cpp + oscarencodingselectionbase.ui oscarencodingselectiondialog.cpp + oscarlistcontactsbase.ui oscarlistnonservercontacts.cpp + oscarvisibilitybase.ui oscarvisibilitydialog.cpp + oscarversionupdater.cpp + VERSION 2.0.0 + LINK oscar-static kopete-shared + DESTINATION ${LIB_INSTALL_DIR} +) diff --git a/kopete/protocols/oscar/aim/CMakeLists.txt b/kopete/protocols/oscar/aim/CMakeLists.txt new file mode 100644 index 00000000..75230df3 --- /dev/null +++ b/kopete/protocols/oscar/aim/CMakeLists.txt @@ -0,0 +1,47 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_subdirectory( ui ) + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/ui + ${CMAKE_CURRENT_SOURCE_DIR}/ui + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ${CMAKE_CURRENT_SOURCE_DIR}/../liboscar + ${CMAKE_SOURCE_DIR}/kopete/libkopete + ${CMAKE_SOURCE_DIR}/kopete/libkopete/ui + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + +link_directories( + ${TQT_LIBRARY_DIRS} +) + + +##### other data ################################ + +install( FILES + kopete_aim.desktop aim.protocol + DESTINATION ${SERVICES_INSTALL_DIR} ) + + +##### kopete_aim (module) ####################### + +tde_add_kpart( kopete_aim AUTOMOC + SOURCES + aimprotocol.cpp aimaccount.cpp aimcontact.cpp aimuserinfo.cpp + aimjoinchat.cpp aimchatsession.cpp + LINK + kopeteaimui-static kopete_oscar-shared + DESTINATION ${PLUGIN_INSTALL_DIR} +) diff --git a/kopete/protocols/oscar/aim/ui/CMakeLists.txt b/kopete/protocols/oscar/aim/ui/CMakeLists.txt new file mode 100644 index 00000000..8f5ff329 --- /dev/null +++ b/kopete/protocols/oscar/aim/ui/CMakeLists.txt @@ -0,0 +1,31 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ${CMAKE_CURRENT_SOURCE_DIR}/../.. + ${CMAKE_CURRENT_SOURCE_DIR}/../../liboscar + ${CMAKE_BINARY_DIR}/kopete/libkopete/ui + ${CMAKE_SOURCE_DIR}/kopete/libkopete + ${CMAKE_SOURCE_DIR}/kopete/libkopete/ui + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### kopeteaimui (static) ###################### + +tde_add_library( kopeteaimui STATIC_PIC AUTOMOC + SOURCES + aimaddcontactui.ui aimeditaccountui.ui aiminfobase.ui + aimjoinchatbase.ui aimaddcontactpage.cpp aimeditaccountwidget.cpp +) diff --git a/kopete/protocols/oscar/icons/CMakeLists.txt b/kopete/protocols/oscar/icons/CMakeLists.txt new file mode 100644 index 00000000..ba51467b --- /dev/null +++ b/kopete/protocols/oscar/icons/CMakeLists.txt @@ -0,0 +1,12 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +tde_install_icons( DESTINATION ${DATA_INSTALL_DIR}/kopete/icons ) diff --git a/kopete/protocols/oscar/icq/CMakeLists.txt b/kopete/protocols/oscar/icq/CMakeLists.txt new file mode 100644 index 00000000..20f8b11a --- /dev/null +++ b/kopete/protocols/oscar/icq/CMakeLists.txt @@ -0,0 +1,45 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_subdirectory( ui ) + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/ui + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ${CMAKE_CURRENT_SOURCE_DIR}/../liboscar + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/kopete/libkopete + ${CMAKE_SOURCE_DIR}/kopete/libkopete/ui + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + +link_directories( + ${TQT_LIBRARY_DIRS} +) + + +##### other data ################################ + +install( FILES kopete_icq.desktop DESTINATION ${SERVICES_INSTALL_DIR} ) +install( FILES x-icq.desktop DESTINATION ${MIME_INSTALL_DIR}/application ) + + +##### kopete_icq (module) ####################### + +tde_add_kpart( kopete_icq AUTOMOC + SOURCES + icqpresence.cpp icqaccount.cpp icqcontact.cpp icqprotocol.cpp + LINK + kopeteicqui-static kopete_oscar-shared + DESTINATION ${PLUGIN_INSTALL_DIR} +) diff --git a/kopete/protocols/oscar/icq/ui/CMakeLists.txt b/kopete/protocols/oscar/icq/ui/CMakeLists.txt new file mode 100644 index 00000000..9da3ac25 --- /dev/null +++ b/kopete/protocols/oscar/icq/ui/CMakeLists.txt @@ -0,0 +1,34 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ${CMAKE_CURRENT_SOURCE_DIR}/../.. + ${CMAKE_CURRENT_SOURCE_DIR}/../../liboscar + ${CMAKE_BINARY_DIR}/kopete/libkopete/ui + ${CMAKE_SOURCE_DIR}/kopete/libkopete + ${CMAKE_SOURCE_DIR}/kopete/libkopete/ui + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### kopeteicqui (static) ###################### + +tde_add_library( kopeteicqui STATIC_PIC AUTOMOC + SOURCES + icqadd.ui icqeditaccountui.ui icqeditaccountwidget.cpp + icqgeneralinfo.ui icqotherinfowidget.ui icqworkinfowidget.ui + icqinterestinfowidget.ui icquserinfowidget.cpp icqauthreplyui.ui + icqauthreplydialog.cpp icqaddcontactpage.cpp icqsearchbase.ui + icqsearchdialog.cpp +) diff --git a/kopete/protocols/oscar/liboscar/CMakeLists.txt b/kopete/protocols/oscar/liboscar/CMakeLists.txt new file mode 100644 index 00000000..6053541f --- /dev/null +++ b/kopete/protocols/oscar/liboscar/CMakeLists.txt @@ -0,0 +1,46 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/kopete/libkopete + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### oscar (static) ############################ + +tde_add_library( oscar STATIC_PIC AUTOMOC + SOURCES + oscarutils.cpp client.cpp task.cpp connector.cpp + inputprotocolbase.cpp coreprotocol.cpp flapprotocol.cpp + snacprotocol.cpp transfer.cpp rtf.cc bytestream.cpp + oscarclientstream.cpp safedelete.cpp stream.cpp oscarconnector.cpp + oscarbytestream.cpp buffer.cpp md5.c logintask.cpp aimlogintask.cpp + icqlogintask.cpp closeconnectiontask.cpp rateclassmanager.cpp + serverversionstask.cpp rateinfotask.cpp errortask.cpp + locationrightstask.cpp profiletask.cpp blmlimitstask.cpp + servicesetuptask.cpp icbmparamstask.cpp ssimanager.cpp rateclass.cpp + rateclass.h prmparamstask.cpp ssiparamstask.cpp ssilisttask.cpp + ssiactivatetask.cpp clientreadytask.cpp senddcinfotask.cpp + sendidletimetask.cpp ownuserinfotask.cpp connection.cpp + onlinenotifiertask.cpp userdetails.cpp ssimodifytask.cpp + oscartypeclasses.cpp oscarmessage.cpp messagereceivertask.cpp + sendmessagetask.cpp icqtask.cpp offlinemessagestask.cpp + ssiauthtask.cpp userinfotask.cpp icquserinfo.cpp icquserinfotask.cpp + usersearchtask.cpp warningtask.cpp changevisibilitytask.cpp + typingnotifytask.cpp buddyicontask.cpp serverredirecttask.cpp + oscarsettings.cpp chatnavservicetask.cpp connectionhandler.cpp + chatservicetask.cpp +) diff --git a/kopete/protocols/sms/CMakeLists.txt b/kopete/protocols/sms/CMakeLists.txt new file mode 100644 index 00000000..017ae01e --- /dev/null +++ b/kopete/protocols/sms/CMakeLists.txt @@ -0,0 +1,48 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_subdirectory( ui ) +add_subdirectory( services ) +add_subdirectory( icons ) + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/ui + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/services + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/kopete/libkopete + ${CMAKE_SOURCE_DIR}/kopete/libkopete/ui + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + +link_directories( + ${TQT_LIBRARY_DIRS} +) + + +##### other data ################################ + +install( FILES kopete_sms.desktop DESTINATION ${SERVICES_INSTALL_DIR} ) + + +##### kopete_sms (module) ####################### + +tde_add_kpart( kopete_sms AUTOMOC + SOURCES + smsaddcontactpage.cpp smscontact.cpp smseditaccountwidget.cpp + smsprotocol.cpp serviceloader.cpp smsservice.cpp + smsuserpreferences.cpp smsaccount.cpp + LINK + kopetesmsui-static kopetesmsservices-static kopete-shared + DESTINATION ${PLUGIN_INSTALL_DIR} +) diff --git a/kopete/protocols/sms/icons/CMakeLists.txt b/kopete/protocols/sms/icons/CMakeLists.txt new file mode 100644 index 00000000..ba51467b --- /dev/null +++ b/kopete/protocols/sms/icons/CMakeLists.txt @@ -0,0 +1,12 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +tde_install_icons( DESTINATION ${DATA_INSTALL_DIR}/kopete/icons ) diff --git a/kopete/protocols/sms/services/CMakeLists.txt b/kopete/protocols/sms/services/CMakeLists.txt new file mode 100644 index 00000000..c9942bd6 --- /dev/null +++ b/kopete/protocols/sms/services/CMakeLists.txt @@ -0,0 +1,32 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +# FIXME KDE_CXXFLAGS = $(USE_EXCEPTIONS) + +include( ConfigureChecks.cmake ) + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ${CMAKE_SOURCE_DIR}/kopete/libkopete + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### kopetesmsservices (static) ################ + +tde_add_library( kopetesmsservices STATIC_PIC AUTOMOC + SOURCES + smssend.cpp smssendprefs.ui smssendprovider.cpp smsclient.cpp + smsclientprefs.ui gsmlib.cpp gsmlibprefs.ui kopete_unix_serial.cpp + LINK ${GSM_LIBRARY} +) diff --git a/kopete/protocols/sms/services/ConfigureChecks.cmake b/kopete/protocols/sms/services/ConfigureChecks.cmake new file mode 100644 index 00000000..4ed454b4 --- /dev/null +++ b/kopete/protocols/sms/services/ConfigureChecks.cmake @@ -0,0 +1,30 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +if( WITH_GSM ) + + tde_save( CMAKE_REQUIRED_INCLUDES ) + set( CMAKE_REQUIRED_INCLUDES ${TQT_INCLUDE_DIRS} ) + check_include_file_cxx( gsmlib/gsm_util.h HAVE_GSMLIB_GSM_UTIL_H ) + tde_restore( CMAKE_REQUIRED_INCLUDES ) + + if( HAVE_GSMLIB_GSM_UTIL_H ) + set( INCLUDE_SMSGSM 1 ) + find_library( GSM_LIBRARY gsmme ) + endif( ) + + if( NOT (HAVE_GSMLIB_GSM_UTIL_H AND GSM_LIBRARY) ) + tde_message_fatal( "gsmlib is required, but was not found on your system" ) + endif( ) + +endif( ) + +configure_file( config.h.cmake config.h @ONLY ) diff --git a/kopete/protocols/sms/services/config.h.cmake b/kopete/protocols/sms/services/config.h.cmake new file mode 100644 index 00000000..9555d535 --- /dev/null +++ b/kopete/protocols/sms/services/config.h.cmake @@ -0,0 +1 @@ +#cmakedefine INCLUDE_SMSGSM 1 diff --git a/kopete/protocols/sms/ui/CMakeLists.txt b/kopete/protocols/sms/ui/CMakeLists.txt new file mode 100644 index 00000000..619f7a88 --- /dev/null +++ b/kopete/protocols/sms/ui/CMakeLists.txt @@ -0,0 +1,24 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### kopetesmsui (static) ###################### + +tde_add_library( kopetesmsui STATIC_PIC AUTOMOC + SOURCES + smsadd.ui smsactprefs.ui smsuserprefs.ui empty.cpp +) diff --git a/kopete/protocols/testbed/CMakeLists.txt b/kopete/protocols/testbed/CMakeLists.txt new file mode 100644 index 00000000..6052845a --- /dev/null +++ b/kopete/protocols/testbed/CMakeLists.txt @@ -0,0 +1,44 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_subdirectory( icons ) +add_subdirectory( ui ) + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/ui + ${CMAKE_SOURCE_DIR}/kopete/libkopete + ${CMAKE_SOURCE_DIR}/kopete/libkopete/ui + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + +link_directories( + ${TQT_LIBRARY_DIRS} +) + + +##### other data ################################ + +install( FILES kopete_testbed.desktop DESTINATION ${SERVICES_INSTALL_DIR} ) + + +##### kopete_testbed (module) ################### + +tde_add_kpart( kopete_testbed AUTOMOC + SOURCES + testbedprotocol.cpp testbedcontact.cpp testbedaccount.cpp + testbedaddcontactpage.cpp testbedaddui.ui + testbededitaccountwidget.cpp testbedaccountpreferences.ui + testbedfakeserver.cpp testbedincomingmessage.cpp + LINK kopetetestbedui-static kopete-shared kopete_videodevice-shared + DESTINATION ${PLUGIN_INSTALL_DIR} +) diff --git a/kopete/protocols/testbed/icons/CMakeLists.txt b/kopete/protocols/testbed/icons/CMakeLists.txt new file mode 100644 index 00000000..ba51467b --- /dev/null +++ b/kopete/protocols/testbed/icons/CMakeLists.txt @@ -0,0 +1,12 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +tde_install_icons( DESTINATION ${DATA_INSTALL_DIR}/kopete/icons ) diff --git a/kopete/protocols/testbed/testbedaccount.h b/kopete/protocols/testbed/testbedaccount.h index 52261cb7..b58249c6 100644 --- a/kopete/protocols/testbed/testbedaccount.h +++ b/kopete/protocols/testbed/testbedaccount.h @@ -59,7 +59,7 @@ public: /** * 'Connect' to the testbed server. Only sets myself() online. */ - virtual void connect( const Kopete::OnlineStatus& initialStatus = Kopete::OnlineStatus::OnlineStatus() ); + virtual void connect( const Kopete::OnlineStatus& initialStatus = Kopete::OnlineStatus() ); /** * Disconnect from the server. Only sets myself() offline. */ diff --git a/kopete/protocols/testbed/ui/CMakeLists.txt b/kopete/protocols/testbed/ui/CMakeLists.txt new file mode 100644 index 00000000..febe5b7b --- /dev/null +++ b/kopete/protocols/testbed/ui/CMakeLists.txt @@ -0,0 +1,25 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/kopete/libkopete + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### kopetetestbedui (static) ################## + +tde_add_library( kopetetestbedui STATIC_PIC AUTOMOC + SOURCES testbedwebcamdialog.cpp +) diff --git a/kopete/protocols/winpopup/CMakeLists.txt b/kopete/protocols/winpopup/CMakeLists.txt new file mode 100644 index 00000000..e80e8e51 --- /dev/null +++ b/kopete/protocols/winpopup/CMakeLists.txt @@ -0,0 +1,51 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_subdirectory( ui ) +add_subdirectory( icons ) +add_subdirectory( libwinpopup ) + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/ui + ${CMAKE_CURRENT_SOURCE_DIR}/libwinpopup + ${CMAKE_SOURCE_DIR}/kopete/libkopete + ${CMAKE_SOURCE_DIR}/kopete/libkopete/ui + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + +link_directories( + ${TQT_LIBRARY_DIRS} +) + + +##### other data ################################ + +install( FILES + kopete_wp.desktop + DESTINATION ${SERVICES_INSTALL_DIR} ) + +install( PROGRAMS + winpopup-send.sh winpopup-install.sh + DESTINATION ${BIN_INSTALL_DIR} ) + + +##### kopete_wp (module) ######################## + +tde_add_kpart( kopete_wp AUTOMOC + SOURCES + wpprotocol.cpp wpcontact.cpp wpaddcontact.cpp wpeditaccount.cpp + wpaccount.cpp wpuserinfo.cpp + LINK + kopetewpui-static winpopup-static kopete-shared + DESTINATION ${PLUGIN_INSTALL_DIR} +) diff --git a/kopete/protocols/winpopup/icons/CMakeLists.txt b/kopete/protocols/winpopup/icons/CMakeLists.txt new file mode 100644 index 00000000..ba51467b --- /dev/null +++ b/kopete/protocols/winpopup/icons/CMakeLists.txt @@ -0,0 +1,12 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +tde_install_icons( DESTINATION ${DATA_INSTALL_DIR}/kopete/icons ) diff --git a/kopete/protocols/winpopup/libwinpopup/CMakeLists.txt b/kopete/protocols/winpopup/libwinpopup/CMakeLists.txt new file mode 100644 index 00000000..4f11898b --- /dev/null +++ b/kopete/protocols/winpopup/libwinpopup/CMakeLists.txt @@ -0,0 +1,24 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/kopete/libkopete + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### winpopup (static) ######################### + +tde_add_library( winpopup STATIC_PIC AUTOMOC + SOURCES libwinpopup.cpp +) diff --git a/kopete/protocols/winpopup/ui/CMakeLists.txt b/kopete/protocols/winpopup/ui/CMakeLists.txt new file mode 100644 index 00000000..d73253ce --- /dev/null +++ b/kopete/protocols/winpopup/ui/CMakeLists.txt @@ -0,0 +1,25 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### kopetewpui (static) ####################### + +tde_add_library( kopetewpui STATIC_PIC AUTOMOC + SOURCES + wpaddcontactbase.ui wpeditaccountbase.ui empty.cpp + wpuserinfowidget.ui +) diff --git a/kopete/protocols/yahoo/CMakeLists.txt b/kopete/protocols/yahoo/CMakeLists.txt new file mode 100644 index 00000000..124fc32a --- /dev/null +++ b/kopete/protocols/yahoo/CMakeLists.txt @@ -0,0 +1,49 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_subdirectory( libkyahoo ) +add_subdirectory( ui ) +add_subdirectory( icons ) + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_BINARY_DIR}/ui + ${CMAKE_BINARY_DIR}/kopete/libkopete/ui + ${CMAKE_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/libkyahoo + ${CMAKE_CURRENT_SOURCE_DIR}/ui + ${CMAKE_SOURCE_DIR}/kopete/libkopete + ${CMAKE_SOURCE_DIR}/kopete/libkopete/ui + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + +link_directories( + ${TQT_LIBRARY_DIRS} +) + + +##### other data ################################ + +install( FILES yahooconferenceui.rc yahoochatui.rc DESTINATION ${DATA_INSTALL_DIR}/kopete_yahoo ) +install( FILES kopete_yahoo.desktop DESTINATION ${SERVICES_INSTALL_DIR} ) + + +##### kopete_yahoo (module) ##################### + +tde_add_kpart( kopete_yahoo AUTOMOC + SOURCES + yahooprotocol.cpp yahooeditaccount.cpp yahooaddcontact.cpp + yahooaccount.cpp yahoocontact.cpp yahooconferencemessagemanager.cpp + yahoochatsession.cpp yahooverifyaccount.cpp yahoowebcam.cpp + LINK kyahoo-static kopeteyahooui-static kopeteui-static kopete-shared kopete_videodevice-shared + DESTINATION ${PLUGIN_INSTALL_DIR} +) diff --git a/kopete/protocols/yahoo/icons/CMakeLists.txt b/kopete/protocols/yahoo/icons/CMakeLists.txt new file mode 100644 index 00000000..ba51467b --- /dev/null +++ b/kopete/protocols/yahoo/icons/CMakeLists.txt @@ -0,0 +1,12 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +tde_install_icons( DESTINATION ${DATA_INSTALL_DIR}/kopete/icons ) diff --git a/kopete/protocols/yahoo/libkyahoo/CMakeLists.txt b/kopete/protocols/yahoo/libkyahoo/CMakeLists.txt new file mode 100644 index 00000000..a4ba8ba0 --- /dev/null +++ b/kopete/protocols/yahoo/libkyahoo/CMakeLists.txt @@ -0,0 +1,48 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include( ConfigureChecks.cmake ) + +if( HAVE_INTTYPES_H ) + add_definitions( -DHAVE_INTTYPES_H ) +elseif( HAVE_STDINT_H ) + add_definitions( -DHAVE_STDINT_H ) +endif() + + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_BINARY_DIR} + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### kyahoo (static) ########################### + +tde_add_library( kyahoo STATIC_PIC AUTOMOC + SOURCES + client.cpp task.cpp connector.cpp inputprotocolbase.cpp + ymsgprotocol.cpp ymsgtransfer.cpp transfer.cpp + yahoobytestream.cpp bytestream.cpp yahooclientstream.cpp + yahooconnector.cpp safedelete.cpp stream.cpp sha1.c + md5.c crypt.c coreprotocol.cpp logintask.cpp libyahoo.c + yahoo_fn.c listtask.cpp statusnotifiertask.cpp + mailnotifiertask.cpp messagereceivertask.cpp + sendnotifytask.cpp sendmessagetask.cpp logofftask.cpp + changestatustask.cpp modifybuddytask.cpp picturenotifiertask.cpp + requestpicturetask.cpp yahoobuddyiconloader.cpp + stealthtask.cpp sendpicturetask.cpp webcamtask.cpp + conferencetask.cpp sendauthresptask.cpp pingtask.cpp + yabtask.cpp yabentry.cpp modifyyabtask.cpp chatsessiontask.cpp + sendfiletask.cpp filetransfernotifiertask.cpp + receivefiletask.cpp yahoochattask.cpp +) diff --git a/kopete/protocols/yahoo/libkyahoo/ConfigureChecks.cmake b/kopete/protocols/yahoo/libkyahoo/ConfigureChecks.cmake new file mode 100644 index 00000000..e7af0c6c --- /dev/null +++ b/kopete/protocols/yahoo/libkyahoo/ConfigureChecks.cmake @@ -0,0 +1,16 @@ +################################################# +# +# (C) 2010 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +check_include_file( inttypes.h HAVE_INTTYPES_H ) +check_include_file( stdint.h HAVE_STDINT_H ) + +check_include_file( string.h HAVE_STRING_H ) +check_include_file( strings.h HAVE_STRINGS_H ) diff --git a/kopete/protocols/yahoo/ui/CMakeLists.txt b/kopete/protocols/yahoo/ui/CMakeLists.txt new file mode 100644 index 00000000..4da1fb8a --- /dev/null +++ b/kopete/protocols/yahoo/ui/CMakeLists.txt @@ -0,0 +1,30 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ${CMAKE_SOURCE_DIR}/kopete/libkopete + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + + +##### kopeteyahooui (static) #################### + +tde_add_library( kopeteyahooui STATIC_PIC AUTOMOC + SOURCES + yahooadd.ui yahooeditaccountbase.ui yahooinvitelistbase.ui + yahooinvitelistimpl.cpp empty.cpp yahooverifyaccountbase.ui + yahoostealthsetting.ui yahoowebcamdialog.cpp yahoogeneralinfowidget.ui + yahoouserinfodialog.cpp yahooworkinfowidget.ui + yahoootherinfowidget.ui +) |