--- /dev/null
+Dafydd Harries <dafydd.harries@collabora.co.uk>
+Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
+Kai Vehmanen <kai.vehmanen@nokia.com>
+Youness Alaoui <youness.alaoui@collabora.co.uk>
--- /dev/null
+The Nice Glib ICE library is licensed under both the Mozilla Public License
+version 1.1 and the GNU Lesser General Public License version 2.1. For the
+full text of these licenses, see the files COPYING.MPL and COPYING.LGPL
+respectively.
--- /dev/null
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin St, 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.
+\f
+ 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.
+\f
+ 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.
+\f
+ 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.
+\f
+ 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.
+\f
+ 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.
+\f
+ 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.
+\f
+ 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.
+\f
+ 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
+\f
+ 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 St, 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!
+
+
--- /dev/null
+ MOZILLA PUBLIC LICENSE
+ Version 1.1
+
+ ---------------
+
+1. Definitions.
+
+ 1.0.1. "Commercial Use" means distribution or otherwise making the
+ Covered Code available to a third party.
+
+ 1.1. "Contributor" means each entity that creates or contributes to
+ the creation of Modifications.
+
+ 1.2. "Contributor Version" means the combination of the Original
+ Code, prior Modifications used by a Contributor, and the Modifications
+ made by that particular Contributor.
+
+ 1.3. "Covered Code" means the Original Code or Modifications or the
+ combination of the Original Code and Modifications, in each case
+ including portions thereof.
+
+ 1.4. "Electronic Distribution Mechanism" means a mechanism generally
+ accepted in the software development community for the electronic
+ transfer of data.
+
+ 1.5. "Executable" means Covered Code in any form other than Source
+ Code.
+
+ 1.6. "Initial Developer" means the individual or entity identified
+ as the Initial Developer in the Source Code notice required by Exhibit
+ A.
+
+ 1.7. "Larger Work" means a work which combines Covered Code or
+ portions thereof with code not governed by the terms of this License.
+
+ 1.8. "License" means this document.
+
+ 1.8.1. "Licensable" means having the right to grant, to the maximum
+ extent possible, whether at the time of the initial grant or
+ subsequently acquired, any and all of the rights conveyed herein.
+
+ 1.9. "Modifications" means any addition to or deletion from the
+ substance or structure of either the Original Code or any previous
+ Modifications. When Covered Code is released as a series of files, a
+ Modification is:
+ A. Any addition to or deletion from the contents of a file
+ containing Original Code or previous Modifications.
+
+ B. Any new file that contains any part of the Original Code or
+ previous Modifications.
+
+ 1.10. "Original Code" means Source Code of computer software code
+ which is described in the Source Code notice required by Exhibit A as
+ Original Code, and which, at the time of its release under this
+ License is not already Covered Code governed by this License.
+
+ 1.10.1. "Patent Claims" means any patent claim(s), now owned or
+ hereafter acquired, including without limitation, method, process,
+ and apparatus claims, in any patent Licensable by grantor.
+
+ 1.11. "Source Code" means the preferred form of the Covered Code for
+ making modifications to it, including all modules it contains, plus
+ any associated interface definition files, scripts used to control
+ compilation and installation of an Executable, or source code
+ differential comparisons against either the Original Code or another
+ well known, available Covered Code of the Contributor's choice. The
+ Source Code can be in a compressed or archival form, provided the
+ appropriate decompression or de-archiving software is widely available
+ for no charge.
+
+ 1.12. "You" (or "Your") means an individual or a legal entity
+ exercising rights under, and complying with all of the terms of, this
+ License or a future version of this License issued under Section 6.1.
+ For legal entities, "You" includes any entity which controls, is
+ controlled by, or is under common control with You. For purposes of
+ this definition, "control" means (a) the power, direct or indirect,
+ to cause the direction or management of such entity, whether by
+ contract or otherwise, or (b) ownership of more than fifty percent
+ (50%) of the outstanding shares or beneficial ownership of such
+ entity.
+
+2. Source Code License.
+
+ 2.1. The Initial Developer Grant.
+ The Initial Developer hereby grants You a world-wide, royalty-free,
+ non-exclusive license, subject to third party intellectual property
+ claims:
+ (a) under intellectual property rights (other than patent or
+ trademark) Licensable by Initial Developer to use, reproduce,
+ modify, display, perform, sublicense and distribute the Original
+ Code (or portions thereof) with or without Modifications, and/or
+ as part of a Larger Work; and
+
+ (b) under Patents Claims infringed by the making, using or
+ selling of Original Code, to make, have made, use, practice,
+ sell, and offer for sale, and/or otherwise dispose of the
+ Original Code (or portions thereof).
+
+ (c) the licenses granted in this Section 2.1(a) and (b) are
+ effective on the date Initial Developer first distributes
+ Original Code under the terms of this License.
+
+ (d) Notwithstanding Section 2.1(b) above, no patent license is
+ granted: 1) for code that You delete from the Original Code; 2)
+ separate from the Original Code; or 3) for infringements caused
+ by: i) the modification of the Original Code or ii) the
+ combination of the Original Code with other software or devices.
+
+ 2.2. Contributor Grant.
+ Subject to third party intellectual property claims, each Contributor
+ hereby grants You a world-wide, royalty-free, non-exclusive license
+
+ (a) under intellectual property rights (other than patent or
+ trademark) Licensable by Contributor, to use, reproduce, modify,
+ display, perform, sublicense and distribute the Modifications
+ created by such Contributor (or portions thereof) either on an
+ unmodified basis, with other Modifications, as Covered Code
+ and/or as part of a Larger Work; and
+
+ (b) under Patent Claims infringed by the making, using, or
+ selling of Modifications made by that Contributor either alone
+ and/or in combination with its Contributor Version (or portions
+ of such combination), to make, use, sell, offer for sale, have
+ made, and/or otherwise dispose of: 1) Modifications made by that
+ Contributor (or portions thereof); and 2) the combination of
+ Modifications made by that Contributor with its Contributor
+ Version (or portions of such combination).
+
+ (c) the licenses granted in Sections 2.2(a) and 2.2(b) are
+ effective on the date Contributor first makes Commercial Use of
+ the Covered Code.
+
+ (d) Notwithstanding Section 2.2(b) above, no patent license is
+ granted: 1) for any code that Contributor has deleted from the
+ Contributor Version; 2) separate from the Contributor Version;
+ 3) for infringements caused by: i) third party modifications of
+ Contributor Version or ii) the combination of Modifications made
+ by that Contributor with other software (except as part of the
+ Contributor Version) or other devices; or 4) under Patent Claims
+ infringed by Covered Code in the absence of Modifications made by
+ that Contributor.
+
+3. Distribution Obligations.
+
+ 3.1. Application of License.
+ The Modifications which You create or to which You contribute are
+ governed by the terms of this License, including without limitation
+ Section 2.2. The Source Code version of Covered Code may be
+ distributed only under the terms of this License or a future version
+ of this License released under Section 6.1, and You must include a
+ copy of this License with every copy of the Source Code You
+ distribute. You may not offer or impose any terms on any Source Code
+ version that alters or restricts the applicable version of this
+ License or the recipients' rights hereunder. However, You may include
+ an additional document offering the additional rights described in
+ Section 3.5.
+
+ 3.2. Availability of Source Code.
+ Any Modification which You create or to which You contribute must be
+ made available in Source Code form under the terms of this License
+ either on the same media as an Executable version or via an accepted
+ Electronic Distribution Mechanism to anyone to whom you made an
+ Executable version available; and if made available via Electronic
+ Distribution Mechanism, must remain available for at least twelve (12)
+ months after the date it initially became available, or at least six
+ (6) months after a subsequent version of that particular Modification
+ has been made available to such recipients. You are responsible for
+ ensuring that the Source Code version remains available even if the
+ Electronic Distribution Mechanism is maintained by a third party.
+
+ 3.3. Description of Modifications.
+ You must cause all Covered Code to which You contribute to contain a
+ file documenting the changes You made to create that Covered Code and
+ the date of any change. You must include a prominent statement that
+ the Modification is derived, directly or indirectly, from Original
+ Code provided by the Initial Developer and including the name of the
+ Initial Developer in (a) the Source Code, and (b) in any notice in an
+ Executable version or related documentation in which You describe the
+ origin or ownership of the Covered Code.
+
+ 3.4. Intellectual Property Matters
+ (a) Third Party Claims.
+ If Contributor has knowledge that a license under a third party's
+ intellectual property rights is required to exercise the rights
+ granted by such Contributor under Sections 2.1 or 2.2,
+ Contributor must include a text file with the Source Code
+ distribution titled "LEGAL" which describes the claim and the
+ party making the claim in sufficient detail that a recipient will
+ know whom to contact. If Contributor obtains such knowledge after
+ the Modification is made available as described in Section 3.2,
+ Contributor shall promptly modify the LEGAL file in all copies
+ Contributor makes available thereafter and shall take other steps
+ (such as notifying appropriate mailing lists or newsgroups)
+ reasonably calculated to inform those who received the Covered
+ Code that new knowledge has been obtained.
+
+ (b) Contributor APIs.
+ If Contributor's Modifications include an application programming
+ interface and Contributor has knowledge of patent licenses which
+ are reasonably necessary to implement that API, Contributor must
+ also include this information in the LEGAL file.
+
+ (c) Representations.
+ Contributor represents that, except as disclosed pursuant to
+ Section 3.4(a) above, Contributor believes that Contributor's
+ Modifications are Contributor's original creation(s) and/or
+ Contributor has sufficient rights to grant the rights conveyed by
+ this License.
+
+ 3.5. Required Notices.
+ You must duplicate the notice in Exhibit A in each file of the Source
+ Code. If it is not possible to put such notice in a particular Source
+ Code file due to its structure, then You must include such notice in a
+ location (such as a relevant directory) where a user would be likely
+ to look for such a notice. If You created one or more Modification(s)
+ You may add your name as a Contributor to the notice described in
+ Exhibit A. You must also duplicate this License in any documentation
+ for the Source Code where You describe recipients' rights or ownership
+ rights relating to Covered Code. You may choose to offer, and to
+ charge a fee for, warranty, support, indemnity or liability
+ obligations to one or more recipients of Covered Code. However, You
+ may do so only on Your own behalf, and not on behalf of the Initial
+ Developer or any Contributor. You must make it absolutely clear than
+ any such warranty, support, indemnity or liability obligation is
+ offered by You alone, and You hereby agree to indemnify the Initial
+ Developer and every Contributor for any liability incurred by the
+ Initial Developer or such Contributor as a result of warranty,
+ support, indemnity or liability terms You offer.
+
+ 3.6. Distribution of Executable Versions.
+ You may distribute Covered Code in Executable form only if the
+ requirements of Section 3.1-3.5 have been met for that Covered Code,
+ and if You include a notice stating that the Source Code version of
+ the Covered Code is available under the terms of this License,
+ including a description of how and where You have fulfilled the
+ obligations of Section 3.2. The notice must be conspicuously included
+ in any notice in an Executable version, related documentation or
+ collateral in which You describe recipients' rights relating to the
+ Covered Code. You may distribute the Executable version of Covered
+ Code or ownership rights under a license of Your choice, which may
+ contain terms different from this License, provided that You are in
+ compliance with the terms of this License and that the license for the
+ Executable version does not attempt to limit or alter the recipient's
+ rights in the Source Code version from the rights set forth in this
+ License. If You distribute the Executable version under a different
+ license You must make it absolutely clear that any terms which differ
+ from this License are offered by You alone, not by the Initial
+ Developer or any Contributor. You hereby agree to indemnify the
+ Initial Developer and every Contributor for any liability incurred by
+ the Initial Developer or such Contributor as a result of any such
+ terms You offer.
+
+ 3.7. Larger Works.
+ You may create a Larger Work by combining Covered Code with other code
+ not governed by the terms of this License and distribute the Larger
+ Work as a single product. In such a case, You must make sure the
+ requirements of this License are fulfilled for the Covered Code.
+
+4. Inability to Comply Due to Statute or Regulation.
+
+ If it is impossible for You to comply with any of the terms of this
+ License with respect to some or all of the Covered Code due to
+ statute, judicial order, or regulation then You must: (a) comply with
+ the terms of this License to the maximum extent possible; and (b)
+ describe the limitations and the code they affect. Such description
+ must be included in the LEGAL file described in Section 3.4 and must
+ be included with all distributions of the Source Code. Except to the
+ extent prohibited by statute or regulation, such description must be
+ sufficiently detailed for a recipient of ordinary skill to be able to
+ understand it.
+
+5. Application of this License.
+
+ This License applies to code to which the Initial Developer has
+ attached the notice in Exhibit A and to related Covered Code.
+
+6. Versions of the License.
+
+ 6.1. New Versions.
+ Netscape Communications Corporation ("Netscape") may publish revised
+ and/or new versions of the License from time to time. Each version
+ will be given a distinguishing version number.
+
+ 6.2. Effect of New Versions.
+ Once Covered Code has been published under a particular version of the
+ License, You may always continue to use it under the terms of that
+ version. You may also choose to use such Covered Code under the terms
+ of any subsequent version of the License published by Netscape. No one
+ other than Netscape has the right to modify the terms applicable to
+ Covered Code created under this License.
+
+ 6.3. Derivative Works.
+ If You create or use a modified version of this License (which you may
+ only do in order to apply it to code which is not already Covered Code
+ governed by this License), You must (a) rename Your license so that
+ the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape",
+ "MPL", "NPL" or any confusingly similar phrase do not appear in your
+ license (except to note that your license differs from this License)
+ and (b) otherwise make it clear that Your version of the license
+ contains terms which differ from the Mozilla Public License and
+ Netscape Public License. (Filling in the name of the Initial
+ Developer, Original Code or Contributor in the notice described in
+ Exhibit A shall not of themselves be deemed to be modifications of
+ this License.)
+
+7. DISCLAIMER OF WARRANTY.
+
+ COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF
+ DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING.
+ THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE
+ IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT,
+ YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE
+ COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER
+ OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF
+ ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+
+8. TERMINATION.
+
+ 8.1. This License and the rights granted hereunder will terminate
+ automatically if You fail to comply with terms herein and fail to cure
+ such breach within 30 days of becoming aware of the breach. All
+ sublicenses to the Covered Code which are properly granted shall
+ survive any termination of this License. Provisions which, by their
+ nature, must remain in effect beyond the termination of this License
+ shall survive.
+
+ 8.2. If You initiate litigation by asserting a patent infringement
+ claim (excluding declatory judgment actions) against Initial Developer
+ or a Contributor (the Initial Developer or Contributor against whom
+ You file such action is referred to as "Participant") alleging that:
+
+ (a) such Participant's Contributor Version directly or indirectly
+ infringes any patent, then any and all rights granted by such
+ Participant to You under Sections 2.1 and/or 2.2 of this License
+ shall, upon 60 days notice from Participant terminate prospectively,
+ unless if within 60 days after receipt of notice You either: (i)
+ agree in writing to pay Participant a mutually agreeable reasonable
+ royalty for Your past and future use of Modifications made by such
+ Participant, or (ii) withdraw Your litigation claim with respect to
+ the Contributor Version against such Participant. If within 60 days
+ of notice, a reasonable royalty and payment arrangement are not
+ mutually agreed upon in writing by the parties or the litigation claim
+ is not withdrawn, the rights granted by Participant to You under
+ Sections 2.1 and/or 2.2 automatically terminate at the expiration of
+ the 60 day notice period specified above.
+
+ (b) any software, hardware, or device, other than such Participant's
+ Contributor Version, directly or indirectly infringes any patent, then
+ any rights granted to You by such Participant under Sections 2.1(b)
+ and 2.2(b) are revoked effective as of the date You first made, used,
+ sold, distributed, or had made, Modifications made by that
+ Participant.
+
+ 8.3. If You assert a patent infringement claim against Participant
+ alleging that such Participant's Contributor Version directly or
+ indirectly infringes any patent where such claim is resolved (such as
+ by license or settlement) prior to the initiation of patent
+ infringement litigation, then the reasonable value of the licenses
+ granted by such Participant under Sections 2.1 or 2.2 shall be taken
+ into account in determining the amount or value of any payment or
+ license.
+
+ 8.4. In the event of termination under Sections 8.1 or 8.2 above,
+ all end user license agreements (excluding distributors and resellers)
+ which have been validly granted by You or any distributor hereunder
+ prior to termination shall survive termination.
+
+9. LIMITATION OF LIABILITY.
+
+ UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT
+ (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL
+ DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE,
+ OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR
+ ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY
+ CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL,
+ WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER
+ COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN
+ INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF
+ LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY
+ RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW
+ PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE
+ EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO
+ THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU.
+
+10. U.S. GOVERNMENT END USERS.
+
+ The Covered Code is a "commercial item," as that term is defined in
+ 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer
+ software" and "commercial computer software documentation," as such
+ terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48
+ C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995),
+ all U.S. Government End Users acquire Covered Code with only those
+ rights set forth herein.
+
+11. MISCELLANEOUS.
+
+ This License represents the complete agreement concerning subject
+ matter hereof. If any provision of this License is held to be
+ unenforceable, such provision shall be reformed only to the extent
+ necessary to make it enforceable. This License shall be governed by
+ California law provisions (except to the extent applicable law, if
+ any, provides otherwise), excluding its conflict-of-law provisions.
+ With respect to disputes in which at least one party is a citizen of,
+ or an entity chartered or registered to do business in the United
+ States of America, any litigation relating to this License shall be
+ subject to the jurisdiction of the Federal Courts of the Northern
+ District of California, with venue lying in Santa Clara County,
+ California, with the losing party responsible for costs, including
+ without limitation, court costs and reasonable attorneys' fees and
+ expenses. The application of the United Nations Convention on
+ Contracts for the International Sale of Goods is expressly excluded.
+ Any law or regulation which provides that the language of a contract
+ shall be construed against the drafter shall not apply to this
+ License.
+
+12. RESPONSIBILITY FOR CLAIMS.
+
+ As between Initial Developer and the Contributors, each party is
+ responsible for claims and damages arising, directly or indirectly,
+ out of its utilization of rights under this License and You agree to
+ work with Initial Developer and Contributors to distribute such
+ responsibility on an equitable basis. Nothing herein is intended or
+ shall be deemed to constitute any admission of liability.
+
+13. MULTIPLE-LICENSED CODE.
+
+ Initial Developer may designate portions of the Covered Code as
+ "Multiple-Licensed". "Multiple-Licensed" means that the Initial
+ Developer permits you to utilize portions of the Covered Code under
+ Your choice of the NPL or the alternative licenses, if any, specified
+ by the Initial Developer in the file described in Exhibit A.
+
+EXHIBIT A -Mozilla Public License.
+
+ ``The contents of this file are subject to the Mozilla Public License
+ Version 1.1 (the "License"); you may not use this file except in
+ compliance with the License. You may obtain a copy of the License at
+ http://www.mozilla.org/MPL/
+
+ Software distributed under the License is distributed on an "AS IS"
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ License for the specific language governing rights and limitations
+ under the License.
+
+ The Original Code is the Nice GLib ICE library.
+
+ The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ Corporation. All Rights Reserved.
+
+ Contributor(s): ______________________________________.
+
+ Alternatively, the contents of this file may be used under the terms
+ of the _____ license (the "[___] License"), in which case the
+ provisions of [______] License are applicable instead of those
+ above. If you wish to allow use of your version of this file only
+ under the terms of the [____] License and not to allow others to use
+ your version of this file under the MPL, indicate your decision by
+ deleting the provisions above and replace them with the notice and
+ other provisions required by the [___] License. If you do not delete
+ the provisions above, a recipient may use your version of this file
+ under either the MPL or the [___] License."
+
+ [NOTE: The text of this Exhibit A may differ slightly from the text of
+ the notices in the Source Code files of the Original Code. You should
+ use the text of this Exhibit A rather than the text found in the
+ Original Code Source Code for Your Modifications.]
+
--- /dev/null
+Installation Instructions
+*************************
+
+ Copyright (C) 1994-1996, 1999-2002, 2004-2016 Free Software
+Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved. This file is offered as-is,
+without warranty of any kind.
+
+Basic Installation
+==================
+
+ Briefly, the shell command './configure && make && make install'
+should configure, build, and install this package. The following
+more-detailed instructions are generic; see the 'README' file for
+instructions specific to this package. Some packages provide this
+'INSTALL' file but do not implement all of the features documented
+below. The lack of an optional feature in a given package is not
+necessarily a bug. More recommendations for GNU packages can be found
+in *note Makefile Conventions: (standards)Makefile Conventions.
+
+ The 'configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a 'Makefile' in each directory of the package.
+It may also create one or more '.h' files containing system-dependent
+definitions. Finally, it creates a shell script 'config.status' that
+you can run in the future to recreate the current configuration, and a
+file 'config.log' containing compiler output (useful mainly for
+debugging 'configure').
+
+ It can also use an optional file (typically called 'config.cache' and
+enabled with '--cache-file=config.cache' or simply '-C') that saves the
+results of its tests to speed up reconfiguring. Caching is disabled by
+default to prevent problems with accidental use of stale cache files.
+
+ If you need to do unusual things to compile the package, please try
+to figure out how 'configure' could check whether to do them, and mail
+diffs or instructions to the address given in the 'README' so they can
+be considered for the next release. If you are using the cache, and at
+some point 'config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+ The file 'configure.ac' (or 'configure.in') is used to create
+'configure' by a program called 'autoconf'. You need 'configure.ac' if
+you want to change it or regenerate 'configure' using a newer version of
+'autoconf'.
+
+ The simplest way to compile this package is:
+
+ 1. 'cd' to the directory containing the package's source code and type
+ './configure' to configure the package for your system.
+
+ Running 'configure' might take a while. While running, it prints
+ some messages telling which features it is checking for.
+
+ 2. Type 'make' to compile the package.
+
+ 3. Optionally, type 'make check' to run any self-tests that come with
+ the package, generally using the just-built uninstalled binaries.
+
+ 4. Type 'make install' to install the programs and any data files and
+ documentation. When installing into a prefix owned by root, it is
+ recommended that the package be configured and built as a regular
+ user, and only the 'make install' phase executed with root
+ privileges.
+
+ 5. Optionally, type 'make installcheck' to repeat any self-tests, but
+ this time using the binaries in their final installed location.
+ This target does not install anything. Running this target as a
+ regular user, particularly if the prior 'make install' required
+ root privileges, verifies that the installation completed
+ correctly.
+
+ 6. You can remove the program binaries and object files from the
+ source code directory by typing 'make clean'. To also remove the
+ files that 'configure' created (so you can compile the package for
+ a different kind of computer), type 'make distclean'. There is
+ also a 'make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+ 7. Often, you can also type 'make uninstall' to remove the installed
+ files again. In practice, not all packages have tested that
+ uninstallation works correctly, even though it is required by the
+ GNU Coding Standards.
+
+ 8. Some packages, particularly those that use Automake, provide 'make
+ distcheck', which can by used by developers to test that all other
+ targets like 'make install' and 'make uninstall' work correctly.
+ This target is generally not run by end users.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the 'configure' script does not know about. Run './configure --help'
+for details on some of the pertinent environment variables.
+
+ You can give 'configure' initial values for configuration parameters
+by setting variables in the command line or in the environment. Here is
+an example:
+
+ ./configure CC=c99 CFLAGS=-g LIBS=-lposix
+
+ *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+ You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you can use GNU 'make'. 'cd' to the
+directory where you want the object files and executables to go and run
+the 'configure' script. 'configure' automatically checks for the source
+code in the directory that 'configure' is in and in '..'. This is known
+as a "VPATH" build.
+
+ With a non-GNU 'make', it is safer to compile the package for one
+architecture at a time in the source code directory. After you have
+installed the package for one architecture, use 'make distclean' before
+reconfiguring for another architecture.
+
+ On MacOS X 10.5 and later systems, you can create libraries and
+executables that work on multiple system types--known as "fat" or
+"universal" binaries--by specifying multiple '-arch' options to the
+compiler but only a single '-arch' option to the preprocessor. Like
+this:
+
+ ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+ CPP="gcc -E" CXXCPP="g++ -E"
+
+ This is not guaranteed to produce working output in all cases, you
+may have to build one architecture at a time and combine the results
+using the 'lipo' tool if you have problems.
+
+Installation Names
+==================
+
+ By default, 'make install' installs the package's commands under
+'/usr/local/bin', include files under '/usr/local/include', etc. You
+can specify an installation prefix other than '/usr/local' by giving
+'configure' the option '--prefix=PREFIX', where PREFIX must be an
+absolute file name.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+pass the option '--exec-prefix=PREFIX' to 'configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like '--bindir=DIR' to specify different values for particular
+kinds of files. Run 'configure --help' for a list of the directories
+you can set and what kinds of files go in them. In general, the default
+for these options is expressed in terms of '${prefix}', so that
+specifying just '--prefix' will affect all of the other directory
+specifications that were not explicitly provided.
+
+ The most portable way to affect installation locations is to pass the
+correct locations to 'configure'; however, many packages provide one or
+both of the following shortcuts of passing variable assignments to the
+'make install' command line to change installation locations without
+having to reconfigure or recompile.
+
+ The first method involves providing an override variable for each
+affected directory. For example, 'make install
+prefix=/alternate/directory' will choose an alternate location for all
+directory configuration variables that were expressed in terms of
+'${prefix}'. Any directories that were specified during 'configure',
+but not in terms of '${prefix}', must each be overridden at install time
+for the entire installation to be relocated. The approach of makefile
+variable overrides for each directory variable is required by the GNU
+Coding Standards, and ideally causes no recompilation. However, some
+platforms have known limitations with the semantics of shared libraries
+that end up requiring recompilation when using this method, particularly
+noticeable in packages that use GNU Libtool.
+
+ The second method involves providing the 'DESTDIR' variable. For
+example, 'make install DESTDIR=/alternate/directory' will prepend
+'/alternate/directory' before all installation names. The approach of
+'DESTDIR' overrides is not required by the GNU Coding Standards, and
+does not work on platforms that have drive letters. On the other hand,
+it does better at avoiding recompilation issues, and works well even
+when some directory options were not specified in terms of '${prefix}'
+at 'configure' time.
+
+Optional Features
+=================
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving 'configure' the
+option '--program-prefix=PREFIX' or '--program-suffix=SUFFIX'.
+
+ Some packages pay attention to '--enable-FEATURE' options to
+'configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to '--with-PACKAGE' options, where PACKAGE
+is something like 'gnu-as' or 'x' (for the X Window System). The
+'README' should mention any '--enable-' and '--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, 'configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the 'configure' options '--x-includes=DIR' and
+'--x-libraries=DIR' to specify their locations.
+
+ Some packages offer the ability to configure how verbose the
+execution of 'make' will be. For these packages, running './configure
+--enable-silent-rules' sets the default to minimal output, which can be
+overridden with 'make V=1'; while running './configure
+--disable-silent-rules' sets the default to verbose, which can be
+overridden with 'make V=0'.
+
+Particular systems
+==================
+
+ On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC
+is not installed, it is recommended to use the following options in
+order to use an ANSI C compiler:
+
+ ./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
+
+and if that doesn't work, install pre-built binaries of GCC for HP-UX.
+
+ HP-UX 'make' updates targets which have the same time stamps as their
+prerequisites, which makes it generally unusable when shipped generated
+files such as 'configure' are involved. Use GNU 'make' instead.
+
+ On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
+parse its '<wchar.h>' header file. The option '-nodtk' can be used as a
+workaround. If GNU CC is not installed, it is therefore recommended to
+try
+
+ ./configure CC="cc"
+
+and if that doesn't work, try
+
+ ./configure CC="cc -nodtk"
+
+ On Solaris, don't put '/usr/ucb' early in your 'PATH'. This
+directory contains several dysfunctional programs; working variants of
+these programs are available in '/usr/bin'. So, if you need '/usr/ucb'
+in your 'PATH', put it _after_ '/usr/bin'.
+
+ On Haiku, software installed for all users goes in '/boot/common',
+not '/usr/local'. It is recommended to use the following options:
+
+ ./configure --prefix=/boot/common
+
+Specifying the System Type
+==========================
+
+ There may be some features 'configure' cannot figure out
+automatically, but needs to determine by the type of machine the package
+will run on. Usually, assuming the package is built to be run on the
+_same_ architectures, 'configure' can figure that out, but if it prints
+a message saying it cannot guess the machine type, give it the
+'--build=TYPE' option. TYPE can either be a short name for the system
+type, such as 'sun4', or a canonical name which has the form:
+
+ CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+ OS
+ KERNEL-OS
+
+ See the file 'config.sub' for the possible values of each field. If
+'config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+ If you are _building_ compiler tools for cross-compiling, you should
+use the option '--target=TYPE' to select the type of system they will
+produce code for.
+
+ If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with '--host=TYPE'.
+
+Sharing Defaults
+================
+
+ If you want to set default values for 'configure' scripts to share,
+you can create a site shell script called 'config.site' that gives
+default values for variables like 'CC', 'cache_file', and 'prefix'.
+'configure' looks for 'PREFIX/share/config.site' if it exists, then
+'PREFIX/etc/config.site' if it exists. Or, you can set the
+'CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all 'configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+ Variables not defined in a site shell script can be set in the
+environment passed to 'configure'. However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost. In order to avoid this problem, you should set
+them in the 'configure' command line, using 'VAR=value'. For example:
+
+ ./configure CC=/usr/local2/bin/gcc
+
+causes the specified 'gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+Unfortunately, this technique does not work for 'CONFIG_SHELL' due to an
+Autoconf limitation. Until the limitation is lifted, you can use this
+workaround:
+
+ CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+'configure' Invocation
+======================
+
+ 'configure' recognizes the following options to control how it
+operates.
+
+'--help'
+'-h'
+ Print a summary of all of the options to 'configure', and exit.
+
+'--help=short'
+'--help=recursive'
+ Print a summary of the options unique to this package's
+ 'configure', and exit. The 'short' variant lists options used only
+ in the top level, while the 'recursive' variant lists options also
+ present in any nested packages.
+
+'--version'
+'-V'
+ Print the version of Autoconf used to generate the 'configure'
+ script, and exit.
+
+'--cache-file=FILE'
+ Enable the cache: use and save the results of the tests in FILE,
+ traditionally 'config.cache'. FILE defaults to '/dev/null' to
+ disable caching.
+
+'--config-cache'
+'-C'
+ Alias for '--cache-file=config.cache'.
+
+'--quiet'
+'--silent'
+'-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to '/dev/null' (any error
+ messages will still be shown).
+
+'--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ 'configure' can determine that directory automatically.
+
+'--prefix=DIR'
+ Use DIR as the installation prefix. *note Installation Names:: for
+ more details, including other options available for fine-tuning the
+ installation locations.
+
+'--no-create'
+'-n'
+ Run the configure checks, but stop before creating any output
+ files.
+
+'configure' also accepts some other, not widely useful, options. Run
+'configure --help' for more details.
--- /dev/null
+#
+# Makefile.am for the Nice Glib ICE library
+#
+# (C) 2006, 2007 Collabora Ltd.
+# (C) 2006, 2007 Nokia Corporation. All rights reserved.
+#
+# Licensed under MPL 1.1/LGPL 2.1. See file COPYING.
+
+include common.mk
+
+ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
+
+SUBDIRS = \
+ stun \
+ socket \
+ random \
+ agent \
+ nice \
+ gst \
+ tests \
+ docs \
+ examples
+
+DISTCHECK_CONFIGURE_FLAGS = --disable-assert -enable-gtk-doc --enable-introspection
+
+EXTRA_DIST = \
+ COPYING.LGPL \
+ COPYING.MPL \
+ autogen.sh \
+ common.mk \
+ scripts/lcov.mk \
+ scripts/lcov.sh \
+ scripts/valgrind-test-driver \
+ m4/introspection.m4 \
+ meson.build \
+ meson_options.txt
+
+MAINTAINERCLEANFILES = ar-lib
+
+dist_check_SCRIPTS = \
+ scripts/check-symbols.sh \
+ scripts/make-symbol-list.sh
+
+lcov:
+ find -name '*.gcda' -delete
+ $(MAKE) $(AM_MAKEFLAGS) check
+ find -type d -name '.libs' | while read d ; do \
+ mv -fv $$d/*.gc* $$d/.. 2>/dev/null || true ; \
+ done
+ $(MAKE) lcov-report
+
+lcov-report:
+ mkdir -p lcov
+ lcov -d . -c > lcov/lcov.info
+ lcov -l lcov/lcov.info 2>/dev/null | \
+ egrep '(^/usr|/test.*\.c)' | \
+ cut -d: -f1 > lcov/lcov.remove
+ lcov -r lcov/lcov.info `cat lcov/lcov.remove` 2>/dev/null > lcov/lcov.info.clean
+ genhtml -o lcov lcov/lcov.info.clean
+
+clean-local:
+ rm -rf doc
+
+.PHONY: doc lcov-report lcov
--- /dev/null
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+#
+# Makefile.am for the Nice Glib ICE library
+#
+# (C) 2006, 2007 Collabora Ltd.
+# (C) 2006, 2007 Nokia Corporation. All rights reserved.
+#
+# Licensed under MPL 1.1/LGPL 2.1. See file COPYING.
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = .
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/as-compiler-flag.m4 \
+ $(top_srcdir)/m4/ax_check_openssl.m4 \
+ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/introspection.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \
+ $(am__configure_deps) $(dist_check_SCRIPTS) $(am__DIST_COMMON)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno config.status.lineno
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
+ ctags-recursive dvi-recursive html-recursive info-recursive \
+ install-data-recursive install-dvi-recursive \
+ install-exec-recursive install-html-recursive \
+ install-info-recursive install-pdf-recursive \
+ install-ps-recursive install-recursive installcheck-recursive \
+ installdirs-recursive pdf-recursive ps-recursive \
+ tags-recursive uninstall-recursive
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+am__recursive_targets = \
+ $(RECURSIVE_TARGETS) \
+ $(RECURSIVE_CLEAN_TARGETS) \
+ $(am__extra_recursive_targets)
+AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
+ cscope distdir distdir-am dist dist-all distcheck
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \
+ $(LISP)config.h.in
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+CSCOPE = cscope
+DIST_SUBDIRS = $(SUBDIRS)
+am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/common.mk \
+ $(srcdir)/config.h.in AUTHORS COPYING ChangeLog INSTALL NEWS \
+ README TODO ar-lib compile config.guess config.sub depcomp \
+ install-sh ltmain.sh missing
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+ if test -d "$(distdir)"; then \
+ find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \
+ && rm -rf "$(distdir)" \
+ || { sleep 5 && rm -rf "$(distdir)"; }; \
+ else :; fi
+am__post_remove_distdir = $(am__remove_distdir)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+DIST_ARCHIVES = $(distdir).tar.gz
+GZIP_ENV = --best
+DIST_TARGETS = dist-gzip
+distuninstallcheck_listfiles = find . -type f -print
+am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \
+ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$'
+distcleancheck_listfiles = find . -type f -print
+pkgincludedir = $(includedir)/nice
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCACHE_DISABLE = @CCACHE_DISABLE@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GST010_CFLAGS = @GST010_CFLAGS@
+GST010_LIBS = @GST010_LIBS@
+GST_CFLAGS = @GST_CFLAGS@
+GST_CHECK_CFLAGS = @GST_CHECK_CFLAGS@
+GST_CHECK_LIBS = @GST_CHECK_LIBS@
+GST_LIBS = @GST_LIBS@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@
+GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@
+GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@
+GTKDOC_MKPDF = @GTKDOC_MKPDF@
+GTKDOC_REBASE = @GTKDOC_REBASE@
+GUPNP_CFLAGS = @GUPNP_CFLAGS@
+GUPNP_LIBS = @GUPNP_LIBS@
+GUPNP_PACKAGES = @GUPNP_PACKAGES@
+GUPNP_PACKAGES_PRIVATE = @GUPNP_PACKAGES_PRIVATE@
+GUPNP_PACKAGES_PUBLIC = @GUPNP_PACKAGES_PUBLIC@
+HAVE_GUPNP = @HAVE_GUPNP@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@
+INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@
+INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@
+INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@
+INTROSPECTION_LIBS = @INTROSPECTION_LIBS@
+INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@
+INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
+INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBNICE_CFLAGS = @LIBNICE_CFLAGS@
+LIBNICE_LT_LDFLAGS = @LIBNICE_LT_LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBRT = @LIBRT@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NICE_PACKAGES_PRIVATE = @NICE_PACKAGES_PRIVATE@
+NICE_PACKAGES_PUBLIC = @NICE_PACKAGES_PUBLIC@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_INCLUDES = @OPENSSL_INCLUDES@
+OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+UPNP_ENABLED = @UPNP_ENABLED@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gstplugin010dir = @gstplugin010dir@
+gstplugindir = @gstplugindir@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+CLEANFILES = *.gcno *.gcda
+LOG_DRIVER = $(top_srcdir)/scripts/valgrind-test-driver
+ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
+SUBDIRS = \
+ stun \
+ socket \
+ random \
+ agent \
+ nice \
+ gst \
+ tests \
+ docs \
+ examples
+
+DISTCHECK_CONFIGURE_FLAGS = --disable-assert -enable-gtk-doc --enable-introspection
+EXTRA_DIST = \
+ COPYING.LGPL \
+ COPYING.MPL \
+ autogen.sh \
+ common.mk \
+ scripts/lcov.mk \
+ scripts/lcov.sh \
+ scripts/valgrind-test-driver \
+ m4/introspection.m4 \
+ meson.build \
+ meson_options.txt
+
+MAINTAINERCLEANFILES = ar-lib
+dist_check_SCRIPTS = \
+ scripts/check-symbols.sh \
+ scripts/make-symbol-list.sh
+
+all: config.h
+ $(MAKE) $(AM_MAKEFLAGS) all-recursive
+
+.SUFFIXES:
+am--refresh: Makefile
+ @:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/common.mk $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \
+ $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ echo ' $(SHELL) ./config.status'; \
+ $(SHELL) ./config.status;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \
+ esac;
+$(srcdir)/common.mk $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ $(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ $(am__cd) $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+$(am__aclocal_m4_deps):
+
+config.h: stamp-h1
+ @test -f $@ || rm -f stamp-h1
+ @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1
+
+stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
+ @rm -f stamp-h1
+ cd $(top_builddir) && $(SHELL) ./config.status config.h
+$(srcdir)/config.h.in: $(am__configure_deps)
+ ($(am__cd) $(top_srcdir) && $(AUTOHEADER))
+ rm -f stamp-h1
+ touch $@
+
+distclean-hdr:
+ -rm -f config.h stamp-h1
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool config.lt
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run 'make' without going through this Makefile.
+# To change the values of 'make' variables: instead of editing Makefiles,
+# (1) if the variable is set in 'config.status', edit 'config.status'
+# (which will cause the Makefiles to be regenerated when you run 'make');
+# (2) otherwise, pass the desired values on the 'make' command line.
+$(am__recursive_targets):
+ @fail=; \
+ if $(am__make_keepgoing); then \
+ failcom='fail=yes'; \
+ else \
+ failcom='exit 1'; \
+ fi; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-recursive
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-recursive
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscope: cscope.files
+ test ! -s cscope.files \
+ || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS)
+clean-cscope:
+ -rm -f cscope.files
+cscope.files: clean-cscope cscopelist
+cscopelist: cscopelist-recursive
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+ -rm -f cscope.out cscope.in.out cscope.po.out cscope.files
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ $(am__remove_distdir)
+ test -d "$(distdir)" || mkdir "$(distdir)"
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ $(am__make_dryrun) \
+ || test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+ -test -n "$(am__skip_mode_fix)" \
+ || find "$(distdir)" -type d ! -perm -755 \
+ -exec chmod u+rwx,go+rx {} \; -o \
+ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
+ || chmod -R a+r "$(distdir)"
+dist-gzip: distdir
+ tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz
+ $(am__post_remove_distdir)
+
+dist-bzip2: distdir
+ tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2
+ $(am__post_remove_distdir)
+
+dist-lzip: distdir
+ tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz
+ $(am__post_remove_distdir)
+
+dist-xz: distdir
+ tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz
+ $(am__post_remove_distdir)
+
+dist-tarZ: distdir
+ @echo WARNING: "Support for distribution archives compressed with" \
+ "legacy program 'compress' is deprecated." >&2
+ @echo WARNING: "It will be removed altogether in Automake 2.0" >&2
+ tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+ $(am__post_remove_distdir)
+
+dist-shar: distdir
+ @echo WARNING: "Support for shar distribution archives is" \
+ "deprecated." >&2
+ @echo WARNING: "It will be removed altogether in Automake 2.0" >&2
+ shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz
+ $(am__post_remove_distdir)
+
+dist-zip: distdir
+ -rm -f $(distdir).zip
+ zip -rq $(distdir).zip $(distdir)
+ $(am__post_remove_distdir)
+
+dist dist-all:
+ $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:'
+ $(am__post_remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration. Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+ case '$(DIST_ARCHIVES)' in \
+ *.tar.gz*) \
+ eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\
+ *.tar.bz2*) \
+ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
+ *.tar.lz*) \
+ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\
+ *.tar.xz*) \
+ xz -dc $(distdir).tar.xz | $(am__untar) ;;\
+ *.tar.Z*) \
+ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+ *.shar.gz*) \
+ eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\
+ *.zip*) \
+ unzip $(distdir).zip ;;\
+ esac
+ chmod -R a-w $(distdir)
+ chmod u+w $(distdir)
+ mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst
+ chmod a-w $(distdir)
+ test -d $(distdir)/_build || exit 0; \
+ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+ && am__cwd=`pwd` \
+ && $(am__cd) $(distdir)/_build/sub \
+ && ../../configure \
+ $(AM_DISTCHECK_CONFIGURE_FLAGS) \
+ $(DISTCHECK_CONFIGURE_FLAGS) \
+ --srcdir=../.. --prefix="$$dc_install_base" \
+ && $(MAKE) $(AM_MAKEFLAGS) \
+ && $(MAKE) $(AM_MAKEFLAGS) dvi \
+ && $(MAKE) $(AM_MAKEFLAGS) check \
+ && $(MAKE) $(AM_MAKEFLAGS) install \
+ && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+ && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+ distuninstallcheck \
+ && chmod -R a-w "$$dc_install_base" \
+ && ({ \
+ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+ } || { rm -rf "$$dc_destdir"; exit 1; }) \
+ && rm -rf "$$dc_destdir" \
+ && $(MAKE) $(AM_MAKEFLAGS) dist \
+ && rm -rf $(DIST_ARCHIVES) \
+ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
+ && cd "$$am__cwd" \
+ || exit 1
+ $(am__post_remove_distdir)
+ @(echo "$(distdir) archives ready for distribution: "; \
+ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
+distuninstallcheck:
+ @test -n '$(distuninstallcheck_dir)' || { \
+ echo 'ERROR: trying to run $@ with an empty' \
+ '$$(distuninstallcheck_dir)' >&2; \
+ exit 1; \
+ }; \
+ $(am__cd) '$(distuninstallcheck_dir)' || { \
+ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \
+ exit 1; \
+ }; \
+ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \
+ || { echo "ERROR: files left after uninstall:" ; \
+ if test -n "$(DESTDIR)"; then \
+ echo " (check DESTDIR support)"; \
+ fi ; \
+ $(distuninstallcheck_listfiles) ; \
+ exit 1; } >&2
+distcleancheck: distclean
+ @if test '$(srcdir)' = . ; then \
+ echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+ exit 1 ; \
+ fi
+ @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+ || { echo "ERROR: files left in build directory after distclean:" ; \
+ $(distcleancheck_listfiles) ; \
+ exit 1; } >&2
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) $(dist_check_SCRIPTS)
+check: check-recursive
+all-am: Makefile config.h
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool clean-local mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-hdr \
+ distclean-libtool distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+ -rm -rf $(top_srcdir)/autom4te.cache
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(am__recursive_targets) all check-am install-am install-strip
+
+.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \
+ am--refresh check check-am clean clean-cscope clean-generic \
+ clean-libtool clean-local cscope cscopelist-am ctags ctags-am \
+ dist dist-all dist-bzip2 dist-gzip dist-lzip dist-shar \
+ dist-tarZ dist-xz dist-zip distcheck distclean \
+ distclean-generic distclean-hdr distclean-libtool \
+ distclean-tags distcleancheck distdir distuninstallcheck dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs installdirs-am \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags tags-am uninstall uninstall-am
+
+.PRECIOUS: Makefile
+
+
+check-valgrind:
+ $(MAKE) TESTS_ENVIRONMENT="USE_VALGRIND=1 " check
+
+.PHONY: check-valgrind
+
+lcov:
+ find -name '*.gcda' -delete
+ $(MAKE) $(AM_MAKEFLAGS) check
+ find -type d -name '.libs' | while read d ; do \
+ mv -fv $$d/*.gc* $$d/.. 2>/dev/null || true ; \
+ done
+ $(MAKE) lcov-report
+
+lcov-report:
+ mkdir -p lcov
+ lcov -d . -c > lcov/lcov.info
+ lcov -l lcov/lcov.info 2>/dev/null | \
+ egrep '(^/usr|/test.*\.c)' | \
+ cut -d: -f1 > lcov/lcov.remove
+ lcov -r lcov/lcov.info `cat lcov/lcov.remove` 2>/dev/null > lcov/lcov.info.clean
+ genhtml -o lcov lcov/lcov.info.clean
+
+clean-local:
+ rm -rf doc
+
+.PHONY: doc lcov-report lcov
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null
+libnice 0.1.16 (2019-05-09)
+===========================
+Add API to make it easier to implement ICE trickle
+Add async closing of agent, to cleanly close TURN allocations
+Add Google non-standard NOMINATION STUN attribute
+Fix tests on Windows
+Fix some racy tests
+
+libnice 0.1.15 (2018-12-27)
+===========================
+Add support for Regular Nomination
+Removal of the global lock over all agents
+Add method to compare candidate targets
+Added optional Meson build system, future releases will remove autotools
+Renamed all members of PseudoTcpState enum (compile-time API change)
+Now drops all packets from addresses that have not been validated by an ICE check
+Multiple improvements to ICE interoperability
+Improved RFC compliance
+Improved OC2007 compatibility mode alternate-server support
+
+libnice 0.1.14 (2017-04-03)
+===========================
+Improved RFC compliance
+Split verbose logs into a separate option
+Numerous bug fixes
+Use GnuTLS for hash functions
+Implement NewReno in PseudoTCP
+Requires GLib 2.44 GnuTLS 2.12
+
+libnice 0.1.13 (2015-04-28)
+===========================
+Fix build on non-Windows platforms that don't have getifaddrs()
+Fix build regression on Windows
+
+libnice 0.1.12 (2015-04-22)
+===========================
+Fix regression in SDP parser
+Make examples work on Windows
+Bug fixes on nicesrc
+
+libnice 0.1.11 (2015-04-20)
+===========================
+API: nice_agent_set_local_credentials() for WebRTC
+Nicesink: support GstBufferList
+Better warnings on programming errors
+Build fixes for Solaris and Windows
+Bug and documentation fixes
+
+libnice 0.1.10 (2015-01-28)
+===========================
+Fix bug on component change on the sink
+
+libnice 0.1.9 (2015-01-28)
+==========================
+Make it possible to statically build the GStreamer plugins
+Bug fixes, in particular fix compatibility with coTurn servers
+Documentation fixes
+
+libnice 0.1.8 (2014-10-09)
+==========================
+Added FIN-ACK behavior in the PseudoTCP
+ICE-TCP, both standard mode and Microsoft compatible
+Microsoft compatible TURN-TCP
+API: nice_address_equal_no_port() to compare NiceAddresses ignoring the port
+API: nice_agent_get_component_state() to get the current component state
+API: agent:keepalive-conncheck to make the agent use conncheck as keepalives
+ and fail the connection if there is no answer
+API: agent:ice-tcp, agent:udp-tcp to control ICE-UDP vs ICE-TCP behaviours
+API: agent:bytestream-tcp to know if the send/receives in reliable mode create full packets or not
+API: New signals agent::new-selected-pair-full, agent::new-candidate-full,
+ agent::new-remote-candidate-full which include the NiceCandidates directly
+API: Deprecated agent::new-selected-pair and agent::new-candidate and
+ agent::new-remote-candidate signals
+Now all signals are emitted at the function return time
+
+libnice 0.1.7 (2014-05-05)
+==========================
+Fix undesired API change that broke Farstream unit testsx
+
+libnice 0.1.6 (2014-04-28)
+==========================
+API: nice_agent_restart_stream() to do a ICE restart on a single strema
+API: nice_component_state_to_string() to get a printable name for a component
+ state
+API: nice_agent_forget_relays() to forget the relays set for a
+ specific component, along with nice_agent_restart_stream(), it allows
+ changing the current relay without dropping the connection.
+It is now possible to add relays after the initial candidate gathering.
+Many bug fixes
+
+libnice 0.1.5 (2014-03-06)
+==========================
+
+API: nice_agent_recv() and nice_agent_recv_nonblocking() as an alternative to
+ the nice_agent_attach_recv()
+API: nice_agent_recv_messages() and nice_agent_recv_messages_nonblocking() to
+ receive multiple messages at the same time
+API: nice_agent_get_io_stream() to get a GIOStream in reliable mode
+API: nice_agent_get_selected_socket() to extract the selected GSocket
+Import Google's newer PseudoTCP code including window scaling
+Improve PseudoTCP performance
+Improve performance
+Build fixes
+
+libnice 0.1.4 (2013-02-22)
+==========================
+
+Fix issue with dribble mode
+Fix issue with TURN permissions
+Fix missing win32 directory from release archive
+Fix support for OC2007
+Added new nice_address_ip_vesion API
+Added new nice_agent_get_selected_pair API
+Added new SDP parsing and generation API
+Added simple examples (simple, threaded and sdp usages examples)
+
+libnice 0.1.3 (2012-09-13)
+==========================
+
+Dribble mode: You can set remote candidates while gathering the local ones
+Add support for GStreamer 1.0, will compile plugins for both 1.0 and 0.10 by default
+Cache GSocketAddress in UdpBsdSocket, creating it is very slow
+
+libnice 0.1.2 (2012-04-03)
+==========================
+
+Fix a bug where a controlled agent may never go to READY if it received early conncheck
+Restart connchecks on a failed candidate pair when receiving a triggered check
+Fix a bug where gathering-done signal could be sent before UPnP mapping finishes
+Fix a race condition where setting remote-candidates on a gathered stream failed if another stream was gathering
+Many fixes to complete and stabilize TURN support
+Fix a bug in proxy support where TURN packets were misread
+Refactor libnice to use GSocket which works around a glib limitation of g_io_channel on windows
+Fix a bug with receiving error messages during conncheck
+Fix a possible infinite loop bug
+Fix memory leaks and multi-threaded race conditions
+Better compatibility for BSD and Mingw
+Added support files for Visual Studio compilation
+Various fixes to UPnP support
+Fixes to the build system
+
+libnice 0.1.1 (2011-09-07)
+==========================
+
+Fixed BSD and Solaris compatibility
+Fixed PPC64 symbol test
+Removed a few possible leak/bugs
+Fixed compatibility with google's recent protocol change
+
+libnice 0.1.0 (2011-01-20)
+==========================
+
+Added nice_candidate_copy to the public API
+Make stun_timer timeouts configurable (Break API and ABI)
+Add compatibility support for MSOC 2007 and MSOC 2007 R2
+Add MS-TURN support for MSOC
+Added and completed TURN RFC 5766 support
+Add a nice_agent_set_port_range API to force a component to use a specific port
+Fix various bugs and memory leaks
+Improve documentation
+
+libnice 0.0.13 (2010-07-20)
+==========================
+
+Add support for IPv6
+Fix crc32 function conflict with libz.so
+Various bug fixing and code cleaning
+Validate the remote candidate address before adding it
+
+libnice 0.0.12 (2010-05-19)
+==========================
+
+Update compatibility to RFC5245
+Fix a memory corruption bug
+Fix a possible buffer overflow with socks5 proxies
+
+libnice 0.0.11 (2010-03-18)
+===========================
+
+Handle EAGAIN for UDP sockets
+Fix coverity warnings
+Fix a bug with TURN and Channel Bindings
+Add a reliable transport mode using libjingle's PseudoTcp implementation
+Various fixes
+
+libnice 0.0.10 (2009-11-04)
+===========================
+
+Fix some memory leaks with the gstreamer elements
+Fix username/foundation for google TURN candidates
+Fix the sending of hundreds of connectivity checks at once the stream is connected
+Fix BSD support
+Fix reprocessing of already processed early incoming checks when in dribble-mode
+Fix a rare crash with failing relay candidates allocations
+Add a stun_agent_set_software API
+Add a nice_agent_set_software API
+
+libnice 0.0.9 (2009-07-31)
+===========================
+
+Fix some more issues with peer-reflexive candidates in google mode (for early incoming checks)
+Fix SHA1 algorithm when strict aliasing is used
+Fix google mode connectivity with discovered remote peer reflexive candidates
+Fix google/msn mode by not limiting the conncheck list
+Fix the interfaces discovery by using getifaddrs
+Fix compilation on Mac OS X
+Add ToS support to the sockets
+
+
+libnice 0.0.8 (2009-06-19)
+===========================
+
+Remove deprecated g_strcasecmp call
+Use addr instead of base_addr on assigning remote peer-reflexive candidates (fixes crash)
+Use a global mutex and g_source_is_destroyed to avoid race conditions (fixes crashes)
+Unlock the mutex before calling the recv callback
+
+libnice 0.0.7 (2009-06-11)
+===========================
+
+Added UPnP Support
+Fix a race condition when destroying the nice agent
+Stun headers are now installed
+Unset timer's source if they return FALSE
+Fix interoperability with gtalk2voip.com
+Avoid a race condition where a candidate has the wrong user/pass
+Add support for delayed setting of the remote candidates in google mode
+Better connectivity support and race condition fixes
+Keepalive connchecks do not change the state if they fail but data was still received
+Fix foundation generation for remote peer reflexive candidates
+Drop packets when using TCP and the bandwidth is too slow for the data output
+
+
+libnice 0.0.6 (2009-03-31)
+===========================
+
+Fix connectivity checks for detecting when we loose the connection
+Fix a race condition with gtalk that made the call silent after 30 seconds
+Robustness checks with regards to relay information
+Fix a race condition crash with retransmission ticks
+Added a new STUN API : stun_agent_forget_transaction
+Fix a possible crash if tcp-turn is shutdown early in the process
+Fix a crash when a stream is removed
+Fix MSN support by disable keepalive connchecks
+
+
+libnice 0.0.5 (2009-03-04)
+===========================
+
+Name change from nice to libnice
+Added support for HTTP proxies
+Added a nice_interfaces API to query the local interfaces/ips
+Fixed libnice when used in dribble mode
+Fix a data corruption issue with the SHA1 algorithm
+Endianness gets checked at runtime so libnice should compile and work everywhere
+Add compatiblity for WLM2009 ICE
+Export libstun API and add documentation for libstun
+Add connectivity checks during the connection to detect when the peer gets disconnected
+Bug fixes and code cleaning
+
+
+nice 0.0.4 (2008-12-17)
+========================
+
+Fix compilation for 64bits systems
+Revert the use of netbuffer in the gstreamer elements
+Added support for pseudossl-tcp TURN relay for Google
+Added support for SOCKS5 proxy servers for TCP relaying
+Bug fixes and code cleaning
+
+nice 0.0.3 (2008-11-25)
+========================
+
+Stable google talk support
+Added TCP TURN relay support for google.
+Removed openssl dependency.
+
+nice 0.0.2 (2008-11-12)
+========================
+
+Better support for google talk compatibility mode as well as UDP TURN relay compatibility for Google.
+Removed -Werror compile flag for releases
+
+nice 0.0.1 (2008-11-05)
+========================
+
+Initial release of libnice.
+It has compatibility support for the latest ICE draft 19, as well as google talk and MSN compatibility.
+It also has support for TURN relays using TURN draft 9 if you're in ICE draft 19 compatibility, or specific Google/MSN relay support if you're in Google/MSN compatibility mode.
+The library is multiplatform and should compile fine on Linux, Mac and Windows systems.
--- /dev/null
+
+Nice: GLib ICE library
+======================
+
+Copyright
+---------
+
+ (C) 2006-2018 Collabora Ltd.
+ (C) 2006-2011 Nokia Corporation
+
+License
+-------
+
+See the file COPYING.
+
+Requirements
+------------
+
+ glib >= 2.44
+ pkg-config
+ gnutls >= 2.12.0 or OpenSSL
+ gupnp-igd >= 0.1.2 (optional)
+ gstreamer-0.10 >= 0.10.0 (optional)
+ gstreamer-1.0 (optional)
+
+Build instructions
+------------------
+
+To build on Linux and Mac, you only need to type the usual commands :
+ ./configure && make && sudo make install
+Please refer to the INSTALL file for more details.
+If you are building from git, you must first run the ./autogen.sh script
+to generate the configure file for you.
+
+Structure
+---------
+
+ agent/ - ICE agent
+ docs/ - Design and API documentation
+ gst/ - Gstreamer elements
+ nice/ - libnice library
+ random/ - random number generation
+ socket/ - Socket abstraction layer
+ stun/ - STUN implementation
+ tests/ - Unit tests
+
+Relevant standards
+------------------
+
+These standards are relevant to nice's current implementation.
+
+ICE RFC 5245
+ http://tools.ietf.org/html/rfc5245
+STUN
+ http://tools.ietf.org/html/rfc3489
+ http://tools.ietf.org/html/rfc5389
+TURN
+ http://tools.ietf.org/html/rfc5766
+RTP
+ http://tools.ietf.org/html/rfc3550
+XMPP Jingle ICE transport
+ http://www.xmpp.org/extensions/xep-0176.html
+
+In future, nice may additionally support the following standards.
+
+NAT-PMP
+ http://files.dns-sd.org/draft-cheshire-nat-pmp.txt
+
+
--- /dev/null
+- High priority:
+Refactor/cleanup conncheck.c and discovery.c
+Add a nice_agent_create_source()
+Implement SIP-style forking
+nice_socket_recv returns -1 means we must close the nice_socket and stop all connchecks/candidates and reelect if was eleected...
+Bytestream mode (non packetized) for standard ICE-TCP
+Standard (RFC 6062) TURN-TCP
+Server reflexive candidates for ICE-TCP (aka STUN TCP)
+Clear unused local sockets (freeing file descriptions in the process) on READY
+TCP simultaneous-open (S-O)
+
+- Low priority:
+Add HTTP Digest support
+check for the cookie and act accordingly for incoming messages.
--- /dev/null
+# generated automatically by aclocal 1.16.1 -*- Autoconf -*-
+
+# Copyright (C) 1996-2018 Free Software Foundation, Inc.
+
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
+m4_ifndef([AC_AUTOCONF_VERSION],
+ [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],,
+[m4_warning([this file was generated for autoconf 2.69.
+You have another version of autoconf. It may work, but is not guaranteed to.
+If you have problems, you may need to regenerate the build system entirely.
+To do so, use the procedure documented by the package, typically 'autoreconf'.])])
+
+# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
+# serial 11 (pkg-config-0.29.1)
+
+dnl Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
+dnl Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com>
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful, but
+dnl WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+dnl General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+dnl 02111-1307, USA.
+dnl
+dnl As a special exception to the GNU General Public License, if you
+dnl distribute this file as part of a program that contains a
+dnl configuration script generated by Autoconf, you may include it under
+dnl the same distribution terms that you use for the rest of that
+dnl program.
+
+dnl PKG_PREREQ(MIN-VERSION)
+dnl -----------------------
+dnl Since: 0.29
+dnl
+dnl Verify that the version of the pkg-config macros are at least
+dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's
+dnl installed version of pkg-config, this checks the developer's version
+dnl of pkg.m4 when generating configure.
+dnl
+dnl To ensure that this macro is defined, also add:
+dnl m4_ifndef([PKG_PREREQ],
+dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])])
+dnl
+dnl See the "Since" comment for each macro you use to see what version
+dnl of the macros you require.
+m4_defun([PKG_PREREQ],
+[m4_define([PKG_MACROS_VERSION], [0.29.1])
+m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1,
+ [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])])
+])dnl PKG_PREREQ
+
+dnl PKG_PROG_PKG_CONFIG([MIN-VERSION])
+dnl ----------------------------------
+dnl Since: 0.16
+dnl
+dnl Search for the pkg-config tool and set the PKG_CONFIG variable to
+dnl first found in the path. Checks that the version of pkg-config found
+dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is
+dnl used since that's the first version where most current features of
+dnl pkg-config existed.
+AC_DEFUN([PKG_PROG_PKG_CONFIG],
+[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
+m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
+m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$])
+AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])
+AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
+AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+ AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
+fi
+if test -n "$PKG_CONFIG"; then
+ _pkg_min_version=m4_default([$1], [0.9.0])
+ AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
+ if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ PKG_CONFIG=""
+ fi
+fi[]dnl
+])dnl PKG_PROG_PKG_CONFIG
+
+dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+dnl -------------------------------------------------------------------
+dnl Since: 0.18
+dnl
+dnl Check to see whether a particular set of modules exists. Similar to
+dnl PKG_CHECK_MODULES(), but does not set variables or print errors.
+dnl
+dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+dnl only at the first occurence in configure.ac, so if the first place
+dnl it's called might be skipped (such as if it is within an "if", you
+dnl have to call PKG_CHECK_EXISTS manually
+AC_DEFUN([PKG_CHECK_EXISTS],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+if test -n "$PKG_CONFIG" && \
+ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
+ m4_default([$2], [:])
+m4_ifvaln([$3], [else
+ $3])dnl
+fi])
+
+dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
+dnl ---------------------------------------------
+dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting
+dnl pkg_failed based on the result.
+m4_define([_PKG_CONFIG],
+[if test -n "$$1"; then
+ pkg_cv_[]$1="$$1"
+ elif test -n "$PKG_CONFIG"; then
+ PKG_CHECK_EXISTS([$3],
+ [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes ],
+ [pkg_failed=yes])
+ else
+ pkg_failed=untried
+fi[]dnl
+])dnl _PKG_CONFIG
+
+dnl _PKG_SHORT_ERRORS_SUPPORTED
+dnl ---------------------------
+dnl Internal check to see if pkg-config supports short errors.
+AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi[]dnl
+])dnl _PKG_SHORT_ERRORS_SUPPORTED
+
+
+dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+dnl [ACTION-IF-NOT-FOUND])
+dnl --------------------------------------------------------------
+dnl Since: 0.4.0
+dnl
+dnl Note that if there is a possibility the first call to
+dnl PKG_CHECK_MODULES might not happen, you should be sure to include an
+dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
+AC_DEFUN([PKG_CHECK_MODULES],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
+AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
+
+pkg_failed=no
+AC_MSG_CHECKING([for $1])
+
+_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
+_PKG_CONFIG([$1][_LIBS], [libs], [$2])
+
+m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
+and $1[]_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.])
+
+if test $pkg_failed = yes; then
+ AC_MSG_RESULT([no])
+ _PKG_SHORT_ERRORS_SUPPORTED
+ if test $_pkg_short_errors_supported = yes; then
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
+ else
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
+
+ m4_default([$4], [AC_MSG_ERROR(
+[Package requirements ($2) were not met:
+
+$$1_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+_PKG_TEXT])[]dnl
+ ])
+elif test $pkg_failed = untried; then
+ AC_MSG_RESULT([no])
+ m4_default([$4], [AC_MSG_FAILURE(
+[The pkg-config script could not be found or is too old. Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+_PKG_TEXT
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl
+ ])
+else
+ $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
+ $1[]_LIBS=$pkg_cv_[]$1[]_LIBS
+ AC_MSG_RESULT([yes])
+ $3
+fi[]dnl
+])dnl PKG_CHECK_MODULES
+
+
+dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+dnl [ACTION-IF-NOT-FOUND])
+dnl ---------------------------------------------------------------------
+dnl Since: 0.29
+dnl
+dnl Checks for existence of MODULES and gathers its build flags with
+dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags
+dnl and VARIABLE-PREFIX_LIBS from --libs.
+dnl
+dnl Note that if there is a possibility the first call to
+dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to
+dnl include an explicit call to PKG_PROG_PKG_CONFIG in your
+dnl configure.ac.
+AC_DEFUN([PKG_CHECK_MODULES_STATIC],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+_save_PKG_CONFIG=$PKG_CONFIG
+PKG_CONFIG="$PKG_CONFIG --static"
+PKG_CHECK_MODULES($@)
+PKG_CONFIG=$_save_PKG_CONFIG[]dnl
+])dnl PKG_CHECK_MODULES_STATIC
+
+
+dnl PKG_INSTALLDIR([DIRECTORY])
+dnl -------------------------
+dnl Since: 0.27
+dnl
+dnl Substitutes the variable pkgconfigdir as the location where a module
+dnl should install pkg-config .pc files. By default the directory is
+dnl $libdir/pkgconfig, but the default can be changed by passing
+dnl DIRECTORY. The user can override through the --with-pkgconfigdir
+dnl parameter.
+AC_DEFUN([PKG_INSTALLDIR],
+[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])])
+m4_pushdef([pkg_description],
+ [pkg-config installation directory @<:@]pkg_default[@:>@])
+AC_ARG_WITH([pkgconfigdir],
+ [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],,
+ [with_pkgconfigdir=]pkg_default)
+AC_SUBST([pkgconfigdir], [$with_pkgconfigdir])
+m4_popdef([pkg_default])
+m4_popdef([pkg_description])
+])dnl PKG_INSTALLDIR
+
+
+dnl PKG_NOARCH_INSTALLDIR([DIRECTORY])
+dnl --------------------------------
+dnl Since: 0.27
+dnl
+dnl Substitutes the variable noarch_pkgconfigdir as the location where a
+dnl module should install arch-independent pkg-config .pc files. By
+dnl default the directory is $datadir/pkgconfig, but the default can be
+dnl changed by passing DIRECTORY. The user can override through the
+dnl --with-noarch-pkgconfigdir parameter.
+AC_DEFUN([PKG_NOARCH_INSTALLDIR],
+[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])])
+m4_pushdef([pkg_description],
+ [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@])
+AC_ARG_WITH([noarch-pkgconfigdir],
+ [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],,
+ [with_noarch_pkgconfigdir=]pkg_default)
+AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir])
+m4_popdef([pkg_default])
+m4_popdef([pkg_description])
+])dnl PKG_NOARCH_INSTALLDIR
+
+
+dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
+dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+dnl -------------------------------------------
+dnl Since: 0.28
+dnl
+dnl Retrieves the value of the pkg-config variable for the given module.
+AC_DEFUN([PKG_CHECK_VAR],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
+
+_PKG_CONFIG([$1], [variable="][$3]["], [$2])
+AS_VAR_COPY([$1], [pkg_cv_][$1])
+
+AS_VAR_IF([$1], [""], [$5], [$4])dnl
+])dnl PKG_CHECK_VAR
+
+dnl PKG_WITH_MODULES(VARIABLE-PREFIX, MODULES,
+dnl [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND],
+dnl [DESCRIPTION], [DEFAULT])
+dnl ------------------------------------------
+dnl
+dnl Prepare a "--with-" configure option using the lowercase
+dnl [VARIABLE-PREFIX] name, merging the behaviour of AC_ARG_WITH and
+dnl PKG_CHECK_MODULES in a single macro.
+AC_DEFUN([PKG_WITH_MODULES],
+[
+m4_pushdef([with_arg], m4_tolower([$1]))
+
+m4_pushdef([description],
+ [m4_default([$5], [build with ]with_arg[ support])])
+
+m4_pushdef([def_arg], [m4_default([$6], [auto])])
+m4_pushdef([def_action_if_found], [AS_TR_SH([with_]with_arg)=yes])
+m4_pushdef([def_action_if_not_found], [AS_TR_SH([with_]with_arg)=no])
+
+m4_case(def_arg,
+ [yes],[m4_pushdef([with_without], [--without-]with_arg)],
+ [m4_pushdef([with_without],[--with-]with_arg)])
+
+AC_ARG_WITH(with_arg,
+ AS_HELP_STRING(with_without, description[ @<:@default=]def_arg[@:>@]),,
+ [AS_TR_SH([with_]with_arg)=def_arg])
+
+AS_CASE([$AS_TR_SH([with_]with_arg)],
+ [yes],[PKG_CHECK_MODULES([$1],[$2],$3,$4)],
+ [auto],[PKG_CHECK_MODULES([$1],[$2],
+ [m4_n([def_action_if_found]) $3],
+ [m4_n([def_action_if_not_found]) $4])])
+
+m4_popdef([with_arg])
+m4_popdef([description])
+m4_popdef([def_arg])
+
+])dnl PKG_WITH_MODULES
+
+dnl PKG_HAVE_WITH_MODULES(VARIABLE-PREFIX, MODULES,
+dnl [DESCRIPTION], [DEFAULT])
+dnl -----------------------------------------------
+dnl
+dnl Convenience macro to trigger AM_CONDITIONAL after PKG_WITH_MODULES
+dnl check._[VARIABLE-PREFIX] is exported as make variable.
+AC_DEFUN([PKG_HAVE_WITH_MODULES],
+[
+PKG_WITH_MODULES([$1],[$2],,,[$3],[$4])
+
+AM_CONDITIONAL([HAVE_][$1],
+ [test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"])
+])dnl PKG_HAVE_WITH_MODULES
+
+dnl PKG_HAVE_DEFINE_WITH_MODULES(VARIABLE-PREFIX, MODULES,
+dnl [DESCRIPTION], [DEFAULT])
+dnl ------------------------------------------------------
+dnl
+dnl Convenience macro to run AM_CONDITIONAL and AC_DEFINE after
+dnl PKG_WITH_MODULES check. HAVE_[VARIABLE-PREFIX] is exported as make
+dnl and preprocessor variable.
+AC_DEFUN([PKG_HAVE_DEFINE_WITH_MODULES],
+[
+PKG_HAVE_WITH_MODULES([$1],[$2],[$3],[$4])
+
+AS_IF([test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"],
+ [AC_DEFINE([HAVE_][$1], 1, [Enable ]m4_tolower([$1])[ support])])
+])dnl PKG_HAVE_DEFINE_WITH_MODULES
+
+# Copyright (C) 2002-2018 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+# (This private macro should not be called outside this file.)
+AC_DEFUN([AM_AUTOMAKE_VERSION],
+[am__api_version='1.16'
+dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
+dnl require some minimum version. Point them to the right macro.
+m4_if([$1], [1.16.1], [],
+ [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
+])
+
+# _AM_AUTOCONF_VERSION(VERSION)
+# -----------------------------
+# aclocal traces this macro to find the Autoconf version.
+# This is a private macro too. Using m4_define simplifies
+# the logic in aclocal, which can simply ignore this definition.
+m4_define([_AM_AUTOCONF_VERSION], [])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
+# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+[AM_AUTOMAKE_VERSION([1.16.1])dnl
+m4_ifndef([AC_AUTOCONF_VERSION],
+ [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
+
+# Copyright (C) 2011-2018 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_AR([ACT-IF-FAIL])
+# -------------------------
+# Try to determine the archiver interface, and trigger the ar-lib wrapper
+# if it is needed. If the detection of archiver interface fails, run
+# ACT-IF-FAIL (default is to abort configure with a proper error message).
+AC_DEFUN([AM_PROG_AR],
+[AC_BEFORE([$0], [LT_INIT])dnl
+AC_BEFORE([$0], [AC_PROG_LIBTOOL])dnl
+AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([ar-lib])dnl
+AC_CHECK_TOOLS([AR], [ar lib "link -lib"], [false])
+: ${AR=ar}
+
+AC_CACHE_CHECK([the archiver ($AR) interface], [am_cv_ar_interface],
+ [AC_LANG_PUSH([C])
+ am_cv_ar_interface=ar
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int some_variable = 0;]])],
+ [am_ar_try='$AR cru libconftest.a conftest.$ac_objext >&AS_MESSAGE_LOG_FD'
+ AC_TRY_EVAL([am_ar_try])
+ if test "$ac_status" -eq 0; then
+ am_cv_ar_interface=ar
+ else
+ am_ar_try='$AR -NOLOGO -OUT:conftest.lib conftest.$ac_objext >&AS_MESSAGE_LOG_FD'
+ AC_TRY_EVAL([am_ar_try])
+ if test "$ac_status" -eq 0; then
+ am_cv_ar_interface=lib
+ else
+ am_cv_ar_interface=unknown
+ fi
+ fi
+ rm -f conftest.lib libconftest.a
+ ])
+ AC_LANG_POP([C])])
+
+case $am_cv_ar_interface in
+ar)
+ ;;
+lib)
+ # Microsoft lib, so override with the ar-lib wrapper script.
+ # FIXME: It is wrong to rewrite AR.
+ # But if we don't then we get into trouble of one sort or another.
+ # A longer-term fix would be to have automake use am__AR in this case,
+ # and then we could set am__AR="$am_aux_dir/ar-lib \$(AR)" or something
+ # similar.
+ AR="$am_aux_dir/ar-lib $AR"
+ ;;
+unknown)
+ m4_default([$1],
+ [AC_MSG_ERROR([could not determine $AR interface])])
+ ;;
+esac
+AC_SUBST([AR])dnl
+])
+
+# AM_AUX_DIR_EXPAND -*- Autoconf -*-
+
+# Copyright (C) 2001-2018 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to
+# '$srcdir', '$srcdir/..', or '$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory. The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run. This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+# fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+# fails if $ac_aux_dir is absolute,
+# fails when called from a subdirectory in a VPATH build with
+# a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir. In an in-source build this is usually
+# harmless because $srcdir is '.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir. That would be:
+# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+# MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH. The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
+# Expand $ac_aux_dir to an absolute path.
+am_aux_dir=`cd "$ac_aux_dir" && pwd`
+])
+
+# AM_CONDITIONAL -*- Autoconf -*-
+
+# Copyright (C) 1997-2018 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ([2.52])dnl
+ m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
+ [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])dnl
+AC_SUBST([$1_FALSE])dnl
+_AM_SUBST_NOTMAKE([$1_TRUE])dnl
+_AM_SUBST_NOTMAKE([$1_FALSE])dnl
+m4_define([_AM_COND_VALUE_$1], [$2])dnl
+if $2; then
+ $1_TRUE=
+ $1_FALSE='#'
+else
+ $1_TRUE='#'
+ $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+ AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+# Copyright (C) 1999-2018 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+
+# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery. Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+# _AM_DEPENDENCIES(NAME)
+# ----------------------
+# See how the compiler implements dependency checking.
+# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC".
+# We try a few techniques and use that to set a single cache variable.
+#
+# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
+# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
+# dependency, and given that the user is not expected to run this macro,
+# just rely on AC_PROG_CC.
+AC_DEFUN([_AM_DEPENDENCIES],
+[AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
+AC_REQUIRE([AM_MAKE_INCLUDE])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+
+m4_if([$1], [CC], [depcc="$CC" am_compiler_list=],
+ [$1], [CXX], [depcc="$CXX" am_compiler_list=],
+ [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
+ [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'],
+ [$1], [UPC], [depcc="$UPC" am_compiler_list=],
+ [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'],
+ [depcc="$$1" am_compiler_list=])
+
+AC_CACHE_CHECK([dependency style of $depcc],
+ [am_cv_$1_dependencies_compiler_type],
+[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named 'D' -- because '-MD' means "put the output
+ # in D".
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_$1_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+ fi
+ am__universal=false
+ m4_case([$1], [CC],
+ [case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac],
+ [CXX],
+ [case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac])
+
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
+ # Solaris 10 /bin/sh.
+ echo '/* dummy */' > sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ # We check with '-c' and '-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle '-M -o', and we need to detect this. Also, some Intel
+ # versions had trouble with output in subdirs.
+ am__obj=sub/conftest.${OBJEXT-o}
+ am__minus_obj="-o $am__obj"
+ case $depmode in
+ gcc)
+ # This depmode causes a compiler race in universal mode.
+ test "$am__universal" = false || continue
+ ;;
+ nosideeffect)
+ # After this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested.
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+ # This compiler won't grok '-c -o', but also, the minuso test has
+ # not run yet. These depmodes are late enough in the game, and
+ # so weak that their functioning should not be impacted.
+ am__obj=conftest.${OBJEXT-o}
+ am__minus_obj=
+ ;;
+ none) break ;;
+ esac
+ if depmode=$depmode \
+ source=sub/conftest.c object=$am__obj \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_$1_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_$1_dependencies_compiler_type=none
+fi
+])
+AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
+AM_CONDITIONAL([am__fastdep$1], [
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES.
+AC_DEFUN([AM_SET_DEPDIR],
+[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE([dependency-tracking], [dnl
+AS_HELP_STRING(
+ [--enable-dependency-tracking],
+ [do not reject slow dependency extractors])
+AS_HELP_STRING(
+ [--disable-dependency-tracking],
+ [speeds up one-time build])])
+if test "x$enable_dependency_tracking" != xno; then
+ am_depcomp="$ac_aux_dir/depcomp"
+ AMDEPBACKSLASH='\'
+ am__nodep='_no'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+AC_SUBST([AMDEPBACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
+AC_SUBST([am__nodep])dnl
+_AM_SUBST_NOTMAKE([am__nodep])dnl
+])
+
+# Generate code to set up dependency tracking. -*- Autoconf -*-
+
+# Copyright (C) 1999-2018 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_OUTPUT_DEPENDENCY_COMMANDS
+# ------------------------------
+AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+[{
+ # Older Autoconf quotes --file arguments for eval, but not when files
+ # are listed without --file. Let's play safe and only enable the eval
+ # if we detect the quoting.
+ # TODO: see whether this extra hack can be removed once we start
+ # requiring Autoconf 2.70 or later.
+ AS_CASE([$CONFIG_FILES],
+ [*\'*], [eval set x "$CONFIG_FILES"],
+ [*], [set x $CONFIG_FILES])
+ shift
+ # Used to flag and report bootstrapping failures.
+ am_rc=0
+ for am_mf
+ do
+ # Strip MF so we end up with the name of the file.
+ am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile which includes
+ # dependency-tracking related rules and includes.
+ # Grep'ing the whole file directly is not great: AIX grep has a line
+ # limit of 2048, but all sed's we know have understand at least 4000.
+ sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \
+ || continue
+ am_dirpart=`AS_DIRNAME(["$am_mf"])`
+ am_filepart=`AS_BASENAME(["$am_mf"])`
+ AM_RUN_LOG([cd "$am_dirpart" \
+ && sed -e '/# am--include-marker/d' "$am_filepart" \
+ | $MAKE -f - am--depfiles]) || am_rc=$?
+ done
+ if test $am_rc -ne 0; then
+ AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments
+ for automatic dependency tracking. Try re-running configure with the
+ '--disable-dependency-tracking' option to at least be able to build
+ the package (albeit without support for automatic dependency tracking).])
+ fi
+ AS_UNSET([am_dirpart])
+ AS_UNSET([am_filepart])
+ AS_UNSET([am_mf])
+ AS_UNSET([am_rc])
+ rm -f conftest-deps.mk
+}
+])# _AM_OUTPUT_DEPENDENCY_COMMANDS
+
+
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+# -----------------------------
+# This macro should only be invoked once -- use via AC_REQUIRE.
+#
+# This code is only required when automatic dependency tracking is enabled.
+# This creates each '.Po' and '.Plo' makefile fragment that we'll need in
+# order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+[AC_CONFIG_COMMANDS([depfiles],
+ [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
+ [AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])])
+
+# Do all the work for Automake. -*- Autoconf -*-
+
+# Copyright (C) 1996-2018 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This macro actually does too much. Some checks are only needed if
+# your package does certain things. But this isn't really a big deal.
+
+dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O.
+m4_define([AC_PROG_CC],
+m4_defn([AC_PROG_CC])
+[_AM_PROG_CC_C_O
+])
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out. PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition. After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.65])dnl
+dnl Autoconf wants to disallow AM_ names. We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+ # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+ # is not polluted with repeated "-I."
+ AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
+ # test to see if srcdir already configured
+ if test -f $srcdir/config.status; then
+ AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+ fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+ if (cygpath --version) >/dev/null 2>/dev/null; then
+ CYGPATH_W='cygpath -w'
+ else
+ CYGPATH_W=echo
+ fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[AC_DIAGNOSE([obsolete],
+ [$0: two- and three-arguments forms are deprecated.])
+m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
+m4_if(
+ m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]),
+ [ok:ok],,
+ [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package])
+ AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}])
+AM_MISSING_PROG([AUTOCONF], [autoconf])
+AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}])
+AM_MISSING_PROG([AUTOHEADER], [autoheader])
+AM_MISSING_PROG([MAKEINFO], [makeinfo])
+AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
+AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+# For better backward compatibility. To be removed once Automake 1.9.x
+# dies out for good. For more background, see:
+# <https://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
+# <https://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
+AC_SUBST([mkdir_p], ['$(MKDIR_P)'])
+# We need awk for the "check" target (and possibly the TAP driver). The
+# system "awk" is bad on some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+ [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+ [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+ [_AM_DEPENDENCIES([CC])],
+ [m4_define([AC_PROG_CC],
+ m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+ [_AM_DEPENDENCIES([CXX])],
+ [m4_define([AC_PROG_CXX],
+ m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJC],
+ [_AM_DEPENDENCIES([OBJC])],
+ [m4_define([AC_PROG_OBJC],
+ m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJCXX],
+ [_AM_DEPENDENCIES([OBJCXX])],
+ [m4_define([AC_PROG_OBJCXX],
+ m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl
+])
+AC_REQUIRE([AM_SILENT_RULES])dnl
+dnl The testsuite driver may need to know about EXEEXT, so add the
+dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This
+dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below.
+AC_CONFIG_COMMANDS_PRE(dnl
+[m4_provide_if([_AM_COMPILER_EXEEXT],
+ [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
+
+# POSIX will say in a future version that running "rm -f" with no argument
+# is OK; and we want to be able to make that assumption in our Makefile
+# recipes. So use an aggressive probe to check that the usage we want is
+# actually supported "in the wild" to an acceptable degree.
+# See automake bug#10828.
+# To make any issue more visible, cause the running configure to be aborted
+# by default if the 'rm' program in use doesn't match our expectations; the
+# user can still override this though.
+if rm -f && rm -fr && rm -rf; then : OK; else
+ cat >&2 <<'END'
+Oops!
+
+Your 'rm' program seems unable to run without file operands specified
+on the command line, even when the '-f' option is present. This is contrary
+to the behaviour of most rm programs out there, and not conforming with
+the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>
+
+Please tell bug-automake@gnu.org about your system, including the value
+of your $PATH and any error possibly output before this message. This
+can help us improve future automake versions.
+
+END
+ if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
+ echo 'Configuration will proceed anyway, since you have set the' >&2
+ echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
+ echo >&2
+ else
+ cat >&2 <<'END'
+Aborting the configuration process, to ensure you take notice of the issue.
+
+You can download and install GNU coreutils to get an 'rm' implementation
+that behaves properly: <https://www.gnu.org/software/coreutils/>.
+
+If you want to complete the configuration process using your problematic
+'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
+to "yes", and re-run configure.
+
+END
+ AC_MSG_ERROR([Your 'rm' program is bad, sorry.])
+ fi
+fi
+dnl The trailing newline in this macro's definition is deliberate, for
+dnl backward compatibility and to allow trailing 'dnl'-style comments
+dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841.
+])
+
+dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not
+dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
+dnl mangled by Autoconf and run in a shell conditional statement.
+m4_define([_AC_COMPILER_EXEEXT],
+m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated. The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_arg=$1
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+ case $_am_header in
+ $_am_arg | $_am_arg:* )
+ break ;;
+ * )
+ _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+ esac
+done
+echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001-2018 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+if test x"${install_sh+set}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+ *)
+ install_sh="\${SHELL} $am_aux_dir/install-sh"
+ esac
+fi
+AC_SUBST([install_sh])])
+
+# Copyright (C) 2003-2018 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# Check whether the underlying file-system supports filenames
+# with a leading dot. For instance MS-DOS doesn't.
+AC_DEFUN([AM_SET_LEADING_DOT],
+[rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+ am__leading_dot=.
+else
+ am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+AC_SUBST([am__leading_dot])])
+
+# Check to see how 'make' treats includes. -*- Autoconf -*-
+
+# Copyright (C) 2001-2018 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check whether make has an 'include' directive that can support all
+# the idioms we need for our automatic dependency tracking code.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive])
+cat > confinc.mk << 'END'
+am__doit:
+ @echo this is the am__doit target >confinc.out
+.PHONY: am__doit
+END
+am__include="#"
+am__quote=
+# BSD make does it like this.
+echo '.include "confinc.mk" # ignored' > confmf.BSD
+# Other make implementations (GNU, Solaris 10, AIX) do it like this.
+echo 'include confinc.mk # ignored' > confmf.GNU
+_am_result=no
+for s in GNU BSD; do
+ AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out])
+ AS_CASE([$?:`cat confinc.out 2>/dev/null`],
+ ['0:this is the am__doit target'],
+ [AS_CASE([$s],
+ [BSD], [am__include='.include' am__quote='"'],
+ [am__include='include' am__quote=''])])
+ if test "$am__include" != "#"; then
+ _am_result="yes ($s style)"
+ break
+ fi
+done
+rm -f confinc.* confmf.*
+AC_MSG_RESULT([${_am_result}])
+AC_SUBST([am__include])])
+AC_SUBST([am__quote])])
+
+# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
+
+# Copyright (C) 1997-2018 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it is modern enough.
+# If it is, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([missing])dnl
+if test x"${MISSING+set}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+ *)
+ MISSING="\${SHELL} $am_aux_dir/missing" ;;
+ esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --is-lightweight"; then
+ am_missing_run="$MISSING "
+else
+ am_missing_run=
+ AC_MSG_WARN(['missing' script is too old or missing])
+fi
+])
+
+# Helper functions for option handling. -*- Autoconf -*-
+
+# Copyright (C) 2001-2018 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# --------------------
+# Set option NAME. Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), [1])])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Copyright (C) 1999-2018 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_PROG_CC_C_O
+# ---------------
+# Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC
+# to automatically call this.
+AC_DEFUN([_AM_PROG_CC_C_O],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([compile])dnl
+AC_LANG_PUSH([C])dnl
+AC_CACHE_CHECK(
+ [whether $CC understands -c and -o together],
+ [am_cv_prog_cc_c_o],
+ [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])])
+ # Make sure it works both with $CC and with simple cc.
+ # Following AC_PROG_CC_C_O, we do the test twice because some
+ # compilers refuse to overwrite an existing .o file with -o,
+ # though they will create one.
+ am_cv_prog_cc_c_o=yes
+ for am_i in 1 2; do
+ if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \
+ && test -f conftest2.$ac_objext; then
+ : OK
+ else
+ am_cv_prog_cc_c_o=no
+ break
+ fi
+ done
+ rm -f core conftest*
+ unset am_i])
+if test "$am_cv_prog_cc_c_o" != yes; then
+ # Losing compiler, so override with the script.
+ # FIXME: It is wrong to rewrite CC.
+ # But if we don't then we get into trouble of one sort or another.
+ # A longer-term fix would be to have automake use am__CC in this case,
+ # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+ CC="$am_aux_dir/compile $CC"
+fi
+AC_LANG_POP([C])])
+
+# For backward compatibility.
+AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
+
+# Copyright (C) 2001-2018 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_RUN_LOG(COMMAND)
+# -------------------
+# Run COMMAND, save the exit status in ac_status, and log it.
+# (This has been adapted from Autoconf's _AC_RUN_LOG macro.)
+AC_DEFUN([AM_RUN_LOG],
+[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD
+ ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+ (exit $ac_status); }])
+
+# Check to make sure that the build environment is sane. -*- Autoconf -*-
+
+# Copyright (C) 1996-2018 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name. Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+ *[[\\\"\#\$\&\'\`$am_lf]]*)
+ AC_MSG_ERROR([unsafe absolute working directory name]);;
+esac
+case $srcdir in
+ *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*)
+ AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);;
+esac
+
+# Do 'set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ am_has_slept=no
+ for am_try in 1 2; do
+ echo "timestamp, slept: $am_has_slept" > conftest.file
+ set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+ if test "$[*]" = "X"; then
+ # -L didn't work.
+ set X `ls -t "$srcdir/configure" conftest.file`
+ fi
+ if test "$[*]" != "X $srcdir/configure conftest.file" \
+ && test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
+ alias in your environment])
+ fi
+ if test "$[2]" = conftest.file || test $am_try -eq 2; then
+ break
+ fi
+ # Just in case.
+ sleep 1
+ am_has_slept=yes
+ done
+ test "$[2]" = conftest.file
+ )
+then
+ # Ok.
+ :
+else
+ AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT([yes])
+# If we didn't sleep, we still need to ensure time stamps of config.status and
+# generated files are strictly newer.
+am_sleep_pid=
+if grep 'slept: no' conftest.file >/dev/null 2>&1; then
+ ( sleep 1 ) &
+ am_sleep_pid=$!
+fi
+AC_CONFIG_COMMANDS_PRE(
+ [AC_MSG_CHECKING([that generated files are newer than configure])
+ if test -n "$am_sleep_pid"; then
+ # Hide warnings about reused PIDs.
+ wait $am_sleep_pid 2>/dev/null
+ fi
+ AC_MSG_RESULT([done])])
+rm -f conftest.file
+])
+
+# Copyright (C) 2009-2018 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_SILENT_RULES([DEFAULT])
+# --------------------------
+# Enable less verbose build rules; with the default set to DEFAULT
+# ("yes" being less verbose, "no" or empty being verbose).
+AC_DEFUN([AM_SILENT_RULES],
+[AC_ARG_ENABLE([silent-rules], [dnl
+AS_HELP_STRING(
+ [--enable-silent-rules],
+ [less verbose build output (undo: "make V=1")])
+AS_HELP_STRING(
+ [--disable-silent-rules],
+ [verbose build output (undo: "make V=0")])dnl
+])
+case $enable_silent_rules in @%:@ (((
+ yes) AM_DEFAULT_VERBOSITY=0;;
+ no) AM_DEFAULT_VERBOSITY=1;;
+ *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);;
+esac
+dnl
+dnl A few 'make' implementations (e.g., NonStop OS and NextStep)
+dnl do not support nested variable expansions.
+dnl See automake bug#9928 and bug#10237.
+am_make=${MAKE-make}
+AC_CACHE_CHECK([whether $am_make supports nested variables],
+ [am_cv_make_support_nested_variables],
+ [if AS_ECHO([['TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+ @$(TRUE)
+.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then
+ am_cv_make_support_nested_variables=yes
+else
+ am_cv_make_support_nested_variables=no
+fi])
+if test $am_cv_make_support_nested_variables = yes; then
+ dnl Using '$V' instead of '$(V)' breaks IRIX make.
+ AM_V='$(V)'
+ AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+ AM_V=$AM_DEFAULT_VERBOSITY
+ AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
+fi
+AC_SUBST([AM_V])dnl
+AM_SUBST_NOTMAKE([AM_V])dnl
+AC_SUBST([AM_DEFAULT_V])dnl
+AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl
+AC_SUBST([AM_DEFAULT_VERBOSITY])dnl
+AM_BACKSLASH='\'
+AC_SUBST([AM_BACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl
+])
+
+# Copyright (C) 2001-2018 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor 'install' (even GNU) is that you can't
+# specify the program used to strip binaries. This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in "make install-strip", and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using 'strip' when the user
+# run "make install-strip". However 'strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the 'STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be 'maybe'.
+if test "$cross_compiling" != no; then
+ AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Copyright (C) 2006-2018 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
+# This macro is traced by Automake.
+AC_DEFUN([_AM_SUBST_NOTMAKE])
+
+# AM_SUBST_NOTMAKE(VARIABLE)
+# --------------------------
+# Public sister of _AM_SUBST_NOTMAKE.
+AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
+
+# Check how to create a tarball. -*- Autoconf -*-
+
+# Copyright (C) 2004-2018 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of 'v7', 'ustar', or 'pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+# tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+# $(am__untar) < result.tar
+#
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility. Yes, it's still used
+# in the wild :-( We should find a proper way to deprecate it ...
+AC_SUBST([AMTAR], ['$${TAR-tar}'])
+
+# We'll loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+
+m4_if([$1], [v7],
+ [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'],
+
+ [m4_case([$1],
+ [ustar],
+ [# The POSIX 1988 'ustar' format is defined with fixed-size fields.
+ # There is notably a 21 bits limit for the UID and the GID. In fact,
+ # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343
+ # and bug#13588).
+ am_max_uid=2097151 # 2^21 - 1
+ am_max_gid=$am_max_uid
+ # The $UID and $GID variables are not portable, so we need to resort
+ # to the POSIX-mandated id(1) utility. Errors in the 'id' calls
+ # below are definitely unexpected, so allow the users to see them
+ # (that is, avoid stderr redirection).
+ am_uid=`id -u || echo unknown`
+ am_gid=`id -g || echo unknown`
+ AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format])
+ if test $am_uid -le $am_max_uid; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ _am_tools=none
+ fi
+ AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format])
+ if test $am_gid -le $am_max_gid; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ _am_tools=none
+ fi],
+
+ [pax],
+ [],
+
+ [m4_fatal([Unknown tar format])])
+
+ AC_MSG_CHECKING([how to create a $1 tar archive])
+
+ # Go ahead even if we have the value already cached. We do so because we
+ # need to set the values for the 'am__tar' and 'am__untar' variables.
+ _am_tools=${am_cv_prog_tar_$1-$_am_tools}
+
+ for _am_tool in $_am_tools; do
+ case $_am_tool in
+ gnutar)
+ for _am_tar in tar gnutar gtar; do
+ AM_RUN_LOG([$_am_tar --version]) && break
+ done
+ am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+ am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+ am__untar="$_am_tar -xf -"
+ ;;
+ plaintar)
+ # Must skip GNU tar: if it does not support --format= it doesn't create
+ # ustar tarball either.
+ (tar --version) >/dev/null 2>&1 && continue
+ am__tar='tar chf - "$$tardir"'
+ am__tar_='tar chf - "$tardir"'
+ am__untar='tar xf -'
+ ;;
+ pax)
+ am__tar='pax -L -x $1 -w "$$tardir"'
+ am__tar_='pax -L -x $1 -w "$tardir"'
+ am__untar='pax -r'
+ ;;
+ cpio)
+ am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+ am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+ am__untar='cpio -i -H $1 -d'
+ ;;
+ none)
+ am__tar=false
+ am__tar_=false
+ am__untar=false
+ ;;
+ esac
+
+ # If the value was cached, stop now. We just wanted to have am__tar
+ # and am__untar set.
+ test -n "${am_cv_prog_tar_$1}" && break
+
+ # tar/untar a dummy directory, and stop if the command works.
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ echo GrepMe > conftest.dir/file
+ AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+ rm -rf conftest.dir
+ if test -s conftest.tar; then
+ AM_RUN_LOG([$am__untar <conftest.tar])
+ AM_RUN_LOG([cat conftest.dir/file])
+ grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+ fi
+ done
+ rm -rf conftest.dir
+
+ AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+ AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
+m4_include([m4/as-compiler-flag.m4])
+m4_include([m4/ax_check_openssl.m4])
+m4_include([m4/gtk-doc.m4])
+m4_include([m4/introspection.m4])
+m4_include([m4/libtool.m4])
+m4_include([m4/ltoptions.m4])
+m4_include([m4/ltsugar.m4])
+m4_include([m4/ltversion.m4])
+m4_include([m4/lt~obsolete.m4])
--- /dev/null
+#
+# Makefile.am for the Nice Glib ICE library
+#
+# (C) 2006, 2007 Collabora Ltd.
+# (C) 2006, 2007 Nokia Corporation. All rights reserved.
+#
+# Licensed under MPL 1.1/LGPL 2.1. See file COPYING.
+
+include $(top_srcdir)/common.mk
+
+AM_CFLAGS = \
+ -DG_LOG_DOMAIN=\"libnice\" \
+ $(LIBNICE_CFLAGS) \
+ $(GLIB_CFLAGS) \
+ $(GUPNP_CFLAGS) \
+ -I $(top_srcdir) \
+ -I $(top_srcdir)/random \
+ -I $(top_srcdir)/socket \
+ -I $(top_srcdir)/stun
+
+if WINDOWS
+ AM_CFLAGS += -DWINVER=0x0501 # _WIN32_WINNT_WINXP
+endif
+
+BUILT_SOURCES = \
+ agent-enum-types.h \
+ agent-enum-types.c
+
+CLEANFILES += $(BUILT_SOURCES)
+
+noinst_LTLIBRARIES = libagent.la
+
+pkginclude_HEADERS = \
+ agent.h \
+ candidate.h \
+ debug.h \
+ address.h \
+ interfaces.h \
+ pseudotcp.h \
+ $(NULL)
+
+libagent_la_SOURCES = \
+ address.h \
+ address.c \
+ debug.h \
+ debug.c \
+ candidate.h \
+ candidate.c \
+ component.h \
+ component.c \
+ agent.h \
+ agent-priv.h \
+ agent.c \
+ stream.h \
+ stream.c \
+ conncheck.c \
+ conncheck.h \
+ discovery.c \
+ discovery.h \
+ interfaces.c \
+ interfaces.h \
+ pseudotcp.h \
+ pseudotcp.c \
+ iostream.h \
+ iostream.c \
+ inputstream.h \
+ inputstream.c \
+ outputstream.h \
+ outputstream.c \
+ $(BUILT_SOURCES)
+
+agent-enum-types.h: $(pkginclude_HEADERS) Makefile
+ $(AM_V_GEN)$(GLIB_MKENUMS) \
+ --fhead "#ifndef __AGENT_ENUM_TYPES_H__\n#define __AGENT_ENUM_TYPES_H__ 1\n\n#include <glib-object.h>\n\nG_BEGIN_DECLS\n" \
+ --fprod "/* enumerations from \"@filename@\" */\n" \
+ --vhead "GType @enum_name@_get_type (void) G_GNUC_CONST;\n#define NICE_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n" \
+ --ftail "G_END_DECLS\n\n#endif /* !AGENT_ENUM_TYPES_H */" \
+ $(addprefix $(srcdir)/,$(pkginclude_HEADERS)) > $@
+
+agent-enum-types.c: $(pkginclude_HEADERS) Makefile agent-enum-types.h
+ $(AM_V_GEN)$(GLIB_MKENUMS) \
+ --fhead "#include <config.h>\n#include <glib-object.h>\n#include \"agent.h\"\n#include \"pseudotcp.h\"\n#include \"agent-enum-types.h\"" \
+ --fprod "\n/* enumerations from \"@filename@\" */" \
+ --vhead "GType\n@enum_name@_get_type (void)\n{\n static GType type = 0;\n if (!type) {\n static const G@Type@Value values[] = {" \
+ --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \
+ --vtail " { 0, NULL, NULL }\n };\n type = g_@type@_register_static (\"@EnumName@\", values);\n }\n return type;\n}\n\n" \
+ $(addprefix $(srcdir)/,$(pkginclude_HEADERS)) > $@
+
+libagent_la_LIBADD = \
+ $(top_builddir)/random/libnice-random.la \
+ $(top_builddir)/socket/libsocket.la \
+ $(top_builddir)/stun/libstun.la \
+ $(GLIB_LIBS) \
+ $(GUPNP_LIBS) \
+ $(NULL)
+libagent_la_DEPENDENCIES = \
+ $(top_builddir)/random/libnice-random.la \
+ $(top_builddir)/socket/libsocket.la \
+ $(top_builddir)/stun/libstun.la
+
+if WINDOWS
+ libagent_la_LIBADD += -liphlpapi -lws2_32
+endif
+
+#
+# GObject introspection
+#
+# We need --accept-unprefixed because of PseudoTcp and TurnServer.
+#
+-include $(INTROSPECTION_MAKEFILE)
+INTROSPECTION_GIRS =
+INTROSPECTION_SCANNER_ARGS = --add-include-path=$(srcdir) --warn-all --accept-unprefixed
+INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir)
+
+if HAVE_INTROSPECTION
+introspection_sources = $(pkginclude_HEADERS)
+
+Nice-0.1.gir: libagent.la
+Nice_0_1_gir_INCLUDES = GObject-2.0 Gio-2.0
+Nice_0_1_gir_EXPORT_PACKAGES = nice
+Nice_0_1_gir_CFLAGS = $(AM_CFLAGS)
+Nice_0_1_gir_LIBS = libagent.la
+Nice_0_1_gir_FILES = $(introspection_sources)
+INTROSPECTION_GIRS += Nice-0.1.gir
+
+girdir = $(datadir)/gir-1.0
+gir_DATA = $(INTROSPECTION_GIRS)
+
+typelibdir = $(libdir)/girepository-1.0
+typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
+
+CLEANFILES += $(gir_DATA) $(typelib_DATA)
+endif
+
+EXTRA_DIST = meson.build
--- /dev/null
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+#
+# Makefile.am for the Nice Glib ICE library
+#
+# (C) 2006, 2007 Collabora Ltd.
+# (C) 2006, 2007 Nokia Corporation. All rights reserved.
+#
+# Licensed under MPL 1.1/LGPL 2.1. See file COPYING.
+
+
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+@WINDOWS_TRUE@am__append_1 = -DWINVER=0x0501 # _WIN32_WINNT_WINXP
+@WINDOWS_TRUE@am__append_2 = -liphlpapi -lws2_32
+@HAVE_INTROSPECTION_TRUE@am__append_3 = Nice-0.1.gir
+@HAVE_INTROSPECTION_TRUE@am__append_4 = $(gir_DATA) $(typelib_DATA)
+subdir = agent
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/as-compiler-flag.m4 \
+ $(top_srcdir)/m4/ax_check_openssl.m4 \
+ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/introspection.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(pkginclude_HEADERS) \
+ $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+am__objects_1 = agent-enum-types.lo
+am_libagent_la_OBJECTS = address.lo debug.lo candidate.lo component.lo \
+ agent.lo stream.lo conncheck.lo discovery.lo interfaces.lo \
+ pseudotcp.lo iostream.lo inputstream.lo outputstream.lo \
+ $(am__objects_1)
+libagent_la_OBJECTS = $(am_libagent_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/address.Plo \
+ ./$(DEPDIR)/agent-enum-types.Plo ./$(DEPDIR)/agent.Plo \
+ ./$(DEPDIR)/candidate.Plo ./$(DEPDIR)/component.Plo \
+ ./$(DEPDIR)/conncheck.Plo ./$(DEPDIR)/debug.Plo \
+ ./$(DEPDIR)/discovery.Plo ./$(DEPDIR)/inputstream.Plo \
+ ./$(DEPDIR)/interfaces.Plo ./$(DEPDIR)/iostream.Plo \
+ ./$(DEPDIR)/outputstream.Plo ./$(DEPDIR)/pseudotcp.Plo \
+ ./$(DEPDIR)/stream.Plo
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(libagent_la_SOURCES)
+DIST_SOURCES = $(libagent_la_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(girdir)" "$(DESTDIR)$(typelibdir)" \
+ "$(DESTDIR)$(pkgincludedir)"
+DATA = $(gir_DATA) $(typelib_DATA)
+HEADERS = $(pkginclude_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/common.mk \
+ $(top_srcdir)/depcomp INSTALL
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+pkgincludedir = $(includedir)/nice
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCACHE_DISABLE = @CCACHE_DISABLE@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GST010_CFLAGS = @GST010_CFLAGS@
+GST010_LIBS = @GST010_LIBS@
+GST_CFLAGS = @GST_CFLAGS@
+GST_CHECK_CFLAGS = @GST_CHECK_CFLAGS@
+GST_CHECK_LIBS = @GST_CHECK_LIBS@
+GST_LIBS = @GST_LIBS@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@
+GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@
+GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@
+GTKDOC_MKPDF = @GTKDOC_MKPDF@
+GTKDOC_REBASE = @GTKDOC_REBASE@
+GUPNP_CFLAGS = @GUPNP_CFLAGS@
+GUPNP_LIBS = @GUPNP_LIBS@
+GUPNP_PACKAGES = @GUPNP_PACKAGES@
+GUPNP_PACKAGES_PRIVATE = @GUPNP_PACKAGES_PRIVATE@
+GUPNP_PACKAGES_PUBLIC = @GUPNP_PACKAGES_PUBLIC@
+HAVE_GUPNP = @HAVE_GUPNP@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@
+INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@
+INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@
+INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@
+INTROSPECTION_LIBS = @INTROSPECTION_LIBS@
+INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@
+INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
+INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBNICE_CFLAGS = @LIBNICE_CFLAGS@
+LIBNICE_LT_LDFLAGS = @LIBNICE_LT_LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBRT = @LIBRT@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NICE_PACKAGES_PRIVATE = @NICE_PACKAGES_PRIVATE@
+NICE_PACKAGES_PUBLIC = @NICE_PACKAGES_PUBLIC@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_INCLUDES = @OPENSSL_INCLUDES@
+OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+UPNP_ENABLED = @UPNP_ENABLED@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gstplugin010dir = @gstplugin010dir@
+gstplugindir = @gstplugindir@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+CLEANFILES = *.gcno *.gcda $(BUILT_SOURCES) $(am__append_4)
+LOG_DRIVER = $(top_srcdir)/scripts/valgrind-test-driver
+AM_CFLAGS = -DG_LOG_DOMAIN=\"libnice\" $(LIBNICE_CFLAGS) \
+ $(GLIB_CFLAGS) $(GUPNP_CFLAGS) -I $(top_srcdir) -I \
+ $(top_srcdir)/random -I $(top_srcdir)/socket -I \
+ $(top_srcdir)/stun $(am__append_1)
+BUILT_SOURCES = \
+ agent-enum-types.h \
+ agent-enum-types.c
+
+noinst_LTLIBRARIES = libagent.la
+pkginclude_HEADERS = \
+ agent.h \
+ candidate.h \
+ debug.h \
+ address.h \
+ interfaces.h \
+ pseudotcp.h \
+ $(NULL)
+
+libagent_la_SOURCES = \
+ address.h \
+ address.c \
+ debug.h \
+ debug.c \
+ candidate.h \
+ candidate.c \
+ component.h \
+ component.c \
+ agent.h \
+ agent-priv.h \
+ agent.c \
+ stream.h \
+ stream.c \
+ conncheck.c \
+ conncheck.h \
+ discovery.c \
+ discovery.h \
+ interfaces.c \
+ interfaces.h \
+ pseudotcp.h \
+ pseudotcp.c \
+ iostream.h \
+ iostream.c \
+ inputstream.h \
+ inputstream.c \
+ outputstream.h \
+ outputstream.c \
+ $(BUILT_SOURCES)
+
+libagent_la_LIBADD = $(top_builddir)/random/libnice-random.la \
+ $(top_builddir)/socket/libsocket.la \
+ $(top_builddir)/stun/libstun.la $(GLIB_LIBS) $(GUPNP_LIBS) \
+ $(NULL) $(am__append_2)
+libagent_la_DEPENDENCIES = \
+ $(top_builddir)/random/libnice-random.la \
+ $(top_builddir)/socket/libsocket.la \
+ $(top_builddir)/stun/libstun.la
+
+INTROSPECTION_GIRS = $(am__append_3)
+INTROSPECTION_SCANNER_ARGS = --add-include-path=$(srcdir) --warn-all --accept-unprefixed
+INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir)
+@HAVE_INTROSPECTION_TRUE@introspection_sources = $(pkginclude_HEADERS)
+@HAVE_INTROSPECTION_TRUE@Nice_0_1_gir_INCLUDES = GObject-2.0 Gio-2.0
+@HAVE_INTROSPECTION_TRUE@Nice_0_1_gir_EXPORT_PACKAGES = nice
+@HAVE_INTROSPECTION_TRUE@Nice_0_1_gir_CFLAGS = $(AM_CFLAGS)
+@HAVE_INTROSPECTION_TRUE@Nice_0_1_gir_LIBS = libagent.la
+@HAVE_INTROSPECTION_TRUE@Nice_0_1_gir_FILES = $(introspection_sources)
+@HAVE_INTROSPECTION_TRUE@girdir = $(datadir)/gir-1.0
+@HAVE_INTROSPECTION_TRUE@gir_DATA = $(INTROSPECTION_GIRS)
+@HAVE_INTROSPECTION_TRUE@typelibdir = $(libdir)/girepository-1.0
+@HAVE_INTROSPECTION_TRUE@typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
+EXTRA_DIST = meson.build
+all: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/common.mk $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu agent/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu agent/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+$(top_srcdir)/common.mk $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+libagent.la: $(libagent_la_OBJECTS) $(libagent_la_DEPENDENCIES) $(EXTRA_libagent_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(LINK) $(libagent_la_OBJECTS) $(libagent_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/address.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/agent-enum-types.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/agent.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/candidate.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/component.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conncheck.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debug.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/discovery.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inputstream.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/interfaces.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iostream.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/outputstream.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pseudotcp.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stream.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-girDATA: $(gir_DATA)
+ @$(NORMAL_INSTALL)
+ @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(girdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(girdir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(girdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(girdir)" || exit $$?; \
+ done
+
+uninstall-girDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(girdir)'; $(am__uninstall_files_from_dir)
+install-typelibDATA: $(typelib_DATA)
+ @$(NORMAL_INSTALL)
+ @list='$(typelib_DATA)'; test -n "$(typelibdir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(typelibdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(typelibdir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(typelibdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(typelibdir)" || exit $$?; \
+ done
+
+uninstall-typelibDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(typelib_DATA)'; test -n "$(typelibdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(typelibdir)'; $(am__uninstall_files_from_dir)
+install-pkgincludeHEADERS: $(pkginclude_HEADERS)
+ @$(NORMAL_INSTALL)
+ @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(pkgincludedir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkgincludedir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkgincludedir)" || exit $$?; \
+ done
+
+uninstall-pkgincludeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(pkgincludedir)'; $(am__uninstall_files_from_dir)
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(girdir)" "$(DESTDIR)$(typelibdir)" "$(DESTDIR)$(pkgincludedir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/address.Plo
+ -rm -f ./$(DEPDIR)/agent-enum-types.Plo
+ -rm -f ./$(DEPDIR)/agent.Plo
+ -rm -f ./$(DEPDIR)/candidate.Plo
+ -rm -f ./$(DEPDIR)/component.Plo
+ -rm -f ./$(DEPDIR)/conncheck.Plo
+ -rm -f ./$(DEPDIR)/debug.Plo
+ -rm -f ./$(DEPDIR)/discovery.Plo
+ -rm -f ./$(DEPDIR)/inputstream.Plo
+ -rm -f ./$(DEPDIR)/interfaces.Plo
+ -rm -f ./$(DEPDIR)/iostream.Plo
+ -rm -f ./$(DEPDIR)/outputstream.Plo
+ -rm -f ./$(DEPDIR)/pseudotcp.Plo
+ -rm -f ./$(DEPDIR)/stream.Plo
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-girDATA install-pkgincludeHEADERS \
+ install-typelibDATA
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f ./$(DEPDIR)/address.Plo
+ -rm -f ./$(DEPDIR)/agent-enum-types.Plo
+ -rm -f ./$(DEPDIR)/agent.Plo
+ -rm -f ./$(DEPDIR)/candidate.Plo
+ -rm -f ./$(DEPDIR)/component.Plo
+ -rm -f ./$(DEPDIR)/conncheck.Plo
+ -rm -f ./$(DEPDIR)/debug.Plo
+ -rm -f ./$(DEPDIR)/discovery.Plo
+ -rm -f ./$(DEPDIR)/inputstream.Plo
+ -rm -f ./$(DEPDIR)/interfaces.Plo
+ -rm -f ./$(DEPDIR)/iostream.Plo
+ -rm -f ./$(DEPDIR)/outputstream.Plo
+ -rm -f ./$(DEPDIR)/pseudotcp.Plo
+ -rm -f ./$(DEPDIR)/stream.Plo
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-girDATA uninstall-pkgincludeHEADERS \
+ uninstall-typelibDATA
+
+.MAKE: all check install install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ cscopelist-am ctags ctags-am distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-girDATA install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-pkgincludeHEADERS \
+ install-ps install-ps-am install-strip install-typelibDATA \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags tags-am uninstall uninstall-am uninstall-girDATA \
+ uninstall-pkgincludeHEADERS uninstall-typelibDATA
+
+.PRECIOUS: Makefile
+
+
+check-valgrind:
+ $(MAKE) TESTS_ENVIRONMENT="USE_VALGRIND=1 " check
+
+.PHONY: check-valgrind
+
+agent-enum-types.h: $(pkginclude_HEADERS) Makefile
+ $(AM_V_GEN)$(GLIB_MKENUMS) \
+ --fhead "#ifndef __AGENT_ENUM_TYPES_H__\n#define __AGENT_ENUM_TYPES_H__ 1\n\n#include <glib-object.h>\n\nG_BEGIN_DECLS\n" \
+ --fprod "/* enumerations from \"@filename@\" */\n" \
+ --vhead "GType @enum_name@_get_type (void) G_GNUC_CONST;\n#define NICE_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n" \
+ --ftail "G_END_DECLS\n\n#endif /* !AGENT_ENUM_TYPES_H */" \
+ $(addprefix $(srcdir)/,$(pkginclude_HEADERS)) > $@
+
+agent-enum-types.c: $(pkginclude_HEADERS) Makefile agent-enum-types.h
+ $(AM_V_GEN)$(GLIB_MKENUMS) \
+ --fhead "#include <config.h>\n#include <glib-object.h>\n#include \"agent.h\"\n#include \"pseudotcp.h\"\n#include \"agent-enum-types.h\"" \
+ --fprod "\n/* enumerations from \"@filename@\" */" \
+ --vhead "GType\n@enum_name@_get_type (void)\n{\n static GType type = 0;\n if (!type) {\n static const G@Type@Value values[] = {" \
+ --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \
+ --vtail " { 0, NULL, NULL }\n };\n type = g_@type@_register_static (\"@EnumName@\", values);\n }\n return type;\n}\n\n" \
+ $(addprefix $(srcdir)/,$(pkginclude_HEADERS)) > $@
+
+#
+# GObject introspection
+#
+# We need --accept-unprefixed because of PseudoTcp and TurnServer.
+#
+-include $(INTROSPECTION_MAKEFILE)
+
+@HAVE_INTROSPECTION_TRUE@Nice-0.1.gir: libagent.la
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2006-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2006-2009 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Dafydd Harries, Collabora Ltd.
+ * Youness Alaoui, Collabora Ltd.
+ * Kai Vehmanen, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#else
+#define NICEAPI_EXPORT
+#endif
+
+#include <string.h>
+
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
+#include "address.h"
+
+#ifdef G_OS_WIN32
+#define inet_ntop inet_ntop_win32
+
+/* Defined in recent versions of mingw:
+ * https://github.com/mirror/mingw-w64/commit/0f4899473c4ba2e34fa447b1931a04e38c1f105e
+ */
+#ifndef IN6_ARE_ADDR_EQUAL
+#define IN6_ARE_ADDR_EQUAL(a, b) \
+ (memcmp ((const void *) (a), (const void *) (b), sizeof (struct in6_addr)) == 0)
+#endif
+
+
+static const char *
+inet_ntop_win32 (int af, const void *src, char *dst, socklen_t cnt)
+{
+ if (af == AF_INET) {
+ struct sockaddr_in in;
+ memset(&in, 0, sizeof(in));
+ in.sin_family = AF_INET;
+ memcpy(&in.sin_addr, src, sizeof(struct in_addr));
+ getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in),
+ dst, cnt, NULL, 0, NI_NUMERICHOST);
+ return dst;
+ } else if (af == AF_INET6) {
+ struct sockaddr_in6 in;
+ memset(&in, 0, sizeof(in));
+ in.sin6_family = AF_INET6;
+ memcpy(&in.sin6_addr, src, sizeof(struct in_addr6));
+ getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in6),
+ dst, cnt, NULL, 0, NI_NUMERICHOST);
+ return dst;
+ }
+ return NULL;
+}
+
+#endif
+
+
+
+NICEAPI_EXPORT void
+nice_address_init (NiceAddress *addr)
+{
+ addr->s.addr.sa_family = AF_UNSPEC;
+ memset (&addr->s, 0, sizeof(addr->s));
+}
+
+NICEAPI_EXPORT NiceAddress *
+nice_address_new (void)
+{
+ NiceAddress *addr = g_slice_new0 (NiceAddress);
+ nice_address_init (addr);
+ return addr;
+}
+
+
+NICEAPI_EXPORT void
+nice_address_set_ipv4 (NiceAddress *addr, guint32 addr_ipv4)
+{
+ addr->s.ip4.sin_family = AF_INET;
+#ifdef HAVE_SA_LEN
+ addr->s.ip4.sin_len = sizeof (addr->sa.ip4);
+#endif
+ addr->s.ip4.sin_addr.s_addr = addr_ipv4 ? htonl (addr_ipv4) : INADDR_ANY;
+ addr->s.ip4.sin_port = 0;
+}
+
+
+NICEAPI_EXPORT void
+nice_address_set_ipv6 (NiceAddress *addr, const guchar *addr_ipv6)
+{
+ addr->s.ip6.sin6_family = AF_INET6;
+#ifdef HAVE_SA_LEN
+ addr->s.ip6.sin6_len = sizeof (addr->sa.ip6);
+#endif
+ memcpy (addr->s.ip6.sin6_addr.s6_addr, addr_ipv6, 16);
+ addr->s.ip6.sin6_port = 0;
+ addr->s.ip6.sin6_scope_id = 0;
+}
+
+
+NICEAPI_EXPORT void
+nice_address_set_port (NiceAddress *addr, guint port)
+{
+ g_assert (addr);
+
+ switch (addr->s.addr.sa_family)
+ {
+ case AF_INET:
+ addr->s.ip4.sin_port = htons (port);
+ break;
+ case AF_INET6:
+ addr->s.ip6.sin6_port = htons (port);
+ break;
+ default:
+ g_return_if_reached ();
+ }
+}
+
+
+guint
+nice_address_get_port (const NiceAddress *addr)
+{
+ if (!addr)
+ return 0;
+
+ switch (addr->s.addr.sa_family)
+ {
+ case AF_INET:
+ return ntohs (addr->s.ip4.sin_port);
+ case AF_INET6:
+ return ntohs (addr->s.ip6.sin6_port);
+ default:
+ g_return_val_if_reached (0);
+ }
+}
+
+
+NICEAPI_EXPORT gboolean
+nice_address_set_from_string (NiceAddress *addr, const gchar *str)
+{
+ struct addrinfo hints;
+ struct addrinfo *res;
+
+ memset (&hints, 0, sizeof (hints));
+
+ /* AI_NUMERICHOST prevents getaddrinfo() from doing DNS resolution. */
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_flags = AI_NUMERICHOST;
+
+ if (getaddrinfo (str, NULL, &hints, &res) != 0)
+ return FALSE; /* invalid address */
+
+ nice_address_set_from_sockaddr (addr, res->ai_addr);
+
+ freeaddrinfo (res);
+
+ return TRUE;
+}
+
+
+NICEAPI_EXPORT void
+nice_address_set_from_sockaddr (NiceAddress *addr,
+ const struct sockaddr *sa)
+{
+ switch (sa->sa_family)
+ {
+ case AF_INET:
+ memcpy(&addr->s.ip4, sa, sizeof (addr->s.ip4));
+ break;
+ case AF_INET6:
+ memcpy(&addr->s.ip6, sa, sizeof (addr->s.ip6));
+ break;
+ default:
+ g_return_if_reached ();
+ }
+}
+
+
+NICEAPI_EXPORT void
+nice_address_copy_to_sockaddr (const NiceAddress *addr,
+ struct sockaddr *_sa)
+{
+ union {
+ struct sockaddr *addr;
+ struct sockaddr_in *in;
+ struct sockaddr_in6 *in6;
+ } sa;
+
+ sa.addr = _sa;
+
+ g_assert (_sa);
+
+ switch (addr->s.addr.sa_family)
+ {
+ case AF_INET:
+ memcpy (sa.in, &addr->s.ip4, sizeof (*sa.in));
+ break;
+ case AF_INET6:
+ memcpy (sa.in6, &addr->s.ip6, sizeof (*sa.in6));
+ break;
+ default:
+ g_return_if_reached ();
+ }
+}
+
+NICEAPI_EXPORT void
+nice_address_to_string (const NiceAddress *addr, gchar *dst)
+{
+ switch (addr->s.addr.sa_family) {
+ case AF_INET:
+ inet_ntop (AF_INET, &addr->s.ip4.sin_addr, dst, INET_ADDRSTRLEN);
+ break;
+ case AF_INET6:
+ inet_ntop (AF_INET6, &addr->s.ip6.sin6_addr, dst, INET6_ADDRSTRLEN);
+ break;
+ default:
+ g_return_if_reached ();
+ }
+}
+
+
+NICEAPI_EXPORT gboolean
+nice_address_equal (const NiceAddress *a, const NiceAddress *b)
+{
+ if (a->s.addr.sa_family != b->s.addr.sa_family)
+ return FALSE;
+
+ switch (a->s.addr.sa_family)
+ {
+ case AF_INET:
+ return (a->s.ip4.sin_addr.s_addr == b->s.ip4.sin_addr.s_addr)
+ && (a->s.ip4.sin_port == b->s.ip4.sin_port);
+
+ case AF_INET6:
+ return IN6_ARE_ADDR_EQUAL (&a->s.ip6.sin6_addr, &b->s.ip6.sin6_addr)
+ && (a->s.ip6.sin6_port == b->s.ip6.sin6_port)
+ && (a->s.ip6.sin6_scope_id == 0 || b->s.ip6.sin6_scope_id == 0 ||
+ (a->s.ip6.sin6_scope_id == b->s.ip6.sin6_scope_id));
+
+ default:
+ g_return_val_if_reached (FALSE);
+ }
+}
+
+
+NICEAPI_EXPORT NiceAddress *
+nice_address_dup (const NiceAddress *a)
+{
+ NiceAddress *dup = g_slice_new0 (NiceAddress);
+
+ *dup = *a;
+ return dup;
+}
+
+
+NICEAPI_EXPORT void
+nice_address_free (NiceAddress *addr)
+{
+ g_slice_free (NiceAddress, addr);
+}
+
+
+/* "private" in the sense of "not routable on the Internet" */
+static gboolean
+ipv4_address_is_private (guint32 addr)
+{
+ addr = ntohl (addr);
+
+ /* http://tools.ietf.org/html/rfc3330 */
+ return (
+ /* 10.0.0.0/8 */
+ ((addr & 0xff000000) == 0x0a000000) ||
+ /* 172.16.0.0/12 */
+ ((addr & 0xfff00000) == 0xac100000) ||
+ /* 192.168.0.0/16 */
+ ((addr & 0xffff0000) == 0xc0a80000) ||
+ /* 127.0.0.0/8 */
+ ((addr & 0xff000000) == 0x7f000000));
+}
+
+
+static gboolean
+ipv6_address_is_private (const guchar *addr)
+{
+ return (
+ /* fe80::/10 */
+ ((addr[0] == 0xfe) && ((addr[1] & 0xc0) == 0x80)) ||
+ /* fc00::/7 */
+ ((addr[0] & 0xfe) == 0xfc) ||
+ /* ::1 loopback */
+ ((memcmp (addr, "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x01", 16) == 0)));
+}
+
+
+NICEAPI_EXPORT gboolean
+nice_address_is_private (const NiceAddress *a)
+{
+ switch (a->s.addr.sa_family)
+ {
+ case AF_INET:
+ return ipv4_address_is_private (a->s.ip4.sin_addr.s_addr);
+ case AF_INET6:
+ return ipv6_address_is_private (a->s.ip6.sin6_addr.s6_addr);
+ default:
+ g_return_val_if_reached (FALSE);
+ }
+}
+
+
+NICEAPI_EXPORT gboolean
+nice_address_is_valid (const NiceAddress *a)
+{
+ switch (a->s.addr.sa_family)
+ {
+ case AF_INET:
+ case AF_INET6:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+NICEAPI_EXPORT int
+nice_address_ip_version (const NiceAddress *addr)
+{
+ switch (addr->s.addr.sa_family)
+ {
+ case AF_INET:
+ return 4;
+ case AF_INET6:
+ return 6;
+ default:
+ return 0;
+ }
+}
+
+NICEAPI_EXPORT gboolean
+nice_address_equal_no_port (const NiceAddress *a, const NiceAddress *b)
+{
+ if (a->s.addr.sa_family != b->s.addr.sa_family)
+ return FALSE;
+
+ switch (a->s.addr.sa_family)
+ {
+ case AF_INET:
+ return (a->s.ip4.sin_addr.s_addr == b->s.ip4.sin_addr.s_addr);
+
+ case AF_INET6:
+ return IN6_ARE_ADDR_EQUAL (&a->s.ip6.sin6_addr, &b->s.ip6.sin6_addr)
+ && (a->s.ip6.sin6_scope_id == 0 || b->s.ip6.sin6_scope_id == 0 ||
+ (a->s.ip6.sin6_scope_id == b->s.ip6.sin6_scope_id));
+
+ default:
+ g_return_val_if_reached (FALSE);
+ }
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2006-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2006-2009 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ * Dafydd Harries, Collabora Ltd.
+ * Kai Vehmanen
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef __LIBNICE_ADDRESS_H__
+#define __LIBNICE_ADDRESS_H__
+
+/**
+ * SECTION:address
+ * @short_description: IP address convenience library
+ * @stability: Stable
+ *
+ * The #NiceAddress structure will allow you to easily set/get and modify an IPv4
+ * or IPv6 address in order to communicate with the #NiceAgent.
+ */
+
+
+#include <glib.h>
+
+#ifdef G_OS_WIN32
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+
+G_BEGIN_DECLS
+
+
+/**
+ * NiceAddress:
+ *
+ * The #NiceAddress structure that represents an IPv4 or IPv6 address.
+ */
+struct _NiceAddress
+{
+ union
+ {
+ struct sockaddr addr;
+ struct sockaddr_in ip4;
+ struct sockaddr_in6 ip6;
+ } s;
+};
+
+
+/**
+ * NICE_ADDRESS_STRING_LEN:
+ *
+ * The maximum string length representation of an address.
+ * When using nice_address_to_string() make sure the string has a size of
+ * at least %NICE_ADDRESS_STRING_LEN
+ */
+#define NICE_ADDRESS_STRING_LEN INET6_ADDRSTRLEN
+
+typedef struct _NiceAddress NiceAddress;
+
+
+/**
+ * nice_address_init:
+ * @addr: The #NiceAddress to init
+ *
+ * Initialize a #NiceAddress into an undefined address
+ */
+void
+nice_address_init (NiceAddress *addr);
+
+/**
+ * nice_address_new:
+ *
+ * Create a new #NiceAddress with undefined address
+ * You must free it with nice_address_free()
+ *
+ * Returns: The new #NiceAddress
+ */
+NiceAddress *
+nice_address_new (void);
+
+/**
+ * nice_address_free:
+ * @addr: The #NiceAddress to free
+ *
+ * Frees a #NiceAddress created with nice_address_new() or nice_address_dup()
+ */
+void
+nice_address_free (NiceAddress *addr);
+
+/**
+ * nice_address_dup:
+ * @addr: The #NiceAddress to dup
+ *
+ * Creates a new #NiceAddress with the same address as @addr
+ *
+ * Returns: The new #NiceAddress
+ */
+NiceAddress *
+nice_address_dup (const NiceAddress *addr);
+
+
+/**
+ * nice_address_set_ipv4:
+ * @addr: The #NiceAddress to modify
+ * @addr_ipv4: The IPv4 address
+ *
+ * Set @addr to an IPv4 address using the data from @addr_ipv4
+ *
+ <note>
+ <para>
+ This function will reset the port to 0, so make sure you call it before
+ nice_address_set_port()
+ </para>
+ </note>
+ */
+void
+nice_address_set_ipv4 (NiceAddress *addr, guint32 addr_ipv4);
+
+
+/**
+ * nice_address_set_ipv6:
+ * @addr: The #NiceAddress to modify
+ * @addr_ipv6: The IPv6 address
+ *
+ * Set @addr to an IPv6 address using the data from @addr_ipv6
+ *
+ <note>
+ <para>
+ This function will reset the port to 0, so make sure you call it before
+ nice_address_set_port()
+ </para>
+ </note>
+ */
+void
+nice_address_set_ipv6 (NiceAddress *addr, const guchar *addr_ipv6);
+
+
+/**
+ * nice_address_set_port:
+ * @addr: The #NiceAddress to modify
+ * @port: The port to set
+ *
+ * Set the port of @addr to @port
+ */
+void
+nice_address_set_port (NiceAddress *addr, guint port);
+
+/**
+ * nice_address_get_port:
+ * @addr: The #NiceAddress to query
+ *
+ * Retreive the port of @addr
+ *
+ * Returns: The port of @addr
+ */
+guint
+nice_address_get_port (const NiceAddress *addr);
+
+/**
+ * nice_address_set_from_string:
+ * @addr: The #NiceAddress to modify
+ * @str: The string to set
+ *
+ * Sets an IPv4 or IPv6 address from the string @str
+ *
+ * Returns: %TRUE if success, %FALSE on error
+ */
+gboolean
+nice_address_set_from_string (NiceAddress *addr, const gchar *str);
+
+/**
+ * nice_address_set_from_sockaddr:
+ * @addr: The #NiceAddress to modify
+ * @sin: The sockaddr to set
+ *
+ * Sets an IPv4 or IPv6 address from the sockaddr structure @sin
+ *
+ */
+void
+nice_address_set_from_sockaddr (NiceAddress *addr, const struct sockaddr *sin);
+
+
+/**
+ * nice_address_copy_to_sockaddr:
+ * @addr: The #NiceAddress to query
+ * @sin: The sockaddr to fill
+ *
+ * Fills the sockaddr structure @sin with the address contained in @addr
+ *
+ */
+void
+nice_address_copy_to_sockaddr (const NiceAddress *addr, struct sockaddr *sin);
+
+/**
+ * nice_address_equal:
+ * @a: First #NiceAddress to compare
+ * @b: Second #NiceAddress to compare
+ *
+ * Compares two #NiceAddress structures to see if they contain the same address
+ * and the same port.
+ *
+ * Returns: %TRUE if @a and @b are the same address, %FALSE if they are different
+ */
+gboolean
+nice_address_equal (const NiceAddress *a, const NiceAddress *b);
+
+/**
+ * nice_address_equal_no_port:
+ * @a: First #NiceAddress to compare
+ * @b: Second #NiceAddress to compare
+ *
+ * Compares two #NiceAddress structures to see if they contain the same address,
+ * ignoring the port.
+ *
+ * Returns: %TRUE if @a and @b are the same address, %FALSE if they
+ * are different
+ *
+ * Since: 0.1.8
+ */
+gboolean
+nice_address_equal_no_port (const NiceAddress *a, const NiceAddress *b);
+
+/**
+ * nice_address_to_string:
+ * @addr: The #NiceAddress to query
+ * @dst: The string to fill
+ *
+ * Transforms the address @addr into a human readable string
+ *
+ */
+void
+nice_address_to_string (const NiceAddress *addr, gchar *dst);
+
+/**
+ * nice_address_is_private:
+ * @addr: The #NiceAddress to query
+ *
+ * Verifies if the address in @addr is a private address or not
+ *
+ * Returns: %TRUE if @addr is a private address, %FALSE otherwise
+ */
+gboolean
+nice_address_is_private (const NiceAddress *addr);
+
+/**
+ * nice_address_is_valid:
+ * @addr: The #NiceAddress to query
+ *
+ * Validate whether the #NiceAddress @addr is a valid IPv4 or IPv6 address
+ *
+ * Returns: %TRUE if @addr is valid, %FALSE otherwise
+ */
+G_GNUC_WARN_UNUSED_RESULT
+gboolean
+nice_address_is_valid (const NiceAddress *addr);
+
+/**
+ * nice_address_ip_version:
+ * @addr: The #NiceAddress to query
+ *
+ * Returns the IP version of the address
+ *
+ * Returns: 4 for IPv4, 6 for IPv6 and 0 for undefined address
+ */
+G_GNUC_WARN_UNUSED_RESULT
+int
+nice_address_ip_version (const NiceAddress *addr);
+
+G_END_DECLS
+
+#endif /* __LIBNICE_ADDRESS_H__ */
+
--- /dev/null
+
+/* This file is generated by glib-mkenums, do not modify it. This code is licensed under the same license as the containing project. Note that it links to GLib, so must comply with the LGPL linking clauses. */
+
+#include <config.h>
+#include <glib-object.h>
+#include "agent.h"
+#include "pseudotcp.h"
+#include "agent-enum-types.h"
+
+/* enumerations from "./agent.h" */
+GType
+nice_component_state_get_type (void)
+{
+ static GType type = 0;
+ if (!type) {
+ static const GEnumValue values[] = {
+ { NICE_COMPONENT_STATE_DISCONNECTED, "NICE_COMPONENT_STATE_DISCONNECTED", "disconnected" },
+ { NICE_COMPONENT_STATE_GATHERING, "NICE_COMPONENT_STATE_GATHERING", "gathering" },
+ { NICE_COMPONENT_STATE_CONNECTING, "NICE_COMPONENT_STATE_CONNECTING", "connecting" },
+ { NICE_COMPONENT_STATE_CONNECTED, "NICE_COMPONENT_STATE_CONNECTED", "connected" },
+ { NICE_COMPONENT_STATE_READY, "NICE_COMPONENT_STATE_READY", "ready" },
+ { NICE_COMPONENT_STATE_FAILED, "NICE_COMPONENT_STATE_FAILED", "failed" },
+ { NICE_COMPONENT_STATE_LAST, "NICE_COMPONENT_STATE_LAST", "last" },
+ { 0, NULL, NULL }
+ };
+ type = g_enum_register_static ("NiceComponentState", values);
+ }
+ return type;
+}
+GType
+nice_component_type_get_type (void)
+{
+ static GType type = 0;
+ if (!type) {
+ static const GEnumValue values[] = {
+ { NICE_COMPONENT_TYPE_RTP, "NICE_COMPONENT_TYPE_RTP", "rtp" },
+ { NICE_COMPONENT_TYPE_RTCP, "NICE_COMPONENT_TYPE_RTCP", "rtcp" },
+ { 0, NULL, NULL }
+ };
+ type = g_enum_register_static ("NiceComponentType", values);
+ }
+ return type;
+}
+GType
+nice_compatibility_get_type (void)
+{
+ static GType type = 0;
+ if (!type) {
+ static const GEnumValue values[] = {
+ { NICE_COMPATIBILITY_RFC5245, "NICE_COMPATIBILITY_RFC5245", "rfc5245" },
+ { NICE_COMPATIBILITY_DRAFT19, "NICE_COMPATIBILITY_DRAFT19", "draft19" },
+ { NICE_COMPATIBILITY_GOOGLE, "NICE_COMPATIBILITY_GOOGLE", "google" },
+ { NICE_COMPATIBILITY_MSN, "NICE_COMPATIBILITY_MSN", "msn" },
+ { NICE_COMPATIBILITY_WLM2009, "NICE_COMPATIBILITY_WLM2009", "wlm2009" },
+ { NICE_COMPATIBILITY_OC2007, "NICE_COMPATIBILITY_OC2007", "oc2007" },
+ { NICE_COMPATIBILITY_OC2007R2, "NICE_COMPATIBILITY_OC2007R2", "oc2007r2" },
+ { NICE_COMPATIBILITY_LAST, "NICE_COMPATIBILITY_LAST", "last" },
+ { 0, NULL, NULL }
+ };
+ type = g_enum_register_static ("NiceCompatibility", values);
+ }
+ return type;
+}
+GType
+nice_proxy_type_get_type (void)
+{
+ static GType type = 0;
+ if (!type) {
+ static const GEnumValue values[] = {
+ { NICE_PROXY_TYPE_NONE, "NICE_PROXY_TYPE_NONE", "none" },
+ { NICE_PROXY_TYPE_SOCKS5, "NICE_PROXY_TYPE_SOCKS5", "socks5" },
+ { NICE_PROXY_TYPE_HTTP, "NICE_PROXY_TYPE_HTTP", "http" },
+ { NICE_PROXY_TYPE_LAST, "NICE_PROXY_TYPE_LAST", "last" },
+ { 0, NULL, NULL }
+ };
+ type = g_enum_register_static ("NiceProxyType", values);
+ }
+ return type;
+}
+GType
+nice_nomination_mode_get_type (void)
+{
+ static GType type = 0;
+ if (!type) {
+ static const GEnumValue values[] = {
+ { NICE_NOMINATION_MODE_REGULAR, "NICE_NOMINATION_MODE_REGULAR", "regular" },
+ { NICE_NOMINATION_MODE_AGGRESSIVE, "NICE_NOMINATION_MODE_AGGRESSIVE", "aggressive" },
+ { 0, NULL, NULL }
+ };
+ type = g_enum_register_static ("NiceNominationMode", values);
+ }
+ return type;
+}
+GType
+nice_agent_option_get_type (void)
+{
+ static GType type = 0;
+ if (!type) {
+ static const GFlagsValue values[] = {
+ { NICE_AGENT_OPTION_REGULAR_NOMINATION, "NICE_AGENT_OPTION_REGULAR_NOMINATION", "regular-nomination" },
+ { NICE_AGENT_OPTION_RELIABLE, "NICE_AGENT_OPTION_RELIABLE", "reliable" },
+ { NICE_AGENT_OPTION_LITE_MODE, "NICE_AGENT_OPTION_LITE_MODE", "lite-mode" },
+ { NICE_AGENT_OPTION_ICE_TRICKLE, "NICE_AGENT_OPTION_ICE_TRICKLE", "ice-trickle" },
+ { NICE_AGENT_OPTION_SUPPORT_RENOMINATION, "NICE_AGENT_OPTION_SUPPORT_RENOMINATION", "support-renomination" },
+ { 0, NULL, NULL }
+ };
+ type = g_flags_register_static ("NiceAgentOption", values);
+ }
+ return type;
+}
+
+/* enumerations from "./candidate.h" */
+GType
+nice_candidate_type_get_type (void)
+{
+ static GType type = 0;
+ if (!type) {
+ static const GEnumValue values[] = {
+ { NICE_CANDIDATE_TYPE_HOST, "NICE_CANDIDATE_TYPE_HOST", "host" },
+ { NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE, "NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE", "server-reflexive" },
+ { NICE_CANDIDATE_TYPE_PEER_REFLEXIVE, "NICE_CANDIDATE_TYPE_PEER_REFLEXIVE", "peer-reflexive" },
+ { NICE_CANDIDATE_TYPE_RELAYED, "NICE_CANDIDATE_TYPE_RELAYED", "relayed" },
+ { 0, NULL, NULL }
+ };
+ type = g_enum_register_static ("NiceCandidateType", values);
+ }
+ return type;
+}
+GType
+nice_candidate_transport_get_type (void)
+{
+ static GType type = 0;
+ if (!type) {
+ static const GEnumValue values[] = {
+ { NICE_CANDIDATE_TRANSPORT_UDP, "NICE_CANDIDATE_TRANSPORT_UDP", "udp" },
+ { NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE, "NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE", "tcp-active" },
+ { NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE, "NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE", "tcp-passive" },
+ { NICE_CANDIDATE_TRANSPORT_TCP_SO, "NICE_CANDIDATE_TRANSPORT_TCP_SO", "tcp-so" },
+ { 0, NULL, NULL }
+ };
+ type = g_enum_register_static ("NiceCandidateTransport", values);
+ }
+ return type;
+}
+GType
+nice_relay_type_get_type (void)
+{
+ static GType type = 0;
+ if (!type) {
+ static const GEnumValue values[] = {
+ { NICE_RELAY_TYPE_TURN_UDP, "NICE_RELAY_TYPE_TURN_UDP", "udp" },
+ { NICE_RELAY_TYPE_TURN_TCP, "NICE_RELAY_TYPE_TURN_TCP", "tcp" },
+ { NICE_RELAY_TYPE_TURN_TLS, "NICE_RELAY_TYPE_TURN_TLS", "tls" },
+ { 0, NULL, NULL }
+ };
+ type = g_enum_register_static ("NiceRelayType", values);
+ }
+ return type;
+}
+
+/* enumerations from "./pseudotcp.h" */
+GType
+pseudo_tcp_debug_level_get_type (void)
+{
+ static GType type = 0;
+ if (!type) {
+ static const GEnumValue values[] = {
+ { PSEUDO_TCP_DEBUG_NONE, "PSEUDO_TCP_DEBUG_NONE", "none" },
+ { PSEUDO_TCP_DEBUG_NORMAL, "PSEUDO_TCP_DEBUG_NORMAL", "normal" },
+ { PSEUDO_TCP_DEBUG_VERBOSE, "PSEUDO_TCP_DEBUG_VERBOSE", "verbose" },
+ { 0, NULL, NULL }
+ };
+ type = g_enum_register_static ("PseudoTcpDebugLevel", values);
+ }
+ return type;
+}
+GType
+pseudo_tcp_state_get_type (void)
+{
+ static GType type = 0;
+ if (!type) {
+ static const GEnumValue values[] = {
+ { PSEUDO_TCP_LISTEN, "PSEUDO_TCP_LISTEN", "listen" },
+ { PSEUDO_TCP_SYN_SENT, "PSEUDO_TCP_SYN_SENT", "syn-sent" },
+ { PSEUDO_TCP_SYN_RECEIVED, "PSEUDO_TCP_SYN_RECEIVED", "syn-received" },
+ { PSEUDO_TCP_ESTABLISHED, "PSEUDO_TCP_ESTABLISHED", "established" },
+ { PSEUDO_TCP_CLOSED, "PSEUDO_TCP_CLOSED", "closed" },
+ { PSEUDO_TCP_FIN_WAIT_1, "PSEUDO_TCP_FIN_WAIT_1", "fin-wait-1" },
+ { PSEUDO_TCP_FIN_WAIT_2, "PSEUDO_TCP_FIN_WAIT_2", "fin-wait-2" },
+ { PSEUDO_TCP_CLOSING, "PSEUDO_TCP_CLOSING", "closing" },
+ { PSEUDO_TCP_TIME_WAIT, "PSEUDO_TCP_TIME_WAIT", "time-wait" },
+ { PSEUDO_TCP_CLOSE_WAIT, "PSEUDO_TCP_CLOSE_WAIT", "close-wait" },
+ { PSEUDO_TCP_LAST_ACK, "PSEUDO_TCP_LAST_ACK", "last-ack" },
+ { 0, NULL, NULL }
+ };
+ type = g_enum_register_static ("PseudoTcpState", values);
+ }
+ return type;
+}
+GType
+pseudo_tcp_write_result_get_type (void)
+{
+ static GType type = 0;
+ if (!type) {
+ static const GEnumValue values[] = {
+ { WR_SUCCESS, "WR_SUCCESS", "success" },
+ { WR_TOO_LARGE, "WR_TOO_LARGE", "too-large" },
+ { WR_FAIL, "WR_FAIL", "fail" },
+ { 0, NULL, NULL }
+ };
+ type = g_enum_register_static ("PseudoTcpWriteResult", values);
+ }
+ return type;
+}
+GType
+pseudo_tcp_shutdown_get_type (void)
+{
+ static GType type = 0;
+ if (!type) {
+ static const GEnumValue values[] = {
+ { PSEUDO_TCP_SHUTDOWN_RD, "PSEUDO_TCP_SHUTDOWN_RD", "rd" },
+ { PSEUDO_TCP_SHUTDOWN_WR, "PSEUDO_TCP_SHUTDOWN_WR", "wr" },
+ { PSEUDO_TCP_SHUTDOWN_RDWR, "PSEUDO_TCP_SHUTDOWN_RDWR", "rdwr" },
+ { 0, NULL, NULL }
+ };
+ type = g_enum_register_static ("PseudoTcpShutdown", values);
+ }
+ return type;
+}
+
+/* Generated data ends here */
+
--- /dev/null
+
+/* This file is generated by glib-mkenums, do not modify it. This code is licensed under the same license as the containing project. Note that it links to GLib, so must comply with the LGPL linking clauses. */
+
+#ifndef __AGENT_ENUM_TYPES_H__
+#define __AGENT_ENUM_TYPES_H__ 1
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+/* enumerations from "./agent.h" */
+GType nice_component_state_get_type (void) G_GNUC_CONST;
+#define NICE_TYPE_COMPONENT_STATE (nice_component_state_get_type())
+GType nice_component_type_get_type (void) G_GNUC_CONST;
+#define NICE_TYPE_COMPONENT_TYPE (nice_component_type_get_type())
+GType nice_compatibility_get_type (void) G_GNUC_CONST;
+#define NICE_TYPE_COMPATIBILITY (nice_compatibility_get_type())
+GType nice_proxy_type_get_type (void) G_GNUC_CONST;
+#define NICE_TYPE_PROXY_TYPE (nice_proxy_type_get_type())
+GType nice_nomination_mode_get_type (void) G_GNUC_CONST;
+#define NICE_TYPE_NOMINATION_MODE (nice_nomination_mode_get_type())
+GType nice_agent_option_get_type (void) G_GNUC_CONST;
+#define NICE_TYPE_AGENT_OPTION (nice_agent_option_get_type())
+/* enumerations from "./candidate.h" */
+GType nice_candidate_type_get_type (void) G_GNUC_CONST;
+#define NICE_TYPE_CANDIDATE_TYPE (nice_candidate_type_get_type())
+GType nice_candidate_transport_get_type (void) G_GNUC_CONST;
+#define NICE_TYPE_CANDIDATE_TRANSPORT (nice_candidate_transport_get_type())
+GType nice_relay_type_get_type (void) G_GNUC_CONST;
+#define NICE_TYPE_RELAY_TYPE (nice_relay_type_get_type())
+/* enumerations from "./pseudotcp.h" */
+GType pseudo_tcp_debug_level_get_type (void) G_GNUC_CONST;
+#define NICE_TYPE_TCP_DEBUG_LEVEL (pseudo_tcp_debug_level_get_type())
+GType pseudo_tcp_state_get_type (void) G_GNUC_CONST;
+#define NICE_TYPE_TCP_STATE (pseudo_tcp_state_get_type())
+GType pseudo_tcp_write_result_get_type (void) G_GNUC_CONST;
+#define NICE_TYPE_TCP_WRITE_RESULT (pseudo_tcp_write_result_get_type())
+GType pseudo_tcp_shutdown_get_type (void) G_GNUC_CONST;
+#define NICE_TYPE_TCP_SHUTDOWN (pseudo_tcp_shutdown_get_type())
+G_END_DECLS
+
+#endif /* !AGENT_ENUM_TYPES_H */
+
+/* Generated data ends here */
+
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2006-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2006-2009 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Dafydd Harries, Collabora Ltd.
+ * Youness Alaoui, Collabora Ltd.
+ * Kai Vehmanen, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef _NICE_AGENT_PRIV_H
+#define _NICE_AGENT_PRIV_H
+
+/* note: this is a private header part of agent.h */
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#else
+#define NICEAPI_EXPORT
+#endif
+
+#include <glib.h>
+
+#include "agent.h"
+
+/**
+ * NiceInputMessageIter:
+ * @message: index of the message currently being written into
+ * @buffer: index of the buffer currently being written into
+ * @offset: byte offset into the buffer
+ *
+ * Iterator for sequentially writing into an array of #NiceInputMessages,
+ * tracking the current write position (i.e. the index of the next byte to be
+ * written).
+ *
+ * If @message is equal to the number of messages in the associated
+ * #NiceInputMessage array, and @buffer and @offset are zero, the iterator is at
+ * the end of the messages array, and the array is (presumably) full.
+ *
+ * Since: 0.1.5
+ */
+typedef struct {
+ guint message;
+ guint buffer;
+ gsize offset;
+} NiceInputMessageIter;
+
+void
+nice_input_message_iter_reset (NiceInputMessageIter *iter);
+gboolean
+nice_input_message_iter_is_at_end (NiceInputMessageIter *iter,
+ NiceInputMessage *messages, guint n_messages);
+guint
+nice_input_message_iter_get_n_valid_messages (NiceInputMessageIter *iter);
+gboolean
+nice_input_message_iter_compare (const NiceInputMessageIter *a,
+ const NiceInputMessageIter *b);
+
+
+#include "socket.h"
+#include "candidate.h"
+#include "stream.h"
+#include "conncheck.h"
+#include "component.h"
+#include "random.h"
+#include "stun/stunagent.h"
+#include "stun/usages/turn.h"
+#include "stun/usages/ice.h"
+
+#ifdef HAVE_GUPNP
+#include <libgupnp-igd/gupnp-simple-igd-thread.h>
+#endif
+
+/* XXX: starting from ICE ID-18, Ta SHOULD now be set according
+ * to session bandwidth -> this is not yet implemented in NICE */
+
+#define NICE_AGENT_TIMER_TA_DEFAULT 20 /* timer Ta, msecs (impl. defined) */
+#define NICE_AGENT_TIMER_TR_DEFAULT 25000 /* timer Tr, msecs (impl. defined) */
+#define NICE_AGENT_MAX_CONNECTIVITY_CHECKS_DEFAULT 100 /* see spec 5.7.3 (ID-19) */
+
+
+/* An upper limit to size of STUN packets handled (based on Ethernet
+ * MTU and estimated typical sizes of ICE STUN packet */
+#define MAX_STUN_DATAGRAM_PAYLOAD 1300
+
+#define NICE_COMPONENT_MAX_VALID_CANDIDATES 50 /* maximum number of validates remote candidates to keep, the number is arbitrary but hopefully large enough */
+
+/* A convenient macro to test if the agent is compatible with RFC5245
+ * or OC2007R2. Specifically these two modes share the support
+ * of the regular or aggressive nomination mode */
+#define NICE_AGENT_IS_COMPATIBLE_WITH_RFC5245_OR_OC2007R2(obj) \
+ ((obj)->compatibility == NICE_COMPATIBILITY_RFC5245 || \
+ (obj)->compatibility == NICE_COMPATIBILITY_OC2007R2)
+
+/* A grace period before declaring a component as failed, in msecs. This
+ * delay is added to reduce the chance to see the agent receiving new
+ * stun activity just after the conncheck list has been declared failed,
+ * reactiviting conncheck activity, and causing a (valid) state
+ * transitions like that: connecting -> failed -> connecting ->
+ * connected -> ready.
+ * Such transitions are not buggy per-se, but may break the
+ * test-suite, that counts precisely the number of time each state
+ * has been set, and doesnt expect these transcient failed states.
+ */
+#define NICE_AGENT_MAX_TIMER_GRACE_PERIOD 1000
+
+struct _NiceAgent
+{
+ GObject parent; /* gobject pointer */
+
+ GMutex agent_mutex; /* Mutex used for thread-safe lib */
+
+ gboolean full_mode; /* property: full-mode */
+ gchar *stun_server_ip; /* property: STUN server IP */
+ guint stun_server_port; /* property: STUN server port */
+ gchar *proxy_ip; /* property: Proxy server IP */
+ guint proxy_port; /* property: Proxy server port */
+ NiceProxyType proxy_type; /* property: Proxy type */
+ gchar *proxy_username; /* property: Proxy username */
+ gchar *proxy_password; /* property: Proxy password */
+ gboolean saved_controlling_mode;/* property: controlling-mode */
+ guint timer_ta; /* property: timer Ta */
+ guint max_conn_checks; /* property: max connectivity checks */
+ gboolean force_relay; /* property: force relay */
+ guint stun_max_retransmissions; /* property: stun max retransmissions, Rc */
+ guint stun_initial_timeout; /* property: stun initial timeout, RTO */
+ guint stun_reliable_timeout; /* property: stun reliable timeout */
+ NiceNominationMode nomination_mode; /* property: Nomination mode */
+ gboolean support_renomination; /* property: support RENOMINATION STUN attribute */
+
+ GSList *local_addresses; /* list of NiceAddresses for local
+ interfaces */
+ GSList *streams; /* list of Stream objects */
+ GMainContext *main_context; /* main context pointer */
+ guint next_candidate_id; /* id of next created candidate */
+ guint next_stream_id; /* id of next created candidate */
+ NiceRNG *rng; /* random number generator */
+ GSList *discovery_list; /* list of CandidateDiscovery items */
+ GSList *triggered_check_queue; /* pairs in the triggered check list */
+ guint discovery_unsched_items; /* number of discovery items unscheduled */
+ GSource *discovery_timer_source; /* source of discovery timer */
+ GSource *conncheck_timer_source; /* source of conncheck timer */
+ GSource *keepalive_timer_source; /* source of keepalive timer */
+ GSList *refresh_list; /* list of CandidateRefresh items */
+ guint64 tie_breaker; /* tie breaker (ICE sect 5.2
+ "Determining Role" ID-19) */
+ NiceCompatibility compatibility; /* property: Compatibility mode */
+ gboolean media_after_tick; /* Received media after keepalive tick */
+#ifdef HAVE_GUPNP
+ GUPnPSimpleIgdThread* upnp; /* GUPnP Single IGD agent */
+ gboolean upnp_enabled; /* whether UPnP discovery is enabled */
+ guint upnp_timeout; /* UPnP discovery timeout */
+ GSList *upnp_mapping; /* NiceAddresses of cands being mapped */
+ GSource *upnp_timer_source; /* source of upnp timeout timer */
+#endif
+ gchar *software_attribute; /* SOFTWARE attribute */
+ gboolean reliable; /* property: reliable */
+ gboolean keepalive_conncheck; /* property: keepalive_conncheck */
+
+ GQueue pending_signals;
+ guint16 rfc4571_expecting_length;
+ gboolean use_ice_udp;
+ gboolean use_ice_tcp;
+ gboolean use_ice_trickle;
+
+ guint conncheck_timer_grace_period; /* ongoing delay before timer stop */
+ gboolean controlling_mode; /* controlling mode used by the
+ conncheck */
+ /* XXX: add pointer to internal data struct for ABI-safe extensions */
+};
+
+gboolean
+agent_find_component (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ NiceStream **stream,
+ NiceComponent **component) G_GNUC_WARN_UNUSED_RESULT;
+
+NiceStream *agent_find_stream (NiceAgent *agent, guint stream_id);
+
+void agent_gathering_done (NiceAgent *agent);
+void agent_signal_gathering_done (NiceAgent *agent);
+
+void agent_lock (NiceAgent *agent);
+void agent_unlock (NiceAgent *agent);
+void agent_unlock_and_emit (NiceAgent *agent);
+
+void agent_signal_new_selected_pair (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ NiceCandidate *lcandidate,
+ NiceCandidate *rcandidate);
+
+void agent_signal_component_state_change (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ NiceComponentState state);
+
+void agent_signal_new_candidate (
+ NiceAgent *agent,
+ NiceCandidate *candidate);
+
+void agent_signal_new_remote_candidate (NiceAgent *agent, NiceCandidate *candidate);
+
+void agent_signal_initial_binding_request_received (NiceAgent *agent, NiceStream *stream);
+
+guint64 agent_candidate_pair_priority (NiceAgent *agent, NiceCandidate *local, NiceCandidate *remote);
+
+typedef gboolean (*NiceTimeoutLockedCallback)(NiceAgent *agent,
+ gpointer user_data);
+void agent_timeout_add_with_context (NiceAgent *agent, GSource **out,
+ const gchar *name, guint interval, NiceTimeoutLockedCallback function,
+ gpointer data);
+void agent_timeout_add_seconds_with_context (NiceAgent *agent, GSource **out,
+ const gchar *name, guint interval, NiceTimeoutLockedCallback function,
+ gpointer data);
+
+StunUsageIceCompatibility agent_to_ice_compatibility (NiceAgent *agent);
+StunUsageTurnCompatibility agent_to_turn_compatibility (NiceAgent *agent);
+NiceTurnSocketCompatibility agent_to_turn_socket_compatibility (NiceAgent *agent);
+
+void agent_remove_local_candidate (NiceAgent *agent,
+ NiceCandidate *candidate);
+
+void nice_agent_init_stun_agent (NiceAgent *agent, StunAgent *stun_agent);
+
+void _priv_set_socket_tos (NiceAgent *agent, NiceSocket *sock, gint tos);
+
+void _tcp_sock_is_writable (NiceSocket *sock, gpointer user_data);
+
+gboolean
+component_io_cb (
+ GSocket *gsocket,
+ GIOCondition condition,
+ gpointer data);
+
+gsize
+memcpy_buffer_to_input_message (NiceInputMessage *message,
+ const guint8 *buffer, gsize buffer_length);
+guint8 *
+compact_input_message (const NiceInputMessage *message, gsize *buffer_length);
+
+guint8 *
+compact_output_message (const NiceOutputMessage *message, gsize *buffer_length);
+
+gsize
+output_message_get_size (const NiceOutputMessage *message);
+
+gsize
+input_message_get_size (const NiceInputMessage *message);
+
+gssize agent_socket_send (NiceSocket *sock, const NiceAddress *addr, gsize len,
+ const gchar *buf);
+
+
+guint32
+nice_candidate_jingle_priority (NiceCandidate *candidate);
+
+guint32
+nice_candidate_msn_priority (NiceCandidate *candidate);
+
+guint32
+nice_candidate_ice_priority_full (guint type_pref, guint local_pref,
+ guint component_id);
+
+guint32
+nice_candidate_ice_priority (const NiceCandidate *candidate,
+ gboolean reliable, gboolean nat_assisted);
+
+guint32
+nice_candidate_ms_ice_priority (const NiceCandidate *candidate,
+ gboolean reliable, gboolean nat_assisted);
+
+guint64
+nice_candidate_pair_priority (guint32 o_prio, guint32 a_prio);
+
+/*
+ * nice_debug_init:
+ *
+ * Initialize the debugging system. Uses the NICE_DEBUG environment variable
+ * to set the appropriate debugging flags
+ */
+void nice_debug_init (void);
+
+
+#ifdef NDEBUG
+static inline gboolean nice_debug_is_enabled (void) { return FALSE; }
+static inline gboolean nice_debug_is_verbose (void) { return FALSE; }
+static inline void nice_debug (const char *fmt, ...) { }
+static inline void nice_debug_verbose (const char *fmt, ...) { }
+#else
+gboolean nice_debug_is_enabled (void);
+gboolean nice_debug_is_verbose (void);
+void nice_debug (const char *fmt, ...) G_GNUC_PRINTF (1, 2);
+void nice_debug_verbose (const char *fmt, ...) G_GNUC_PRINTF (1, 2);
+#endif
+
+#if !GLIB_CHECK_VERSION(2, 59, 0)
+#if __GNUC__ > 6
+#define G_GNUC_FALLTHROUGH __attribute__((fallthrough))
+#else
+#define G_GNUC_FALLTHROUGH
+#endif /* __GNUC__ */
+#endif
+
+#endif /*_NICE_AGENT_PRIV_H */
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2006-2010, 2013 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2006-2010 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Dafydd Harries, Collabora Ltd.
+ * Youness Alaoui, Collabora Ltd.
+ * Kai Vehmanen, Nokia
+ * Philip Withnall, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#else
+#define NICEAPI_EXPORT
+#endif
+
+#include <glib.h>
+#include <gobject/gvaluecollector.h>
+
+#include <string.h>
+#include <errno.h>
+
+#ifndef G_OS_WIN32
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+
+#include "debug.h"
+
+#include "socket.h"
+#include "stun/usages/turn.h"
+#include "candidate.h"
+#include "component.h"
+#include "conncheck.h"
+#include "discovery.h"
+#include "agent.h"
+#include "agent-priv.h"
+#include "iostream.h"
+
+#include "stream.h"
+#include "interfaces.h"
+
+#include "pseudotcp.h"
+#include "agent-enum-types.h"
+
+/* Maximum size of a UDP packet’s payload, as the packet’s length field is 16b
+ * wide. */
+#define MAX_BUFFER_SIZE ((1 << 16) - 1) /* 65535 */
+
+#define DEFAULT_STUN_PORT 3478
+#define DEFAULT_UPNP_TIMEOUT 200 /* milliseconds */
+
+#define MAX_TCP_MTU 1400 /* Use 1400 because of VPNs and we assume IEE 802.3 */
+
+static void
+nice_debug_input_message_composition (const NiceInputMessage *messages,
+ guint n_messages);
+static const gchar *_cand_type_to_sdp (NiceCandidateType type);
+
+G_DEFINE_TYPE (NiceAgent, nice_agent, G_TYPE_OBJECT);
+
+enum
+{
+ PROP_COMPATIBILITY = 1,
+ PROP_MAIN_CONTEXT,
+ PROP_STUN_SERVER,
+ PROP_STUN_SERVER_PORT,
+ PROP_CONTROLLING_MODE,
+ PROP_FULL_MODE,
+ PROP_STUN_PACING_TIMER,
+ PROP_MAX_CONNECTIVITY_CHECKS,
+ PROP_PROXY_TYPE,
+ PROP_PROXY_IP,
+ PROP_PROXY_PORT,
+ PROP_PROXY_USERNAME,
+ PROP_PROXY_PASSWORD,
+ PROP_UPNP,
+ PROP_UPNP_TIMEOUT,
+ PROP_RELIABLE,
+ PROP_ICE_UDP,
+ PROP_ICE_TCP,
+ PROP_BYTESTREAM_TCP,
+ PROP_KEEPALIVE_CONNCHECK,
+ PROP_FORCE_RELAY,
+ PROP_STUN_MAX_RETRANSMISSIONS,
+ PROP_STUN_INITIAL_TIMEOUT,
+ PROP_STUN_RELIABLE_TIMEOUT,
+ PROP_NOMINATION_MODE,
+ PROP_ICE_TRICKLE,
+ PROP_SUPPORT_RENOMINATION,
+};
+
+
+enum
+{
+ SIGNAL_COMPONENT_STATE_CHANGED,
+ SIGNAL_CANDIDATE_GATHERING_DONE,
+ SIGNAL_NEW_SELECTED_PAIR,
+ SIGNAL_NEW_CANDIDATE,
+ SIGNAL_NEW_REMOTE_CANDIDATE,
+ SIGNAL_INITIAL_BINDING_REQUEST_RECEIVED,
+ SIGNAL_RELIABLE_TRANSPORT_WRITABLE,
+ SIGNAL_STREAMS_REMOVED,
+ SIGNAL_NEW_SELECTED_PAIR_FULL,
+ SIGNAL_NEW_CANDIDATE_FULL,
+ SIGNAL_NEW_REMOTE_CANDIDATE_FULL,
+
+ N_SIGNALS,
+};
+
+static guint signals[N_SIGNALS];
+
+static void priv_stop_upnp (NiceAgent *agent);
+
+static void pseudo_tcp_socket_opened (PseudoTcpSocket *sock, gpointer user_data);
+static void pseudo_tcp_socket_readable (PseudoTcpSocket *sock, gpointer user_data);
+static void pseudo_tcp_socket_writable (PseudoTcpSocket *sock, gpointer user_data);
+static void pseudo_tcp_socket_closed (PseudoTcpSocket *sock, guint32 err,
+ gpointer user_data);
+static PseudoTcpWriteResult pseudo_tcp_socket_write_packet (PseudoTcpSocket *sock,
+ const gchar *buffer, guint32 len, gpointer user_data);
+static void adjust_tcp_clock (NiceAgent *agent, NiceStream *stream, NiceComponent *component);
+
+static void nice_agent_dispose (GObject *object);
+static void nice_agent_get_property (GObject *object,
+ guint property_id, GValue *value, GParamSpec *pspec);
+static void nice_agent_set_property (GObject *object,
+ guint property_id, const GValue *value, GParamSpec *pspec);
+
+void agent_lock (NiceAgent *agent)
+{
+ g_mutex_lock (&agent->agent_mutex);
+}
+
+void agent_unlock (NiceAgent *agent)
+{
+ g_mutex_unlock (&agent->agent_mutex);
+}
+
+static GType _nice_agent_stream_ids_get_type (void);
+
+G_DEFINE_POINTER_TYPE (_NiceAgentStreamIds, _nice_agent_stream_ids);
+
+#define NICE_TYPE_AGENT_STREAM_IDS _nice_agent_stream_ids_get_type ()
+
+typedef struct {
+ guint signal_id;
+ GSignalQuery query;
+ GValue *params;
+} QueuedSignal;
+
+
+static void
+free_queued_signal (QueuedSignal *sig)
+{
+ guint i;
+
+ g_value_unset (&sig->params[0]);
+
+ for (i = 0; i < sig->query.n_params; i++) {
+ if (G_VALUE_HOLDS(&sig->params[i + 1], NICE_TYPE_AGENT_STREAM_IDS))
+ g_free (g_value_get_pointer (&sig->params[i + 1]));
+ g_value_unset (&sig->params[i + 1]);
+ }
+
+ g_slice_free1 (sizeof(GValue) * (sig->query.n_params + 1), sig->params);
+ g_slice_free (QueuedSignal, sig);
+}
+
+void
+agent_unlock_and_emit (NiceAgent *agent)
+{
+ GQueue queue = G_QUEUE_INIT;
+ QueuedSignal *sig;
+
+ queue = agent->pending_signals;
+ g_queue_init (&agent->pending_signals);
+
+ agent_unlock (agent);
+
+ while ((sig = g_queue_pop_head (&queue))) {
+ g_signal_emitv (sig->params, sig->signal_id, 0, NULL);
+
+ free_queued_signal (sig);
+ }
+}
+
+static void
+agent_queue_signal (NiceAgent *agent, guint signal_id, ...)
+{
+ QueuedSignal *sig;
+ guint i;
+ gchar *error = NULL;
+ va_list var_args;
+
+ sig = g_slice_new (QueuedSignal);
+ g_signal_query (signal_id, &sig->query);
+
+ sig->signal_id = signal_id;
+ sig->params = g_slice_alloc0 (sizeof(GValue) * (sig->query.n_params + 1));
+
+ g_value_init (&sig->params[0], G_TYPE_OBJECT);
+ g_value_set_object (&sig->params[0], agent);
+
+ va_start (var_args, signal_id);
+ for (i = 0; i < sig->query.n_params; i++) {
+ G_VALUE_COLLECT_INIT (&sig->params[i + 1], sig->query.param_types[i],
+ var_args, 0, &error);
+ if (error)
+ break;
+ }
+ va_end (var_args);
+
+ if (error) {
+ free_queued_signal (sig);
+ g_critical ("Error collecting values for signal: %s", error);
+ g_free (error);
+ return;
+ }
+
+ g_queue_push_tail (&agent->pending_signals, sig);
+}
+
+
+StunUsageIceCompatibility
+agent_to_ice_compatibility (NiceAgent *agent)
+{
+ return agent->compatibility == NICE_COMPATIBILITY_GOOGLE ?
+ STUN_USAGE_ICE_COMPATIBILITY_GOOGLE :
+ agent->compatibility == NICE_COMPATIBILITY_MSN ?
+ STUN_USAGE_ICE_COMPATIBILITY_MSN :
+ agent->compatibility == NICE_COMPATIBILITY_WLM2009 ?
+ STUN_USAGE_ICE_COMPATIBILITY_MSICE2 :
+ agent->compatibility == NICE_COMPATIBILITY_OC2007 ?
+ STUN_USAGE_ICE_COMPATIBILITY_MSN :
+ agent->compatibility == NICE_COMPATIBILITY_OC2007R2 ?
+ STUN_USAGE_ICE_COMPATIBILITY_MSICE2 :
+ STUN_USAGE_ICE_COMPATIBILITY_RFC5245;
+}
+
+
+StunUsageTurnCompatibility
+agent_to_turn_compatibility (NiceAgent *agent)
+{
+ return agent->compatibility == NICE_COMPATIBILITY_GOOGLE ?
+ STUN_USAGE_TURN_COMPATIBILITY_GOOGLE :
+ agent->compatibility == NICE_COMPATIBILITY_MSN ?
+ STUN_USAGE_TURN_COMPATIBILITY_MSN :
+ agent->compatibility == NICE_COMPATIBILITY_WLM2009 ?
+ STUN_USAGE_TURN_COMPATIBILITY_MSN :
+ agent->compatibility == NICE_COMPATIBILITY_OC2007 ?
+ STUN_USAGE_TURN_COMPATIBILITY_OC2007 :
+ agent->compatibility == NICE_COMPATIBILITY_OC2007R2 ?
+ STUN_USAGE_TURN_COMPATIBILITY_OC2007 :
+ STUN_USAGE_TURN_COMPATIBILITY_RFC5766;
+}
+
+NiceTurnSocketCompatibility
+agent_to_turn_socket_compatibility (NiceAgent *agent)
+{
+ return agent->compatibility == NICE_COMPATIBILITY_GOOGLE ?
+ NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE :
+ agent->compatibility == NICE_COMPATIBILITY_MSN ?
+ NICE_TURN_SOCKET_COMPATIBILITY_MSN :
+ agent->compatibility == NICE_COMPATIBILITY_WLM2009 ?
+ NICE_TURN_SOCKET_COMPATIBILITY_MSN :
+ agent->compatibility == NICE_COMPATIBILITY_OC2007 ?
+ NICE_TURN_SOCKET_COMPATIBILITY_OC2007 :
+ agent->compatibility == NICE_COMPATIBILITY_OC2007R2 ?
+ NICE_TURN_SOCKET_COMPATIBILITY_OC2007 :
+ NICE_TURN_SOCKET_COMPATIBILITY_RFC5766;
+}
+
+NiceStream *agent_find_stream (NiceAgent *agent, guint stream_id)
+{
+ GSList *i;
+
+ for (i = agent->streams; i; i = i->next)
+ {
+ NiceStream *s = i->data;
+
+ if (s->id == stream_id)
+ return s;
+ }
+
+ return NULL;
+}
+
+
+gboolean
+agent_find_component (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ NiceStream **stream,
+ NiceComponent **component)
+{
+ NiceStream *s;
+ NiceComponent *c;
+
+ s = agent_find_stream (agent, stream_id);
+
+ if (s == NULL)
+ return FALSE;
+
+ c = nice_stream_find_component_by_id (s, component_id);
+
+ if (c == NULL)
+ return FALSE;
+
+ if (stream)
+ *stream = s;
+
+ if (component)
+ *component = c;
+
+ return TRUE;
+}
+
+static void
+nice_agent_class_init (NiceAgentClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->get_property = nice_agent_get_property;
+ gobject_class->set_property = nice_agent_set_property;
+ gobject_class->dispose = nice_agent_dispose;
+
+ /* install properties */
+ /**
+ * NiceAgent:main-context:
+ *
+ * A GLib main context is needed for all timeouts used by libnice.
+ * This is a property being set by the nice_agent_new() call.
+ */
+ g_object_class_install_property (gobject_class, PROP_MAIN_CONTEXT,
+ g_param_spec_pointer (
+ "main-context",
+ "The GMainContext to use for timeouts",
+ "The GMainContext to use for timeouts",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ /**
+ * NiceAgent:compatibility:
+ *
+ * The Nice agent can work in various compatibility modes depending on
+ * what the application/peer needs.
+ * <para> See also: #NiceCompatibility</para>
+ */
+ g_object_class_install_property (gobject_class, PROP_COMPATIBILITY,
+ g_param_spec_uint (
+ "compatibility",
+ "ICE specification compatibility",
+ "The compatibility mode for the agent",
+ NICE_COMPATIBILITY_RFC5245, NICE_COMPATIBILITY_LAST,
+ NICE_COMPATIBILITY_RFC5245,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (gobject_class, PROP_STUN_SERVER,
+ g_param_spec_string (
+ "stun-server",
+ "STUN server IP address",
+ "The IP address (not the hostname) of the STUN server to use",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_STUN_SERVER_PORT,
+ g_param_spec_uint (
+ "stun-server-port",
+ "STUN server port",
+ "Port of the STUN server used to gather server-reflexive candidates",
+ 1, 65536,
+ 1, /* not a construct property, ignored */
+ G_PARAM_READWRITE));
+
+ /**
+ * NiceAgent:controlling-mode:
+ *
+ * Whether the agent has the controlling role. This property should
+ * be modified before gathering candidates, any modification occuring
+ * later will be hold until ICE is restarted.
+ */
+ g_object_class_install_property (gobject_class, PROP_CONTROLLING_MODE,
+ g_param_spec_boolean (
+ "controlling-mode",
+ "ICE controlling mode",
+ "Whether the agent is in controlling mode",
+ FALSE, /* not a construct property, ignored */
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_FULL_MODE,
+ g_param_spec_boolean (
+ "full-mode",
+ "ICE full mode",
+ "Whether agent runs in ICE full mode",
+ TRUE, /* use full mode by default */
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (gobject_class, PROP_STUN_PACING_TIMER,
+ g_param_spec_uint (
+ "stun-pacing-timer",
+ "STUN pacing timer",
+ "Timer 'Ta' (msecs) used in the IETF ICE specification for pacing "
+ "candidate gathering and sending of connectivity checks",
+ 1, 0xffffffff,
+ NICE_AGENT_TIMER_TA_DEFAULT,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ /* note: according to spec recommendation in sect 5.7.3 (ID-19) */
+ g_object_class_install_property (gobject_class, PROP_MAX_CONNECTIVITY_CHECKS,
+ g_param_spec_uint (
+ "max-connectivity-checks",
+ "Maximum number of connectivity checks",
+ "Upper limit for the total number of connectivity checks performed",
+ 0, 0xffffffff,
+ 0, /* default set in init */
+ G_PARAM_READWRITE));
+
+ /**
+ * NiceAgent:nomination-mode:
+ *
+ * The nomination mode used in the ICE specification for describing
+ * the selection of valid pairs to be used upstream.
+ * <para> See also: #NiceNominationMode </para>
+ *
+ * Since: 0.1.15
+ */
+ g_object_class_install_property (gobject_class, PROP_NOMINATION_MODE,
+ g_param_spec_enum (
+ "nomination-mode",
+ "ICE nomination mode",
+ "Nomination mode used in the ICE specification for describing "
+ "the selection of valid pairs to be used upstream",
+ NICE_TYPE_NOMINATION_MODE, NICE_NOMINATION_MODE_AGGRESSIVE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ /**
+ * NiceAgent:support-renomination:
+ *
+ * Support RENOMINATION STUN attribute proposed here:
+ * https://tools.ietf.org/html/draft-thatcher-ice-renomination-00 As
+ * soon as RENOMINATION attribute is received from remote
+ * candidate's address, corresponding candidates pair gets
+ * selected. This is specific to Google Chrome/libWebRTC.
+ */
+ g_object_class_install_property (gobject_class, PROP_SUPPORT_RENOMINATION,
+ g_param_spec_boolean (
+ "support-renomination",
+ "Support RENOMINATION STUN attribute",
+ "As soon as RENOMINATION attribute is received from remote candidate's address, "
+ "corresponding candidates pair gets selected.",
+ FALSE,
+ G_PARAM_READWRITE));
+
+ /**
+ * NiceAgent:proxy-ip:
+ *
+ * The proxy server IP used to bypass a proxy firewall
+ *
+ * Since: 0.0.4
+ */
+ g_object_class_install_property (gobject_class, PROP_PROXY_IP,
+ g_param_spec_string (
+ "proxy-ip",
+ "Proxy server IP",
+ "The proxy server IP used to bypass a proxy firewall",
+ NULL,
+ G_PARAM_READWRITE));
+
+ /**
+ * NiceAgent:proxy-port:
+ *
+ * The proxy server port used to bypass a proxy firewall
+ *
+ * Since: 0.0.4
+ */
+ g_object_class_install_property (gobject_class, PROP_PROXY_PORT,
+ g_param_spec_uint (
+ "proxy-port",
+ "Proxy server port",
+ "The Proxy server port used to bypass a proxy firewall",
+ 1, 65536,
+ 1,
+ G_PARAM_READWRITE));
+
+ /**
+ * NiceAgent:proxy-type:
+ *
+ * The type of proxy set in the proxy-ip property
+ *
+ * Since: 0.0.4
+ */
+ g_object_class_install_property (gobject_class, PROP_PROXY_TYPE,
+ g_param_spec_uint (
+ "proxy-type",
+ "Type of proxy to use",
+ "The type of proxy set in the proxy-ip property",
+ NICE_PROXY_TYPE_NONE, NICE_PROXY_TYPE_LAST,
+ NICE_PROXY_TYPE_NONE,
+ G_PARAM_READWRITE));
+
+ /**
+ * NiceAgent:proxy-username:
+ *
+ * The username used to authenticate with the proxy
+ *
+ * Since: 0.0.4
+ */
+ g_object_class_install_property (gobject_class, PROP_PROXY_USERNAME,
+ g_param_spec_string (
+ "proxy-username",
+ "Proxy server username",
+ "The username used to authenticate with the proxy",
+ NULL,
+ G_PARAM_READWRITE));
+
+ /**
+ * NiceAgent:proxy-password:
+ *
+ * The password used to authenticate with the proxy
+ *
+ * Since: 0.0.4
+ */
+ g_object_class_install_property (gobject_class, PROP_PROXY_PASSWORD,
+ g_param_spec_string (
+ "proxy-password",
+ "Proxy server password",
+ "The password used to authenticate with the proxy",
+ NULL,
+ G_PARAM_READWRITE));
+
+ /**
+ * NiceAgent:upnp:
+ *
+ * Whether the agent should use UPnP to open a port in the router and
+ * get the external IP
+ *
+ * Since: 0.0.7
+ */
+ g_object_class_install_property (gobject_class, PROP_UPNP,
+ g_param_spec_boolean (
+ "upnp",
+#ifdef HAVE_GUPNP
+ "Use UPnP",
+ "Whether the agent should use UPnP to open a port in the router and "
+ "get the external IP",
+#else
+ "Use UPnP (disabled in build)",
+ "Does nothing because libnice was not built with UPnP support",
+#endif
+ TRUE, /* enable UPnP by default */
+ G_PARAM_READWRITE| G_PARAM_CONSTRUCT));
+
+ /**
+ * NiceAgent:upnp-timeout:
+ *
+ * The maximum amount of time (in milliseconds) to wait for UPnP discovery to
+ * finish before signaling the #NiceAgent::candidate-gathering-done signal
+ *
+ * Since: 0.0.7
+ */
+ g_object_class_install_property (gobject_class, PROP_UPNP_TIMEOUT,
+ g_param_spec_uint (
+ "upnp-timeout",
+#ifdef HAVE_GUPNP
+ "Timeout for UPnP discovery",
+ "The maximum amount of time to wait for UPnP discovery to finish before "
+ "signaling the candidate-gathering-done signal",
+#else
+ "Timeout for UPnP discovery (disabled in build)",
+ "Does nothing because libnice was not built with UPnP support",
+#endif
+ 100, 60000,
+ DEFAULT_UPNP_TIMEOUT,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ /**
+ * NiceAgent:reliable:
+ *
+ * Whether the agent is providing a reliable transport of messages (through
+ * ICE-TCP or PseudoTCP over ICE-UDP)
+ *
+ * Since: 0.0.11
+ */
+ g_object_class_install_property (gobject_class, PROP_RELIABLE,
+ g_param_spec_boolean (
+ "reliable",
+ "reliable mode",
+ "Whether the agent provides a reliable transport of messages",
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ /**
+ * NiceAgent:ice-udp:
+ *
+ * Whether the agent should use ICE-UDP when gathering candidates.
+ * If the option is disabled, no UDP candidates will be generated. If the
+ * agent is in reliable mode, then pseudotcp will not be used since pseudotcp
+ * works on top of UDP candidates.
+ * <para>
+ * This option should be set before gathering candidates and should not be
+ * modified afterwards.
+ * </para>
+ * The #NiceAgent:ice-udp property can be set at the same time as the
+ * #NiceAgent:ice-tcp property, but both cannot be unset at the same time.
+ * If #NiceAgent:ice-tcp is set to %FALSE, then this property cannot be set
+ * to %FALSE as well.
+ *
+ * Since: 0.1.8
+ */
+ g_object_class_install_property (gobject_class, PROP_ICE_UDP,
+ g_param_spec_boolean (
+ "ice-udp",
+ "Use ICE-UDP",
+ "Use ICE-UDP specification to generate UDP candidates",
+ TRUE, /* use ice-udp by default */
+ G_PARAM_READWRITE));
+
+ /**
+ * NiceAgent:ice-tcp:
+ *
+ * Whether the agent should use ICE-TCP when gathering candidates.
+ * If the option is disabled, no TCP candidates will be generated. If the
+ * agent is in reliable mode, then pseudotcp will need to be used over UDP
+ * candidates.
+ * <para>
+ * This option should be set before gathering candidates and should not be
+ * modified afterwards.
+ * </para>
+ * The #NiceAgent:ice-tcp property can be set at the same time as the
+ * #NiceAgent:ice-udp property, but both cannot be unset at the same time.
+ * If #NiceAgent:ice-udp is set to %FALSE, then this property cannot be set
+ * to %FALSE as well.
+ * <note>
+ <para>
+ ICE-TCP is only supported for %NICE_COMPATIBILITY_RFC5245,
+ %NICE_COMPATIBILITY_OC2007 and %NICE_COMPATIBILITY_OC2007R2 compatibility
+ modes.
+ </para>
+ * </note>
+ *
+ * Since: 0.1.8
+ */
+ g_object_class_install_property (gobject_class, PROP_ICE_TCP,
+ g_param_spec_boolean (
+ "ice-tcp",
+ "Use ICE-TCP",
+ "Use ICE-TCP specification to generate TCP candidates",
+ TRUE, /* use ice-tcp by default */
+ G_PARAM_READWRITE));
+
+ /**
+ * NiceAgent:bytestream-tcp:
+ *
+ * This property defines whether receive/send over a TCP or pseudo-TCP, in
+ * reliable mode, are considered as packetized or as bytestream.
+ * In unreliable mode, every send/recv is considered as packetized, and
+ * this property is ignored and cannot be set.
+ * <para>
+ * In reliable mode, this property will always return %TRUE in the
+ * %NICE_COMPATIBILITY_GOOGLE compatibility mode.
+ * </para>
+ * If the property is %TRUE, the stream is considered in bytestream mode
+ * and data can be read with any receive size. If the property is %FALSE, then
+ * the stream is considred packetized and each receive will return one packet
+ * of the same size as what was sent from the peer. If in packetized mode,
+ * then doing a receive with a size smaller than the packet, will cause the
+ * remaining bytes in the packet to be dropped, breaking the reliability
+ * of the stream.
+ * <para>
+ * This property is currently read-only, and will become read/write once
+ * bytestream mode will be supported.
+ * </para>
+ *
+ * Since: 0.1.8
+ */
+ g_object_class_install_property (gobject_class, PROP_BYTESTREAM_TCP,
+ g_param_spec_boolean (
+ "bytestream-tcp",
+ "Bytestream TCP",
+ "Use bytestream mode for reliable TCP and Pseudo-TCP connections",
+ FALSE,
+ G_PARAM_READABLE));
+
+ /**
+ * NiceAgent:keepalive-conncheck:
+ *
+ * Use binding requests as keepalives instead of binding
+ * indications. This means that the keepalives may time out which
+ * will change the component state to %NICE_COMPONENT_STATE_FAILED.
+ *
+ * Enabing this is a slight violation of RFC 5245 section 10 which
+ * recommends using Binding Indications for keepalives.
+ *
+ * This is always enabled if the compatibility mode is
+ * %NICE_COMPATIBILITY_GOOGLE.
+ *
+ * Since: 0.1.8
+ */
+ g_object_class_install_property (gobject_class, PROP_KEEPALIVE_CONNCHECK,
+ g_param_spec_boolean (
+ "keepalive-conncheck",
+ "Use conncheck as keepalives",
+ "Use binding requests which require a reply as keepalives instead of "
+ "binding indications which don't.",
+ FALSE,
+ G_PARAM_READWRITE));
+
+ /**
+ * NiceAgent:force-relay
+ *
+ * Force all traffic to go through a relay for added privacy, this
+ * allows hiding the local IP address. When this is enabled, so
+ * local candidates are available before relay servers have been set
+ * with nice_agent_set_relay_info().
+ *
+ * Since: 0.1.14
+ */
+ g_object_class_install_property (gobject_class, PROP_FORCE_RELAY,
+ g_param_spec_boolean (
+ "force-relay",
+ "Force Relay",
+ "Force all traffic to go through a relay for added privacy.",
+ FALSE,
+ G_PARAM_READWRITE));
+
+ /**
+ * NiceAgent:stun-max-retransmissions
+ *
+ * The maximum number of retransmissions of the STUN binding requests
+ * used in the gathering stage, to find our local candidates, and used
+ * in the connection check stage, to test the validity of each
+ * constructed pair. This property is described as 'Rc' in the RFC
+ * 5389, with a default value of 7. The timeout of each STUN request
+ * is doubled for each retransmission, so the choice of this value has
+ * a direct impact on the time needed to move from the CONNECTED state
+ * to the READY state, and on the time needed to complete the GATHERING
+ * state.
+ *
+ * Since: 0.1.15
+ */
+
+ g_object_class_install_property (gobject_class, PROP_STUN_MAX_RETRANSMISSIONS,
+ g_param_spec_uint (
+ "stun-max-retransmissions",
+ "STUN Max Retransmissions",
+ "Maximum number of STUN binding requests retransmissions "
+ "described as 'Rc' in the STUN specification.",
+ 1, 99,
+ STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ /**
+ * NiceAgent:stun-initial-timeout
+ *
+ * The initial timeout (msecs) of the STUN binding requests
+ * used in the gathering stage, to find our local candidates.
+ * This property is described as 'RTO' in the RFC 5389 and RFC 5245.
+ * This timeout is doubled for each retransmission, until
+ * #NiceAgent:stun-max-retransmissions have been done,
+ * with an exception for the last restransmission, where the timeout is
+ * divided by two instead (RFC 5389 indicates that a customisable
+ * multiplier 'Rm' to 'RTO' should be used).
+ *
+ * Since: 0.1.15
+ */
+
+ g_object_class_install_property (gobject_class, PROP_STUN_INITIAL_TIMEOUT,
+ g_param_spec_uint (
+ "stun-initial-timeout",
+ "STUN Initial Timeout",
+ "STUN timeout in msecs of the initial binding requests used in the "
+ "gathering state, described as 'RTO' in the ICE specification.",
+ 20, 9999,
+ STUN_TIMER_DEFAULT_TIMEOUT,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ /**
+ * NiceAgent:stun-reliable-timeout
+ *
+ * The initial timeout of the STUN binding requests used
+ * for a reliable timer.
+ *
+ * Since: 0.1.15
+ */
+
+ g_object_class_install_property (gobject_class, PROP_STUN_RELIABLE_TIMEOUT,
+ g_param_spec_uint (
+ "stun-reliable-timeout",
+ "STUN Reliable Timeout",
+ "STUN timeout in msecs of the initial binding requests used for "
+ "a reliable timer.",
+ 20, 99999,
+ STUN_TIMER_DEFAULT_RELIABLE_TIMEOUT,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ /**
+ * NiceAgent:ice-trickle
+ *
+ * Whether to perform Trickle ICE as per draft-ietf-ice-trickle-ice-21.
+ * When %TRUE, the agent will postpone changing a component state to
+ * %NICE_COMPONENT_STATE_FAILED until nice_agent_peer_candidate_gathering_done()
+ * has been called with the ID of the component's stream.
+ *
+ * Since: 0.1.16
+ */
+ g_object_class_install_property (gobject_class, PROP_ICE_TRICKLE,
+ g_param_spec_boolean (
+ "ice-trickle",
+ "Trickle ICE",
+ "Whether to perform Trickle ICE as per draft-ietf-ice-trickle-ice-21.",
+ FALSE,
+ G_PARAM_READWRITE));
+
+ /* install signals */
+
+ /**
+ * NiceAgent::component-state-changed
+ * @agent: The #NiceAgent object
+ * @stream_id: The ID of the stream
+ * @component_id: The ID of the component
+ * @state: The new #NiceComponentState of the component
+ *
+ * This signal is fired whenever a component’s state changes. There are many
+ * valid state transitions.
+ *
+ * ![State transition diagram](states.png)
+ */
+ signals[SIGNAL_COMPONENT_STATE_CHANGED] =
+ g_signal_new (
+ "component-state-changed",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ G_TYPE_NONE,
+ 3,
+ G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT,
+ G_TYPE_INVALID);
+
+ /**
+ * NiceAgent::candidate-gathering-done:
+ * @agent: The #NiceAgent object
+ * @stream_id: The ID of the stream
+ *
+ * This signal is fired whenever a stream has finished gathering its
+ * candidates after a call to nice_agent_gather_candidates()
+ */
+ signals[SIGNAL_CANDIDATE_GATHERING_DONE] =
+ g_signal_new (
+ "candidate-gathering-done",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_UINT, G_TYPE_INVALID);
+
+ /**
+ * NiceAgent::new-selected-pair
+ * @agent: The #NiceAgent object
+ * @stream_id: The ID of the stream
+ * @component_id: The ID of the component
+ * @lfoundation: The local foundation of the selected candidate pair
+ * @rfoundation: The remote foundation of the selected candidate pair
+ *
+ * This signal is fired once a candidate pair is selected for data
+ * transfer for a stream's component This is emitted along with
+ * #NiceAgent::new-selected-pair-full which has the whole candidate,
+ * the Foundation of a Candidate is not a unique identifier.
+ *
+ * See also: #NiceAgent::new-selected-pair-full
+ * Deprecated: 0.1.8: Use #NiceAgent::new-selected-pair-full
+ */
+ signals[SIGNAL_NEW_SELECTED_PAIR] =
+ g_signal_new (
+ "new-selected-pair",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ G_TYPE_NONE,
+ 4,
+ G_TYPE_UINT, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_INVALID);
+
+ /**
+ * NiceAgent::new-candidate
+ * @agent: The #NiceAgent object
+ * @stream_id: The ID of the stream
+ * @component_id: The ID of the component
+ * @foundation: The foundation of the new candidate
+ *
+ * This signal is fired when the agent discovers a new local candidate.
+ * When this signal is emitted, a matching #NiceAgent::new-candidate-full is
+ * also emitted with the candidate.
+ *
+ * See also: #NiceAgent::candidate-gathering-done,
+ * #NiceAgent::new-candidate-full
+ * Deprecated: 0.1.8: Use #NiceAgent::new-candidate-full
+ */
+ signals[SIGNAL_NEW_CANDIDATE] =
+ g_signal_new (
+ "new-candidate",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ G_TYPE_NONE,
+ 3,
+ G_TYPE_UINT, G_TYPE_UINT, G_TYPE_STRING,
+ G_TYPE_INVALID);
+
+ /**
+ * NiceAgent::new-remote-candidate
+ * @agent: The #NiceAgent object
+ * @stream_id: The ID of the stream
+ * @component_id: The ID of the component
+ * @foundation: The foundation of the new candidate
+ *
+ * This signal is fired when the agent discovers a new remote
+ * candidate. This can happen with peer reflexive candidates. When
+ * this signal is emitted, a matching
+ * #NiceAgent::new-remote-candidate-full is also emitted with the
+ * candidate.
+ *
+ * See also: #NiceAgent::new-remote-candidate-full
+ * Deprecated: 0.1.8: Use #NiceAgent::new-remote-candidate-full
+ */
+ signals[SIGNAL_NEW_REMOTE_CANDIDATE] =
+ g_signal_new (
+ "new-remote-candidate",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ G_TYPE_NONE,
+ 3,
+ G_TYPE_UINT, G_TYPE_UINT, G_TYPE_STRING,
+ G_TYPE_INVALID);
+
+ /**
+ * NiceAgent::initial-binding-request-received
+ * @agent: The #NiceAgent object
+ * @stream_id: The ID of the stream
+ *
+ * This signal is fired when we received our first binding request from
+ * the peer.
+ */
+ signals[SIGNAL_INITIAL_BINDING_REQUEST_RECEIVED] =
+ g_signal_new (
+ "initial-binding-request-received",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_UINT,
+ G_TYPE_INVALID);
+
+ /**
+ * NiceAgent::reliable-transport-writable
+ * @agent: The #NiceAgent object
+ * @stream_id: The ID of the stream
+ * @component_id: The ID of the component
+ *
+ * This signal is fired on the reliable #NiceAgent when the underlying reliable
+ * transport becomes writable.
+ * This signal is only emitted when the nice_agent_send() function returns less
+ * bytes than requested to send (or -1) and once when the connection
+ * is established.
+ *
+ * Since: 0.0.11
+ */
+ signals[SIGNAL_RELIABLE_TRANSPORT_WRITABLE] =
+ g_signal_new (
+ "reliable-transport-writable",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ G_TYPE_NONE,
+ 2,
+ G_TYPE_UINT, G_TYPE_UINT,
+ G_TYPE_INVALID);
+
+ /**
+ * NiceAgent::streams-removed
+ * @agent: The #NiceAgent object
+ * @stream_ids: (array zero-terminated=1) (element-type uint): An array of
+ * unsigned integer stream IDs, ending with a 0 ID
+ *
+ * This signal is fired whenever one or more streams are removed from the
+ * @agent.
+ *
+ * Since: 0.1.5
+ */
+ signals[SIGNAL_STREAMS_REMOVED] =
+ g_signal_new (
+ "streams-removed",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE,
+ 1,
+ NICE_TYPE_AGENT_STREAM_IDS,
+ G_TYPE_INVALID);
+
+
+ /**
+ * NiceAgent::new-selected-pair-full
+ * @agent: The #NiceAgent object
+ * @stream_id: The ID of the stream
+ * @component_id: The ID of the component
+ * @lcandidate: The local #NiceCandidate of the selected candidate pair
+ * @rcandidate: The remote #NiceCandidate of the selected candidate pair
+ *
+ * This signal is fired once a candidate pair is selected for data
+ * transfer for a stream's component. This is emitted along with
+ * #NiceAgent::new-selected-pair.
+ *
+ * See also: #NiceAgent::new-selected-pair
+ * Since: 0.1.8
+ */
+ signals[SIGNAL_NEW_SELECTED_PAIR_FULL] =
+ g_signal_new (
+ "new-selected-pair-full",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ G_TYPE_NONE,
+ 4, G_TYPE_UINT, G_TYPE_UINT, NICE_TYPE_CANDIDATE, NICE_TYPE_CANDIDATE,
+ G_TYPE_INVALID);
+
+ /**
+ * NiceAgent::new-candidate-full
+ * @agent: The #NiceAgent object
+ * @candidate: The new #NiceCandidate
+ *
+ * This signal is fired when the agent discovers a new local candidate.
+ * When this signal is emitted, a matching #NiceAgent::new-candidate is
+ * also emitted with the candidate's foundation.
+ *
+ * See also: #NiceAgent::candidate-gathering-done,
+ * #NiceAgent::new-candidate
+ * Since: 0.1.8
+ */
+ signals[SIGNAL_NEW_CANDIDATE_FULL] =
+ g_signal_new (
+ "new-candidate-full",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ G_TYPE_NONE,
+ 1,
+ NICE_TYPE_CANDIDATE,
+ G_TYPE_INVALID);
+
+ /**
+ * NiceAgent::new-remote-candidate-full
+ * @agent: The #NiceAgent object
+ * @candidate: The new #NiceCandidate
+ *
+ * This signal is fired when the agent discovers a new remote candidate.
+ * This can happen with peer reflexive candidates.
+ * When this signal is emitted, a matching #NiceAgent::new-remote-candidate is
+ * also emitted with the candidate's foundation.
+ *
+ * See also: #NiceAgent::new-remote-candidate
+ * Since: 0.1.8
+ */
+ signals[SIGNAL_NEW_REMOTE_CANDIDATE_FULL] =
+ g_signal_new (
+ "new-remote-candidate-full",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ G_TYPE_NONE,
+ 1,
+ NICE_TYPE_CANDIDATE,
+ G_TYPE_INVALID);
+
+ /* Init debug options depending on env variables */
+ nice_debug_init ();
+}
+
+static void priv_generate_tie_breaker (NiceAgent *agent)
+{
+ nice_rng_generate_bytes (agent->rng, 8, (gchar*)&agent->tie_breaker);
+}
+
+static void
+priv_update_controlling_mode (NiceAgent *agent, gboolean value)
+{
+ gboolean update_controlling_mode;
+ GSList *i, *j;
+
+ agent->saved_controlling_mode = value;
+ /* It is safe to update the agent controlling mode when all
+ * components are still in state disconnected. When we leave
+ * this state, the role must stay under the control of the
+ * conncheck algorithm exclusively, until the conncheck is
+ * eventually restarted. See RFC5245, sect 5.2. Determining Role
+ */
+ if (agent->controlling_mode != agent->saved_controlling_mode) {
+ update_controlling_mode = TRUE;
+ for (i = agent->streams;
+ i && update_controlling_mode; i = i->next) {
+ NiceStream *stream = i->data;
+ for (j = stream->components;
+ j && update_controlling_mode; j = j->next) {
+ NiceComponent *component = j->data;
+ if (component->state > NICE_COMPONENT_STATE_DISCONNECTED)
+ update_controlling_mode = FALSE;
+ }
+ }
+ if (update_controlling_mode) {
+ agent->controlling_mode = agent->saved_controlling_mode;
+ nice_debug ("Agent %p : Property set, changing role to \"%s\".",
+ agent, agent->controlling_mode ? "controlling" : "controlled");
+ } else {
+ nice_debug ("Agent %p : Property set, role switch requested "
+ "but conncheck already started.", agent);
+ nice_debug ("Agent %p : Property set, staying with role \"%s\" "
+ "until restart.", agent,
+ agent->controlling_mode ? "controlling" : "controlled");
+ }
+ } else
+ nice_debug ("Agent %p : Property set, role is already \"%s\".", agent,
+ agent->controlling_mode ? "controlling" : "controlled");
+}
+
+static void
+nice_agent_init (NiceAgent *agent)
+{
+ agent->next_candidate_id = 1;
+ agent->next_stream_id = 1;
+
+ /* set defaults; not construct params, so set here */
+ agent->stun_server_port = DEFAULT_STUN_PORT;
+ agent->controlling_mode = TRUE;
+ agent->saved_controlling_mode = TRUE;
+ agent->max_conn_checks = NICE_AGENT_MAX_CONNECTIVITY_CHECKS_DEFAULT;
+ agent->nomination_mode = NICE_NOMINATION_MODE_AGGRESSIVE;
+ agent->support_renomination = FALSE;
+
+ agent->discovery_list = NULL;
+ agent->discovery_unsched_items = 0;
+ agent->discovery_timer_source = NULL;
+ agent->conncheck_timer_source = NULL;
+ agent->keepalive_timer_source = NULL;
+ agent->refresh_list = NULL;
+ agent->media_after_tick = FALSE;
+ agent->software_attribute = NULL;
+
+ agent->compatibility = NICE_COMPATIBILITY_RFC5245;
+ agent->reliable = FALSE;
+ agent->use_ice_udp = TRUE;
+ agent->use_ice_tcp = TRUE;
+
+ agent->rng = nice_rng_new ();
+ priv_generate_tie_breaker (agent);
+
+ g_queue_init (&agent->pending_signals);
+
+ g_mutex_init (&agent->agent_mutex);
+}
+
+
+NICEAPI_EXPORT NiceAgent *
+nice_agent_new (GMainContext *ctx, NiceCompatibility compat)
+{
+ NiceAgent *agent = g_object_new (NICE_TYPE_AGENT,
+ "compatibility", compat,
+ "main-context", ctx,
+ "reliable", FALSE,
+ NULL);
+
+ return agent;
+}
+
+
+NICEAPI_EXPORT NiceAgent *
+nice_agent_new_reliable (GMainContext *ctx, NiceCompatibility compat)
+{
+ NiceAgent *agent = g_object_new (NICE_TYPE_AGENT,
+ "compatibility", compat,
+ "main-context", ctx,
+ "reliable", TRUE,
+ NULL);
+
+ return agent;
+}
+
+
+NICEAPI_EXPORT NiceAgent *
+nice_agent_new_full (GMainContext *ctx,
+ NiceCompatibility compat,
+ NiceAgentOption flags)
+{
+ NiceAgent *agent = g_object_new (NICE_TYPE_AGENT,
+ "compatibility", compat,
+ "main-context", ctx,
+ "reliable", (flags & NICE_AGENT_OPTION_RELIABLE) ? TRUE : FALSE,
+ "nomination-mode", (flags & NICE_AGENT_OPTION_REGULAR_NOMINATION) ?
+ NICE_NOMINATION_MODE_REGULAR : NICE_NOMINATION_MODE_AGGRESSIVE,
+ "full-mode", (flags & NICE_AGENT_OPTION_LITE_MODE) ? FALSE : TRUE,
+ "ice-trickle", (flags & NICE_AGENT_OPTION_ICE_TRICKLE) ? TRUE : FALSE,
+ "support-renomination", (flags & NICE_AGENT_OPTION_SUPPORT_RENOMINATION) ? TRUE : FALSE,
+ NULL);
+
+ return agent;
+}
+
+
+static void
+nice_agent_get_property (
+ GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ NiceAgent *agent = NICE_AGENT (object);
+
+ agent_lock (agent);
+
+ switch (property_id)
+ {
+ case PROP_MAIN_CONTEXT:
+ g_value_set_pointer (value, agent->main_context);
+ break;
+
+ case PROP_COMPATIBILITY:
+ g_value_set_uint (value, agent->compatibility);
+ break;
+
+ case PROP_STUN_SERVER:
+ g_value_set_string (value, agent->stun_server_ip);
+ break;
+
+ case PROP_STUN_SERVER_PORT:
+ g_value_set_uint (value, agent->stun_server_port);
+ break;
+
+ case PROP_CONTROLLING_MODE:
+ g_value_set_boolean (value, agent->saved_controlling_mode);
+ break;
+
+ case PROP_FULL_MODE:
+ g_value_set_boolean (value, agent->full_mode);
+ break;
+
+ case PROP_STUN_PACING_TIMER:
+ g_value_set_uint (value, agent->timer_ta);
+ break;
+
+ case PROP_MAX_CONNECTIVITY_CHECKS:
+ g_value_set_uint (value, agent->max_conn_checks);
+ /* XXX: should we prune the list of already existing checks? */
+ break;
+
+ case PROP_NOMINATION_MODE:
+ g_value_set_enum (value, agent->nomination_mode);
+ break;
+
+ case PROP_SUPPORT_RENOMINATION:
+ g_value_set_boolean (value, agent->support_renomination);
+ break;
+
+ case PROP_PROXY_IP:
+ g_value_set_string (value, agent->proxy_ip);
+ break;
+
+ case PROP_PROXY_PORT:
+ g_value_set_uint (value, agent->proxy_port);
+ break;
+
+ case PROP_PROXY_TYPE:
+ g_value_set_uint (value, agent->proxy_type);
+ break;
+
+ case PROP_PROXY_USERNAME:
+ g_value_set_string (value, agent->proxy_username);
+ break;
+
+ case PROP_PROXY_PASSWORD:
+ g_value_set_string (value, agent->proxy_password);
+ break;
+
+ case PROP_UPNP:
+#ifdef HAVE_GUPNP
+ g_value_set_boolean (value, agent->upnp_enabled);
+#else
+ g_value_set_boolean (value, FALSE);
+#endif
+ break;
+
+ case PROP_UPNP_TIMEOUT:
+#ifdef HAVE_GUPNP
+ g_value_set_uint (value, agent->upnp_timeout);
+#else
+ g_value_set_uint (value, DEFAULT_UPNP_TIMEOUT);
+#endif
+ break;
+
+ case PROP_RELIABLE:
+ g_value_set_boolean (value, agent->reliable);
+ break;
+
+ case PROP_ICE_UDP:
+ g_value_set_boolean (value, agent->use_ice_udp);
+ break;
+
+ case PROP_ICE_TCP:
+ g_value_set_boolean (value, agent->use_ice_tcp);
+ break;
+
+ case PROP_BYTESTREAM_TCP:
+ if (agent->reliable) {
+ if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE)
+ g_value_set_boolean (value, TRUE);
+ else
+ g_value_set_boolean (value, FALSE);
+ } else {
+ g_value_set_boolean (value, FALSE);
+ }
+ break;
+
+ case PROP_KEEPALIVE_CONNCHECK:
+ if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE)
+ g_value_set_boolean (value, TRUE);
+ else
+ g_value_set_boolean (value, agent->keepalive_conncheck);
+ break;
+
+ case PROP_FORCE_RELAY:
+ g_value_set_boolean (value, agent->force_relay);
+ break;
+
+ case PROP_STUN_MAX_RETRANSMISSIONS:
+ g_value_set_uint (value, agent->stun_max_retransmissions);
+ break;
+
+ case PROP_STUN_INITIAL_TIMEOUT:
+ g_value_set_uint (value, agent->stun_initial_timeout);
+ break;
+
+ case PROP_STUN_RELIABLE_TIMEOUT:
+ g_value_set_uint (value, agent->stun_reliable_timeout);
+ break;
+
+ case PROP_ICE_TRICKLE:
+ g_value_set_boolean (value, agent->use_ice_trickle);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+
+ agent_unlock_and_emit(agent);
+}
+
+void
+nice_agent_init_stun_agent (NiceAgent *agent, StunAgent *stun_agent)
+{
+ if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE) {
+ stun_agent_init (stun_agent, STUN_ALL_KNOWN_ATTRIBUTES,
+ STUN_COMPATIBILITY_RFC3489,
+ STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS |
+ STUN_AGENT_USAGE_IGNORE_CREDENTIALS);
+ } else if (agent->compatibility == NICE_COMPATIBILITY_MSN) {
+ stun_agent_init (stun_agent, STUN_ALL_KNOWN_ATTRIBUTES,
+ STUN_COMPATIBILITY_RFC3489,
+ STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS |
+ STUN_AGENT_USAGE_FORCE_VALIDATER);
+ } else if (agent->compatibility == NICE_COMPATIBILITY_WLM2009) {
+ stun_agent_init (stun_agent, STUN_ALL_KNOWN_ATTRIBUTES,
+ STUN_COMPATIBILITY_MSICE2,
+ STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS |
+ STUN_AGENT_USAGE_USE_FINGERPRINT);
+ } else if (agent->compatibility == NICE_COMPATIBILITY_OC2007) {
+ stun_agent_init (stun_agent, STUN_ALL_KNOWN_ATTRIBUTES,
+ STUN_COMPATIBILITY_RFC3489,
+ STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS |
+ STUN_AGENT_USAGE_FORCE_VALIDATER |
+ STUN_AGENT_USAGE_NO_ALIGNED_ATTRIBUTES);
+ } else if (agent->compatibility == NICE_COMPATIBILITY_OC2007R2) {
+ stun_agent_init (stun_agent, STUN_ALL_KNOWN_ATTRIBUTES,
+ STUN_COMPATIBILITY_MSICE2,
+ STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS |
+ STUN_AGENT_USAGE_USE_FINGERPRINT |
+ STUN_AGENT_USAGE_NO_ALIGNED_ATTRIBUTES);
+ } else {
+ stun_agent_init (stun_agent, STUN_ALL_KNOWN_ATTRIBUTES,
+ STUN_COMPATIBILITY_RFC5389,
+ STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS |
+ STUN_AGENT_USAGE_USE_FINGERPRINT);
+ }
+ stun_agent_set_software (stun_agent, agent->software_attribute);
+}
+
+static void
+nice_agent_reset_all_stun_agents (NiceAgent *agent, gboolean only_software)
+{
+ GSList *stream_item, *component_item;
+
+ for (stream_item = agent->streams; stream_item;
+ stream_item = stream_item->next) {
+ NiceStream *stream = stream_item->data;
+
+ for (component_item = stream->components; component_item;
+ component_item = component_item->next) {
+ NiceComponent *component = component_item->data;
+
+ if (only_software)
+ stun_agent_set_software (&component->stun_agent,
+ agent->software_attribute);
+ else
+ nice_agent_init_stun_agent(agent, &component->stun_agent);
+ }
+ }
+}
+
+static void
+nice_agent_set_property (
+ GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ NiceAgent *agent = NICE_AGENT (object);
+
+ agent_lock (agent);
+
+ switch (property_id)
+ {
+ case PROP_MAIN_CONTEXT:
+ agent->main_context = g_value_get_pointer (value);
+ if (agent->main_context != NULL)
+ g_main_context_ref (agent->main_context);
+ break;
+
+ case PROP_COMPATIBILITY:
+ agent->compatibility = g_value_get_uint (value);
+ if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE ||
+ agent->compatibility == NICE_COMPATIBILITY_MSN ||
+ agent->compatibility == NICE_COMPATIBILITY_WLM2009)
+ agent->use_ice_tcp = FALSE;
+
+ nice_agent_reset_all_stun_agents (agent, FALSE);
+ break;
+
+ case PROP_STUN_SERVER:
+ g_free (agent->stun_server_ip);
+ agent->stun_server_ip = g_value_dup_string (value);
+ break;
+
+ case PROP_STUN_SERVER_PORT:
+ agent->stun_server_port = g_value_get_uint (value);
+ break;
+
+ case PROP_CONTROLLING_MODE:
+ priv_update_controlling_mode (agent, g_value_get_boolean (value));
+ break;
+
+ case PROP_FULL_MODE:
+ agent->full_mode = g_value_get_boolean (value);
+ break;
+
+ case PROP_STUN_PACING_TIMER:
+ agent->timer_ta = g_value_get_uint (value);
+ break;
+
+ case PROP_MAX_CONNECTIVITY_CHECKS:
+ agent->max_conn_checks = g_value_get_uint (value);
+ break;
+
+ case PROP_NOMINATION_MODE:
+ agent->nomination_mode = g_value_get_enum (value);
+ break;
+
+ case PROP_SUPPORT_RENOMINATION:
+ agent->support_renomination = g_value_get_boolean (value);
+ break;
+
+ case PROP_PROXY_IP:
+ g_free (agent->proxy_ip);
+ agent->proxy_ip = g_value_dup_string (value);
+ break;
+
+ case PROP_PROXY_PORT:
+ agent->proxy_port = g_value_get_uint (value);
+ break;
+
+ case PROP_PROXY_TYPE:
+ agent->proxy_type = g_value_get_uint (value);
+ break;
+
+ case PROP_PROXY_USERNAME:
+ g_free (agent->proxy_username);
+ agent->proxy_username = g_value_dup_string (value);
+ break;
+
+ case PROP_PROXY_PASSWORD:
+ g_free (agent->proxy_password);
+ agent->proxy_password = g_value_dup_string (value);
+ break;
+
+ case PROP_UPNP_TIMEOUT:
+#ifdef HAVE_GUPNP
+ agent->upnp_timeout = g_value_get_uint (value);
+#endif
+ break;
+
+ case PROP_UPNP:
+#ifdef HAVE_GUPNP
+ agent->upnp_enabled = g_value_get_boolean (value);
+#endif
+ break;
+
+ case PROP_RELIABLE:
+ agent->reliable = g_value_get_boolean (value);
+ break;
+
+ /* Don't allow ice-udp and ice-tcp to be disabled at the same time */
+ case PROP_ICE_UDP:
+ if (agent->use_ice_tcp == TRUE || g_value_get_boolean (value) == TRUE)
+ agent->use_ice_udp = g_value_get_boolean (value);
+ break;
+
+ case PROP_ICE_TCP:
+ if ((agent->compatibility == NICE_COMPATIBILITY_RFC5245 ||
+ agent->compatibility == NICE_COMPATIBILITY_OC2007 ||
+ agent->compatibility == NICE_COMPATIBILITY_OC2007R2) &&
+ (agent->use_ice_udp == TRUE || g_value_get_boolean (value) == TRUE))
+ agent->use_ice_tcp = g_value_get_boolean (value);
+ break;
+
+ case PROP_BYTESTREAM_TCP:
+ /* TODO: support bytestream mode and set property to writable */
+ break;
+
+ case PROP_KEEPALIVE_CONNCHECK:
+ agent->keepalive_conncheck = g_value_get_boolean (value);
+ break;
+
+ case PROP_FORCE_RELAY:
+ agent->force_relay = g_value_get_boolean (value);
+ break;
+
+ case PROP_STUN_MAX_RETRANSMISSIONS:
+ agent->stun_max_retransmissions = g_value_get_uint (value);
+ break;
+
+ case PROP_STUN_INITIAL_TIMEOUT:
+ agent->stun_initial_timeout = g_value_get_uint (value);
+ break;
+
+ case PROP_STUN_RELIABLE_TIMEOUT:
+ agent->stun_reliable_timeout = g_value_get_uint (value);
+ break;
+
+ case PROP_ICE_TRICKLE:
+ agent->use_ice_trickle = g_value_get_boolean (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ }
+
+ agent_unlock_and_emit (agent);
+
+}
+
+
+static void
+ agent_signal_socket_writable (NiceAgent *agent, NiceComponent *component)
+{
+ g_cancellable_cancel (component->tcp_writable_cancellable);
+
+ agent_queue_signal (agent, signals[SIGNAL_RELIABLE_TRANSPORT_WRITABLE],
+ component->stream_id, component->id);
+}
+
+static void
+pseudo_tcp_socket_create (NiceAgent *agent, NiceStream *stream, NiceComponent *component)
+{
+ PseudoTcpCallbacks tcp_callbacks = {component,
+ pseudo_tcp_socket_opened,
+ pseudo_tcp_socket_readable,
+ pseudo_tcp_socket_writable,
+ pseudo_tcp_socket_closed,
+ pseudo_tcp_socket_write_packet};
+ component->tcp = pseudo_tcp_socket_new (0, &tcp_callbacks);
+ component->tcp_writable_cancellable = g_cancellable_new ();
+ nice_debug ("Agent %p: Create Pseudo Tcp Socket for component %d",
+ agent, component->id);
+}
+
+static void priv_pseudo_tcp_error (NiceAgent *agent, NiceComponent *component)
+{
+ if (component->tcp_writable_cancellable) {
+ g_cancellable_cancel (component->tcp_writable_cancellable);
+ g_clear_object (&component->tcp_writable_cancellable);
+ }
+
+ if (component->tcp) {
+ agent_signal_component_state_change (agent, component->stream_id,
+ component->id, NICE_COMPONENT_STATE_FAILED);
+ nice_component_detach_all_sockets (component);
+ pseudo_tcp_socket_close (component->tcp, TRUE);
+ }
+
+ if (component->tcp_clock) {
+ g_source_destroy (component->tcp_clock);
+ g_source_unref (component->tcp_clock);
+ component->tcp_clock = NULL;
+ }
+}
+
+static void
+pseudo_tcp_socket_opened (PseudoTcpSocket *sock, gpointer user_data)
+{
+ NiceComponent *component = user_data;
+ NiceAgent *agent;
+
+ agent = g_weak_ref_get (&component->agent_ref);
+ if (agent == NULL)
+ return;
+
+ nice_debug ("Agent %p: s%d:%d pseudo Tcp socket Opened", agent,
+ component->stream_id, component->id);
+
+ agent_signal_socket_writable (agent, component);
+
+ g_object_unref (agent);
+}
+
+/* Will attempt to queue all @n_messages into the pseudo-TCP transmission
+ * buffer. This is always used in reliable mode, so essentially treats @messages
+ * as a massive flat array of buffers.
+ *
+ * Returns the number of messages successfully sent on success (which may be
+ * zero if sending the first buffer of the message would have blocked), or
+ * a negative number on error. If "allow_partial" is TRUE, then it returns
+ * the number of bytes sent
+ */
+static gint
+pseudo_tcp_socket_send_messages (PseudoTcpSocket *self,
+ const NiceOutputMessage *messages, guint n_messages, gboolean allow_partial,
+ GError **error)
+{
+ guint i;
+ gint bytes_sent = 0;
+
+ for (i = 0; i < n_messages; i++) {
+ const NiceOutputMessage *message = &messages[i];
+ guint j;
+
+ /* If allow_partial is FALSE and there’s not enough space for the
+ * entire message, bail now before queuing anything. This doesn’t
+ * gel with the fact this function is only used in reliable mode,
+ * and there is no concept of a ‘message’, but is necessary
+ * because the calling API has no way of returning to the client
+ * and indicating that a message was partially sent. */
+ if (!allow_partial &&
+ output_message_get_size (message) >
+ pseudo_tcp_socket_get_available_send_space (self)) {
+ return i;
+ }
+
+ for (j = 0;
+ (message->n_buffers >= 0 && j < (guint) message->n_buffers) ||
+ (message->n_buffers < 0 && message->buffers[j].buffer != NULL);
+ j++) {
+ const GOutputVector *buffer = &message->buffers[j];
+ gssize ret;
+
+ /* Send on the pseudo-TCP socket. */
+ ret = pseudo_tcp_socket_send (self, buffer->buffer, buffer->size);
+
+ /* In case of -1, the error is either EWOULDBLOCK or ENOTCONN, which both
+ * need the user to wait for the reliable-transport-writable signal */
+ if (ret < 0) {
+ if (pseudo_tcp_socket_get_error (self) == EWOULDBLOCK)
+ goto out;
+
+ if (pseudo_tcp_socket_get_error (self) == ENOTCONN ||
+ pseudo_tcp_socket_get_error (self) == EPIPE)
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK,
+ "TCP connection is not yet established.");
+ else
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Error writing data to pseudo-TCP socket.");
+ return -1;
+ } else {
+ bytes_sent += ret;
+ }
+ }
+ }
+
+ out:
+
+ return allow_partial ? bytes_sent : (gint) i;
+}
+
+/* Will fill up @messages from the first free byte onwards (as determined using
+ * @iter). This is always used in reliable mode, so it essentially treats
+ * @messages as a massive flat array of buffers.
+ *
+ * Updates @iter in place. @iter and @messages are left in invalid states if
+ * an error is returned.
+ *
+ * Returns the number of valid messages in @messages on success (which may be
+ * zero if no data is pending and the peer has disconnected), or a negative
+ * number on error (including if the request would have blocked returning no
+ * messages). */
+static gint
+pseudo_tcp_socket_recv_messages (PseudoTcpSocket *self,
+ NiceInputMessage *messages, guint n_messages, NiceInputMessageIter *iter,
+ GError **error)
+{
+ for (; iter->message < n_messages; iter->message++) {
+ NiceInputMessage *message = &messages[iter->message];
+
+ if (iter->buffer == 0 && iter->offset == 0) {
+ message->length = 0;
+ }
+
+ for (;
+ (message->n_buffers >= 0 && iter->buffer < (guint) message->n_buffers) ||
+ (message->n_buffers < 0 && message->buffers[iter->buffer].buffer != NULL);
+ iter->buffer++) {
+ GInputVector *buffer = &message->buffers[iter->buffer];
+
+ do {
+ gssize len;
+
+ len = pseudo_tcp_socket_recv (self,
+ (gchar *) buffer->buffer + iter->offset,
+ buffer->size - iter->offset);
+
+ nice_debug_verbose ("%s: Received %" G_GSSIZE_FORMAT " bytes into "
+ "buffer %p (offset %" G_GSIZE_FORMAT ", length %" G_GSIZE_FORMAT
+ ").", G_STRFUNC, len, buffer->buffer, iter->offset, buffer->size);
+
+ if (len == 0) {
+ /* Reached EOS. */
+ goto done;
+ } else if (len < 0 &&
+ pseudo_tcp_socket_get_error (self) == EWOULDBLOCK) {
+ /* EWOULDBLOCK. If we’ve already received something, return that;
+ * otherwise, error. */
+ if (nice_input_message_iter_get_n_valid_messages (iter) > 0) {
+ goto done;
+ }
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK,
+ "Error reading data from pseudo-TCP socket: would block.");
+ return len;
+ } else if (len < 0 && pseudo_tcp_socket_get_error (self) == ENOTCONN) {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK,
+ "Error reading data from pseudo-TCP socket: not connected.");
+ return len;
+ } else if (len < 0) {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Error reading data from pseudo-TCP socket.");
+ return len;
+ } else {
+ /* Got some data! */
+ message->length += len;
+ iter->offset += len;
+ }
+ } while (iter->offset < buffer->size);
+
+ iter->offset = 0;
+ }
+
+ iter->buffer = 0;
+ }
+
+done:
+ return nice_input_message_iter_get_n_valid_messages (iter);
+}
+
+/* This is called with the agent lock held. */
+static void
+pseudo_tcp_socket_readable (PseudoTcpSocket *sock, gpointer user_data)
+{
+ NiceComponent *component = user_data;
+ NiceAgent *agent;
+ gboolean has_io_callback;
+ NiceStream *stream = NULL;
+ guint stream_id = component->stream_id;
+ guint component_id = component->id;
+
+ agent = g_weak_ref_get (&component->agent_ref);
+ if (agent == NULL)
+ return;
+
+ if (!agent_find_component (agent, stream_id, component_id,
+ &stream, &component)) {
+ goto out;
+ }
+
+ nice_debug_verbose ("Agent %p: s%d:%d pseudo Tcp socket readable", agent,
+ stream_id, component->id);
+
+ component->tcp_readable = TRUE;
+
+ has_io_callback = nice_component_has_io_callback (component);
+
+ /* Only dequeue pseudo-TCP data if we can reliably inform the client. The
+ * agent lock is held here, so has_io_callback can only change during
+ * nice_component_emit_io_callback(), after which it’s re-queried. This ensures
+ * no data loss of packets already received and dequeued. */
+ if (has_io_callback) {
+ do {
+ guint8 buf[MAX_BUFFER_SIZE];
+ gssize len;
+
+ /* FIXME: Why copy into a temporary buffer here? Why can’t the I/O
+ * callbacks be emitted directly from the pseudo-TCP receive buffer? */
+ len = pseudo_tcp_socket_recv (sock, (gchar *) buf, sizeof(buf));
+
+ nice_debug ("%s: I/O callback case: Received %" G_GSSIZE_FORMAT " bytes",
+ G_STRFUNC, len);
+
+ if (len == 0) {
+ /* Reached EOS. */
+ component->tcp_readable = FALSE;
+ pseudo_tcp_socket_close (component->tcp, FALSE);
+ break;
+ } else if (len < 0) {
+ /* Handle errors. */
+ if (pseudo_tcp_socket_get_error (sock) != EWOULDBLOCK) {
+ nice_debug ("%s: calling priv_pseudo_tcp_error()", G_STRFUNC);
+ priv_pseudo_tcp_error (agent, component);
+ }
+
+ if (component->recv_buf_error != NULL) {
+ GIOErrorEnum error_code;
+
+ if (pseudo_tcp_socket_get_error (sock) == ENOTCONN)
+ error_code = G_IO_ERROR_BROKEN_PIPE;
+ else if (pseudo_tcp_socket_get_error (sock) == EWOULDBLOCK)
+ error_code = G_IO_ERROR_WOULD_BLOCK;
+ else
+ error_code = G_IO_ERROR_FAILED;
+
+ g_set_error (component->recv_buf_error, G_IO_ERROR, error_code,
+ "Error reading data from pseudo-TCP socket.");
+ }
+
+ break;
+ }
+
+ nice_component_emit_io_callback (agent, component, buf, len);
+
+ if (!agent_find_component (agent, stream_id, component_id,
+ &stream, &component)) {
+ nice_debug ("Stream or Component disappeared during the callback");
+ goto out;
+ }
+ if (pseudo_tcp_socket_is_closed (component->tcp)) {
+ nice_debug ("PseudoTCP socket got destroyed in readable callback!");
+ goto out;
+ }
+
+ has_io_callback = nice_component_has_io_callback (component);
+ } while (has_io_callback);
+ } else if (component->recv_messages != NULL) {
+ gint n_valid_messages;
+ GError *child_error = NULL;
+
+ /* Fill up every buffer in every message until the connection closes or an
+ * error occurs. Copy the data directly into the client’s receive message
+ * array without making any callbacks. Update component->recv_messages_iter
+ * as we go. */
+ n_valid_messages = pseudo_tcp_socket_recv_messages (sock,
+ component->recv_messages, component->n_recv_messages,
+ &component->recv_messages_iter, &child_error);
+
+ nice_debug_verbose ("%s: Client buffers case: Received %d valid messages:",
+ G_STRFUNC, n_valid_messages);
+ nice_debug_input_message_composition (component->recv_messages,
+ component->n_recv_messages);
+
+ if (n_valid_messages < 0) {
+ g_propagate_error (component->recv_buf_error, child_error);
+ } else {
+ g_clear_error (&child_error);
+ }
+
+ if (n_valid_messages < 0 &&
+ g_error_matches (child_error, G_IO_ERROR,
+ G_IO_ERROR_WOULD_BLOCK)) {
+ component->tcp_readable = FALSE;
+ } else if (n_valid_messages < 0) {
+ nice_debug ("%s: calling priv_pseudo_tcp_error()", G_STRFUNC);
+ priv_pseudo_tcp_error (agent, component);
+ } else if (n_valid_messages == 0) {
+ /* Reached EOS. */
+ component->tcp_readable = FALSE;
+ pseudo_tcp_socket_close (component->tcp, FALSE);
+ }
+ } else {
+ nice_debug ("%s: no data read", G_STRFUNC);
+ }
+
+ if (stream && component)
+ adjust_tcp_clock (agent, stream, component);
+
+out:
+
+ g_object_unref (agent);
+}
+
+static void
+pseudo_tcp_socket_writable (PseudoTcpSocket *sock, gpointer user_data)
+{
+ NiceComponent *component = user_data;
+ NiceAgent *agent;
+
+ agent = g_weak_ref_get (&component->agent_ref);
+ if (agent == NULL)
+ return;
+
+ nice_debug_verbose ("Agent %p: s%d:%d pseudo Tcp socket writable", agent,
+ component->stream_id, component->id);
+
+ agent_signal_socket_writable (agent, component);
+
+ g_object_unref (agent);
+}
+
+static void
+pseudo_tcp_socket_closed (PseudoTcpSocket *sock, guint32 err,
+ gpointer user_data)
+{
+ NiceComponent *component = user_data;
+ NiceAgent *agent;
+
+ agent = g_weak_ref_get (&component->agent_ref);
+ if (agent == NULL)
+ return;
+
+ nice_debug ("Agent %p: s%d:%d pseudo Tcp socket closed. "
+ "Calling priv_pseudo_tcp_error().", agent, component->stream_id,
+ component->id);
+ priv_pseudo_tcp_error (agent, component);
+
+ g_object_unref (agent);
+}
+
+
+static PseudoTcpWriteResult
+pseudo_tcp_socket_write_packet (PseudoTcpSocket *psocket,
+ const gchar *buffer, guint32 len, gpointer user_data)
+{
+ NiceComponent *component = user_data;
+ NiceAgent *agent;
+
+ agent = g_weak_ref_get (&component->agent_ref);
+ if (agent == NULL)
+ return WR_FAIL;
+
+ if (component->selected_pair.local != NULL) {
+ NiceSocket *sock;
+ NiceAddress *addr;
+
+ sock = component->selected_pair.local->sockptr;
+ addr = &component->selected_pair.remote->addr;
+
+ if (nice_debug_is_enabled ()) {
+ gchar tmpbuf[INET6_ADDRSTRLEN];
+ nice_address_to_string (addr, tmpbuf);
+
+ nice_debug_verbose (
+ "Agent %p : s%d:%d: sending %d bytes on socket %p (FD %d) to [%s]:%d",
+ agent, component->stream_id, component->id, len,
+ sock->fileno, g_socket_get_fd (sock->fileno), tmpbuf,
+ nice_address_get_port (addr));
+ }
+
+ /* Send the segment. nice_socket_send() returns 0 on EWOULDBLOCK; in that
+ * case the segment is not sent on the wire, but we return WR_SUCCESS
+ * anyway. This effectively drops the segment. The pseudo-TCP state machine
+ * will eventually pick up this loss and go into recovery mode, reducing
+ * its transmission rate and, hopefully, the usage of system resources
+ * which caused the EWOULDBLOCK in the first place. */
+ if (nice_socket_send (sock, addr, len, buffer) >= 0) {
+ g_object_unref (agent);
+ return WR_SUCCESS;
+ }
+ } else {
+ nice_debug ("%s: WARNING: Failed to send pseudo-TCP packet from agent %p "
+ "as no pair has been selected yet.", G_STRFUNC, agent);
+ }
+
+ g_object_unref (agent);
+
+ return WR_FAIL;
+}
+
+
+static gboolean
+notify_pseudo_tcp_socket_clock_agent_locked (NiceAgent *agent,
+ gpointer user_data)
+{
+ NiceComponent *component = user_data;
+ NiceStream *stream;
+
+ stream = agent_find_stream (agent, component->stream_id);
+ if (!stream)
+ return G_SOURCE_REMOVE;
+
+ pseudo_tcp_socket_notify_clock (component->tcp);
+ adjust_tcp_clock (agent, stream, component);
+
+ return G_SOURCE_CONTINUE;
+}
+
+static void
+adjust_tcp_clock (NiceAgent *agent, NiceStream *stream, NiceComponent *component)
+{
+ if (!pseudo_tcp_socket_is_closed (component->tcp)) {
+ guint64 timeout = component->last_clock_timeout;
+
+ if (pseudo_tcp_socket_get_next_clock (component->tcp, &timeout)) {
+ if (timeout != component->last_clock_timeout) {
+ component->last_clock_timeout = timeout;
+ if (component->tcp_clock) {
+ g_source_set_ready_time (component->tcp_clock, timeout * 1000);
+ }
+ if (!component->tcp_clock) {
+ long interval = timeout - (guint32) (g_get_monotonic_time () / 1000);
+
+ /* Prevent integer overflows */
+ if (interval < 0 || interval > G_MAXINT)
+ interval = G_MAXINT;
+ agent_timeout_add_with_context (agent, &component->tcp_clock,
+ "Pseudo-TCP clock", interval,
+ notify_pseudo_tcp_socket_clock_agent_locked, component);
+ }
+ }
+ } else {
+ nice_debug ("Agent %p: component %d pseudo-TCP socket should be "
+ "destroyed. Calling priv_pseudo_tcp_error().",
+ agent, component->id);
+ priv_pseudo_tcp_error (agent, component);
+ }
+ }
+}
+
+void
+_tcp_sock_is_writable (NiceSocket *sock, gpointer user_data)
+{
+ NiceComponent *component = user_data;
+ NiceAgent *agent;
+
+ agent = g_weak_ref_get (&component->agent_ref);
+ if (agent == NULL)
+ return;
+
+ agent_lock (agent);
+
+ /* Don't signal writable if the socket that has become writable is not
+ * the selected pair */
+ if (component->selected_pair.local == NULL ||
+ !nice_socket_is_based_on (component->selected_pair.local->sockptr, sock)) {
+ agent_unlock (agent);
+ return;
+ }
+
+ nice_debug ("Agent %p: s%d:%d Tcp socket writable", agent,
+ component->stream_id, component->id);
+ agent_signal_socket_writable (agent, component);
+
+ agent_unlock_and_emit (agent);
+
+ g_object_unref (agent);
+}
+
+static const gchar *
+_transport_to_string (NiceCandidateTransport type) {
+ switch(type) {
+ case NICE_CANDIDATE_TRANSPORT_UDP:
+ return "UDP";
+ case NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE:
+ return "TCP-ACT";
+ case NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE:
+ return "TCP-PASS";
+ case NICE_CANDIDATE_TRANSPORT_TCP_SO:
+ return "TCP-SO";
+ default:
+ return "???";
+ }
+}
+
+void agent_gathering_done (NiceAgent *agent)
+{
+
+ GSList *i, *j, *k, *l, *m;
+
+ for (i = agent->streams; i; i = i->next) {
+ NiceStream *stream = i->data;
+
+ /* We ignore streams not in gathering state, typically already in
+ * ready state. Such streams may have couples (local,remote)
+ * candidates that have not resulted in the creation a new pair
+ * during a previous conncheck session, and we don't want these new
+ * pairs to be added now, because it would generate unneeded
+ * transition changes for a stream unconcerned by this gathering.
+ */
+ if (!stream->gathering)
+ continue;
+
+ for (j = stream->components; j; j = j->next) {
+ NiceComponent *component = j->data;
+
+ for (k = component->local_candidates; k; k = k->next) {
+ NiceCandidate *local_candidate = k->data;
+
+ if (agent->force_relay &&
+ local_candidate->type != NICE_CANDIDATE_TYPE_RELAYED)
+ continue;
+
+ if (nice_debug_is_enabled ()) {
+ gchar tmpbuf[INET6_ADDRSTRLEN];
+ nice_address_to_string (&local_candidate->addr, tmpbuf);
+ nice_debug ("Agent %p: gathered %s local candidate : [%s]:%u"
+ " for s%d/c%d. U/P '%s'/'%s'", agent,
+ _transport_to_string (local_candidate->transport),
+ tmpbuf, nice_address_get_port (&local_candidate->addr),
+ local_candidate->stream_id, local_candidate->component_id,
+ local_candidate->username, local_candidate->password);
+ }
+ for (l = component->remote_candidates; l; l = l->next) {
+ NiceCandidate *remote_candidate = l->data;
+
+ for (m = stream->conncheck_list; m; m = m->next) {
+ CandidateCheckPair *p = m->data;
+
+ if (p->local == local_candidate && p->remote == remote_candidate)
+ break;
+ }
+ if (m == NULL) {
+ conn_check_add_for_candidate_pair (agent, stream->id, component,
+ local_candidate, remote_candidate);
+ }
+ }
+ }
+ }
+ }
+
+#ifdef HAVE_GUPNP
+ if (agent->discovery_timer_source == NULL &&
+ agent->upnp_timer_source == NULL) {
+ agent_signal_gathering_done (agent);
+ }
+#else
+ if (agent->discovery_timer_source == NULL)
+ agent_signal_gathering_done (agent);
+#endif
+}
+
+void agent_signal_gathering_done (NiceAgent *agent)
+{
+ GSList *i;
+
+ for (i = agent->streams; i; i = i->next) {
+ NiceStream *stream = i->data;
+ if (stream->gathering) {
+ stream->gathering = FALSE;
+ agent_queue_signal (agent, signals[SIGNAL_CANDIDATE_GATHERING_DONE],
+ stream->id);
+ }
+ }
+}
+
+void
+agent_signal_initial_binding_request_received (NiceAgent *agent,
+ NiceStream *stream)
+{
+ if (stream->initial_binding_request_received != TRUE) {
+ stream->initial_binding_request_received = TRUE;
+ agent_queue_signal (agent, signals[SIGNAL_INITIAL_BINDING_REQUEST_RECEIVED],
+ stream->id);
+ }
+}
+
+/* If the Component now has a selected_pair, and has pending TCP packets which
+ * it couldn’t receive before due to not being able to send out ACKs (or
+ * SYNACKs, for the initial SYN packet), handle them now.
+ *
+ * Must be called with the agent lock held. */
+static void
+process_queued_tcp_packets (NiceAgent *agent, NiceStream *stream,
+ NiceComponent *component)
+{
+ GOutputVector *vec;
+ guint stream_id = stream->id;
+ guint component_id = component->id;
+
+ g_assert (agent->reliable);
+
+ if (component->selected_pair.local == NULL ||
+ pseudo_tcp_socket_is_closed (component->tcp) ||
+ nice_socket_is_reliable (component->selected_pair.local->sockptr)) {
+ return;
+ }
+
+ nice_debug_verbose ("%s: Sending outstanding packets for agent %p.", G_STRFUNC,
+ agent);
+
+ while ((vec = g_queue_peek_head (&component->queued_tcp_packets)) != NULL) {
+ gboolean retval;
+
+ nice_debug ("%s: Sending %" G_GSIZE_FORMAT " bytes.", G_STRFUNC, vec->size);
+ retval =
+ pseudo_tcp_socket_notify_packet (component->tcp, vec->buffer,
+ vec->size);
+
+ if (!agent_find_component (agent, stream_id, component_id,
+ &stream, &component)) {
+ nice_debug ("Stream or Component disappeared during "
+ "pseudo_tcp_socket_notify_packet()");
+ return;
+ }
+ if (pseudo_tcp_socket_is_closed (component->tcp)) {
+ nice_debug ("PseudoTCP socket got destroyed in"
+ " pseudo_tcp_socket_notify_packet()!");
+ return;
+ }
+
+ adjust_tcp_clock (agent, stream, component);
+
+ if (!retval) {
+ /* Failed to send; try again later. */
+ break;
+ }
+
+ g_queue_pop_head (&component->queued_tcp_packets);
+ g_free ((gpointer) vec->buffer);
+ g_slice_free (GOutputVector, vec);
+ }
+}
+
+void agent_signal_new_selected_pair (NiceAgent *agent, guint stream_id,
+ guint component_id, NiceCandidate *lcandidate, NiceCandidate *rcandidate)
+{
+ NiceComponent *component;
+ NiceStream *stream;
+
+ if (!agent_find_component (agent, stream_id, component_id,
+ &stream, &component))
+ return;
+
+ if (((NiceSocket *)lcandidate->sockptr)->type == NICE_SOCKET_TYPE_UDP_TURN) {
+ nice_udp_turn_socket_set_peer (lcandidate->sockptr, &rcandidate->addr);
+ }
+
+ if(agent->reliable && !nice_socket_is_reliable (lcandidate->sockptr)) {
+ if (!component->tcp)
+ pseudo_tcp_socket_create (agent, stream, component);
+ process_queued_tcp_packets (agent, stream, component);
+
+ pseudo_tcp_socket_connect (component->tcp);
+ pseudo_tcp_socket_notify_mtu (component->tcp, MAX_TCP_MTU);
+ adjust_tcp_clock (agent, stream, component);
+ }
+
+ if (nice_debug_is_enabled ()) {
+ gchar ip[100];
+ guint port;
+
+ port = nice_address_get_port (&lcandidate->addr);
+ nice_address_to_string (&lcandidate->addr, ip);
+
+ nice_debug ("Agent %p: Local selected pair: %d:%d %s %s %s:%d %s",
+ agent, stream_id, component_id, lcandidate->foundation,
+ lcandidate->transport == NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE ?
+ "TCP-ACT" :
+ lcandidate->transport == NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE ?
+ "TCP-PASS" :
+ lcandidate->transport == NICE_CANDIDATE_TRANSPORT_UDP ? "UDP" : "???",
+ ip, port, lcandidate->type == NICE_CANDIDATE_TYPE_HOST ? "HOST" :
+ lcandidate->type == NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE ?
+ "SRV-RFLX" :
+ lcandidate->type == NICE_CANDIDATE_TYPE_RELAYED ?
+ "RELAYED" :
+ lcandidate->type == NICE_CANDIDATE_TYPE_PEER_REFLEXIVE ?
+ "PEER-RFLX" : "???");
+
+ port = nice_address_get_port (&rcandidate->addr);
+ nice_address_to_string (&rcandidate->addr, ip);
+
+ nice_debug ("Agent %p: Remote selected pair: %d:%d %s %s %s:%d %s",
+ agent, stream_id, component_id, rcandidate->foundation,
+ rcandidate->transport == NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE ?
+ "TCP-ACT" :
+ rcandidate->transport == NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE ?
+ "TCP-PASS" :
+ rcandidate->transport == NICE_CANDIDATE_TRANSPORT_UDP ? "UDP" : "???",
+ ip, port, rcandidate->type == NICE_CANDIDATE_TYPE_HOST ? "HOST" :
+ rcandidate->type == NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE ?
+ "SRV-RFLX" :
+ rcandidate->type == NICE_CANDIDATE_TYPE_RELAYED ?
+ "RELAYED" :
+ rcandidate->type == NICE_CANDIDATE_TYPE_PEER_REFLEXIVE ?
+ "PEER-RFLX" : "???");
+ }
+
+ agent_queue_signal (agent, signals[SIGNAL_NEW_SELECTED_PAIR_FULL],
+ stream_id, component_id, lcandidate, rcandidate);
+ agent_queue_signal (agent, signals[SIGNAL_NEW_SELECTED_PAIR],
+ stream_id, component_id, lcandidate->foundation, rcandidate->foundation);
+
+ if(agent->reliable && nice_socket_is_reliable (lcandidate->sockptr)) {
+ agent_signal_socket_writable (agent, component);
+ }
+}
+
+void agent_signal_new_candidate (NiceAgent *agent, NiceCandidate *candidate)
+{
+ agent_queue_signal (agent, signals[SIGNAL_NEW_CANDIDATE_FULL],
+ candidate);
+ agent_queue_signal (agent, signals[SIGNAL_NEW_CANDIDATE],
+ candidate->stream_id, candidate->component_id, candidate->foundation);
+}
+
+void agent_signal_new_remote_candidate (NiceAgent *agent, NiceCandidate *candidate)
+{
+ agent_queue_signal (agent, signals[SIGNAL_NEW_REMOTE_CANDIDATE_FULL],
+ candidate);
+ agent_queue_signal (agent, signals[SIGNAL_NEW_REMOTE_CANDIDATE],
+ candidate->stream_id, candidate->component_id, candidate->foundation);
+}
+
+NICEAPI_EXPORT const gchar *
+nice_component_state_to_string (NiceComponentState state)
+{
+ switch (state)
+ {
+ case NICE_COMPONENT_STATE_DISCONNECTED:
+ return "disconnected";
+ case NICE_COMPONENT_STATE_GATHERING:
+ return "gathering";
+ case NICE_COMPONENT_STATE_CONNECTING:
+ return "connecting";
+ case NICE_COMPONENT_STATE_CONNECTED:
+ return "connected";
+ case NICE_COMPONENT_STATE_READY:
+ return "ready";
+ case NICE_COMPONENT_STATE_FAILED:
+ return "failed";
+ case NICE_COMPONENT_STATE_LAST:
+ default:
+ return "invalid";
+ }
+}
+
+void agent_signal_component_state_change (NiceAgent *agent, guint stream_id, guint component_id, NiceComponentState new_state)
+{
+ NiceComponentState old_state;
+ NiceComponent *component;
+ NiceStream *stream;
+
+ g_return_if_fail (new_state < NICE_COMPONENT_STATE_LAST);
+
+ if (!agent_find_component (agent, stream_id, component_id,
+ &stream, &component))
+ return;
+
+ /* Validate the state change. */
+ old_state = component->state;
+
+ if (new_state == old_state) {
+ return;
+ }
+
+ nice_debug ("Agent %p : stream %u component %u STATE-CHANGE %s -> %s.", agent,
+ stream_id, component_id, nice_component_state_to_string (old_state),
+ nice_component_state_to_string (new_state));
+
+ /* Check whether it’s a valid state transition. */
+#define TRANSITION(OLD, NEW) \
+ (old_state == NICE_COMPONENT_STATE_##OLD && \
+ new_state == NICE_COMPONENT_STATE_##NEW)
+
+ g_assert (/* Can (almost) always transition to FAILED (including
+ * DISCONNECTED → FAILED which happens if one component fails
+ * before another leaves DISCONNECTED): */
+ TRANSITION (DISCONNECTED, FAILED) ||
+ TRANSITION (GATHERING, FAILED) ||
+ TRANSITION (CONNECTING, FAILED) ||
+ TRANSITION (CONNECTED, FAILED) ||
+ TRANSITION (READY, FAILED) ||
+ /* Standard progression towards a ready connection: */
+ TRANSITION (DISCONNECTED, GATHERING) ||
+ TRANSITION (GATHERING, CONNECTING) ||
+ TRANSITION (CONNECTING, CONNECTED) ||
+ TRANSITION (CONNECTED, READY) ||
+ /* priv_conn_check_add_for_candidate_pair_matched(): */
+ TRANSITION (READY, CONNECTED) ||
+ /* If set_remote_candidates() is called with new candidates after
+ * reaching FAILED: */
+ TRANSITION (FAILED, CONNECTING) ||
+ /* if new relay servers are added to a failed connection */
+ TRANSITION (FAILED, GATHERING) ||
+ /* Possible by calling set_remote_candidates() without calling
+ * nice_agent_gather_candidates(): */
+ TRANSITION (DISCONNECTED, CONNECTING));
+
+#undef TRANSITION
+
+ component->state = new_state;
+
+ if (agent->reliable)
+ process_queued_tcp_packets (agent, stream, component);
+
+ agent_queue_signal (agent, signals[SIGNAL_COMPONENT_STATE_CHANGED],
+ stream_id, component_id, new_state);
+}
+
+guint64
+agent_candidate_pair_priority (NiceAgent *agent, NiceCandidate *local, NiceCandidate *remote)
+{
+ if (agent->controlling_mode)
+ return nice_candidate_pair_priority (local->priority, remote->priority);
+ else
+ return nice_candidate_pair_priority (remote->priority, local->priority);
+}
+
+static void
+priv_add_new_candidate_discovery_stun (NiceAgent *agent,
+ NiceSocket *nicesock, NiceAddress server,
+ NiceStream *stream, guint component_id)
+{
+ CandidateDiscovery *cdisco;
+
+ /* note: no need to check for redundant candidates, as this is
+ * done later on in the process */
+
+ cdisco = g_slice_new0 (CandidateDiscovery);
+
+ cdisco->type = NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE;
+ cdisco->nicesock = nicesock;
+ cdisco->server = server;
+ cdisco->stream_id = stream->id;
+ cdisco->component_id = component_id;
+ stun_agent_init (&cdisco->stun_agent, STUN_ALL_KNOWN_ATTRIBUTES,
+ STUN_COMPATIBILITY_RFC3489,
+ (agent->compatibility == NICE_COMPATIBILITY_OC2007 ||
+ agent->compatibility == NICE_COMPATIBILITY_OC2007R2) ?
+ STUN_AGENT_USAGE_NO_ALIGNED_ATTRIBUTES : 0);
+
+ nice_debug ("Agent %p : Adding new srv-rflx candidate discovery %p",
+ agent, cdisco);
+
+ agent->discovery_list = g_slist_append (agent->discovery_list, cdisco);
+ ++agent->discovery_unsched_items;
+}
+
+static void
+priv_add_new_candidate_discovery_turn (NiceAgent *agent,
+ NiceSocket *nicesock, TurnServer *turn,
+ NiceStream *stream, guint component_id, gboolean turn_tcp)
+{
+ CandidateDiscovery *cdisco;
+ NiceComponent *component = nice_stream_find_component_by_id (stream, component_id);
+ NiceAddress local_address;
+
+ /* note: no need to check for redundant candidates, as this is
+ * done later on in the process */
+
+ cdisco = g_slice_new0 (CandidateDiscovery);
+ cdisco->type = NICE_CANDIDATE_TYPE_RELAYED;
+
+ if (turn->type == NICE_RELAY_TYPE_TURN_UDP) {
+ if (agent->use_ice_udp == FALSE || turn_tcp == TRUE) {
+ g_slice_free (CandidateDiscovery, cdisco);
+ return;
+ }
+ if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE) {
+ NiceAddress addr = nicesock->addr;
+ NiceSocket *new_socket;
+ nice_address_set_port (&addr, 0);
+
+ new_socket = nice_udp_bsd_socket_new (&addr);
+ if (new_socket) {
+ _priv_set_socket_tos (agent, new_socket, stream->tos);
+ nice_component_attach_socket (component, new_socket);
+ nicesock = new_socket;
+ }
+ }
+ cdisco->nicesock = nicesock;
+ } else {
+ NiceAddress proxy_server;
+ gboolean reliable_tcp = FALSE;
+
+ /* MS-TURN will allocate a transport with the same protocol it received
+ * the allocate request. So if we are connecting in TCP, then the candidate
+ * will be TCP-ACT/TCP-PASS which means it will be reliable all the way
+ * to the peer.
+ * [MS-TURN] : The transport address has the same transport protocol
+ * over which the Allocate request was received; a request that is
+ * received over TCP returns a TCP allocated transport address.
+ */
+ if (turn_tcp)
+ reliable_tcp = TRUE;
+
+ /* Ignore tcp candidates if we disabled ice-tcp */
+ if ((agent->use_ice_udp == FALSE && reliable_tcp == FALSE) ||
+ (agent->use_ice_tcp == FALSE && reliable_tcp == TRUE)) {
+ g_slice_free (CandidateDiscovery, cdisco);
+ return;
+ }
+
+ /* TURN-TCP is currently unsupport unless it's OC2007 compatibliity */
+ /* TODO: Add support for TURN-TCP */
+ if (((agent->compatibility == NICE_COMPATIBILITY_OC2007 ||
+ agent->compatibility == NICE_COMPATIBILITY_OC2007R2) &&
+ reliable_tcp == FALSE) ||
+ (!(agent->compatibility == NICE_COMPATIBILITY_OC2007 ||
+ agent->compatibility == NICE_COMPATIBILITY_OC2007R2) &&
+ reliable_tcp == TRUE)) {
+ g_slice_free (CandidateDiscovery, cdisco);
+ return;
+ }
+
+ local_address = nicesock->addr;
+ nice_address_set_port (&local_address, 0);
+ nicesock = NULL;
+
+ /* TODO: add support for turn-tcp RFC 6062 */
+ if (agent->proxy_type != NICE_PROXY_TYPE_NONE &&
+ agent->proxy_ip != NULL &&
+ nice_address_set_from_string (&proxy_server, agent->proxy_ip)) {
+ nice_address_set_port (&proxy_server, agent->proxy_port);
+ nicesock = nice_tcp_bsd_socket_new (agent->main_context, &local_address,
+ &proxy_server, reliable_tcp);
+
+ if (nicesock) {
+ _priv_set_socket_tos (agent, nicesock, stream->tos);
+ if (agent->proxy_type == NICE_PROXY_TYPE_SOCKS5) {
+ nicesock = nice_socks5_socket_new (nicesock, &turn->server,
+ agent->proxy_username, agent->proxy_password);
+ } else if (agent->proxy_type == NICE_PROXY_TYPE_HTTP){
+ nicesock = nice_http_socket_new (nicesock, &turn->server,
+ agent->proxy_username, agent->proxy_password);
+ } else {
+ nice_socket_free (nicesock);
+ nicesock = NULL;
+ }
+ }
+
+ }
+ if (nicesock == NULL) {
+ nicesock = nice_tcp_bsd_socket_new (agent->main_context, &local_address,
+ &turn->server, reliable_tcp);
+
+ if (nicesock)
+ _priv_set_socket_tos (agent, nicesock, stream->tos);
+ }
+
+ /* The TURN server may be invalid or not listening */
+ if (nicesock == NULL)
+ return;
+
+ nice_socket_set_writable_callback (nicesock, _tcp_sock_is_writable, component);
+
+ if (turn->type == NICE_RELAY_TYPE_TURN_TLS &&
+ agent->compatibility == NICE_COMPATIBILITY_GOOGLE) {
+ nicesock = nice_pseudossl_socket_new (nicesock,
+ NICE_PSEUDOSSL_SOCKET_COMPATIBILITY_GOOGLE);
+ } else if (turn->type == NICE_RELAY_TYPE_TURN_TLS &&
+ (agent->compatibility == NICE_COMPATIBILITY_OC2007 ||
+ agent->compatibility == NICE_COMPATIBILITY_OC2007R2)) {
+ nicesock = nice_pseudossl_socket_new (nicesock,
+ NICE_PSEUDOSSL_SOCKET_COMPATIBILITY_MSOC);
+ }
+ cdisco->nicesock = nice_udp_turn_over_tcp_socket_new (nicesock,
+ agent_to_turn_socket_compatibility (agent));
+
+ nice_component_attach_socket (component, cdisco->nicesock);
+ }
+
+ cdisco->turn = turn_server_ref (turn);
+ cdisco->server = turn->server;
+
+ cdisco->stream_id = stream->id;
+ cdisco->component_id = component_id;
+
+ if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE) {
+ stun_agent_init (&cdisco->stun_agent, STUN_ALL_KNOWN_ATTRIBUTES,
+ STUN_COMPATIBILITY_RFC3489,
+ STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS |
+ STUN_AGENT_USAGE_IGNORE_CREDENTIALS);
+ } else if (agent->compatibility == NICE_COMPATIBILITY_MSN ||
+ agent->compatibility == NICE_COMPATIBILITY_WLM2009) {
+ stun_agent_init (&cdisco->stun_agent, STUN_ALL_KNOWN_ATTRIBUTES,
+ STUN_COMPATIBILITY_RFC3489,
+ STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS);
+ } else if (agent->compatibility == NICE_COMPATIBILITY_OC2007 ||
+ agent->compatibility == NICE_COMPATIBILITY_OC2007R2) {
+ stun_agent_init (&cdisco->stun_agent, STUN_MSOC_KNOWN_ATTRIBUTES,
+ STUN_COMPATIBILITY_OC2007,
+ STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS |
+ STUN_AGENT_USAGE_NO_ALIGNED_ATTRIBUTES);
+ } else {
+ stun_agent_init (&cdisco->stun_agent, STUN_ALL_KNOWN_ATTRIBUTES,
+ STUN_COMPATIBILITY_RFC5389,
+ STUN_AGENT_USAGE_ADD_SOFTWARE |
+ STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS);
+ }
+ stun_agent_set_software (&cdisco->stun_agent, agent->software_attribute);
+
+ nice_debug ("Agent %p : Adding new relay-rflx candidate discovery %p",
+ agent, cdisco);
+ agent->discovery_list = g_slist_append (agent->discovery_list, cdisco);
+ ++agent->discovery_unsched_items;
+}
+
+NICEAPI_EXPORT guint
+nice_agent_add_stream (
+ NiceAgent *agent,
+ guint n_components)
+{
+ NiceStream *stream;
+ guint ret = 0;
+ guint i;
+
+ g_return_val_if_fail (NICE_IS_AGENT (agent), 0);
+ g_return_val_if_fail (n_components >= 1, 0);
+
+ agent_lock (agent);
+ stream = nice_stream_new (agent->next_stream_id++, n_components, agent);
+
+ agent->streams = g_slist_append (agent->streams, stream);
+ nice_debug ("Agent %p : allocating stream id %u (%p)", agent, stream->id, stream);
+ if (agent->reliable) {
+ nice_debug ("Agent %p : reliable stream", agent);
+ for (i = 0; i < n_components; i++) {
+ NiceComponent *component = nice_stream_find_component_by_id (stream, i + 1);
+ if (component) {
+ pseudo_tcp_socket_create (agent, stream, component);
+ } else {
+ nice_debug ("Agent %p: couldn't find component %d", agent, i+1);
+ }
+ }
+ }
+
+ nice_stream_initialize_credentials (stream, agent->rng);
+
+ ret = stream->id;
+
+ agent_unlock_and_emit (agent);
+ return ret;
+}
+
+
+NICEAPI_EXPORT gboolean
+nice_agent_set_relay_info(NiceAgent *agent,
+ guint stream_id, guint component_id,
+ const gchar *server_ip, guint server_port,
+ const gchar *username, const gchar *password,
+ NiceRelayType type)
+{
+
+ NiceComponent *component = NULL;
+ NiceStream *stream = NULL;
+ gboolean ret = TRUE;
+ TurnServer *turn;
+
+ g_return_val_if_fail (NICE_IS_AGENT (agent), FALSE);
+ g_return_val_if_fail (stream_id >= 1, FALSE);
+ g_return_val_if_fail (component_id >= 1, FALSE);
+ g_return_val_if_fail (server_ip, FALSE);
+ g_return_val_if_fail (server_port, FALSE);
+ g_return_val_if_fail (username, FALSE);
+ g_return_val_if_fail (password, FALSE);
+ g_return_val_if_fail (type <= NICE_RELAY_TYPE_TURN_TLS, FALSE);
+
+ agent_lock (agent);
+
+ if (!agent_find_component (agent, stream_id, component_id, &stream,
+ &component)) {
+ ret = FALSE;
+ goto done;
+ }
+
+ turn = turn_server_new (server_ip, server_port, username, password, type);
+
+ if (!turn) {
+ ret = FALSE;
+ goto done;
+ }
+
+ nice_debug ("Agent %p: added relay server [%s]:%d of type %d to s/c %d/%d "
+ "with user/pass : %s -- %s", agent, server_ip, server_port, type,
+ stream_id, component_id, username,
+ nice_debug_is_verbose() ? password : "****");
+
+ component->turn_servers = g_list_append (component->turn_servers, turn);
+
+ if (stream->gathering_started) {
+ GSList *i;
+
+ stream->gathering = TRUE;
+
+ for (i = component->local_candidates; i; i = i->next) {
+ NiceCandidate *candidate = i->data;
+
+ if (candidate->type == NICE_CANDIDATE_TYPE_HOST &&
+ candidate->transport != NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE &&
+ nice_address_ip_version (&candidate->addr) ==
+ nice_address_ip_version (&turn->server))
+ priv_add_new_candidate_discovery_turn (agent,
+ candidate->sockptr, turn, stream, component_id,
+ candidate->transport != NICE_CANDIDATE_TRANSPORT_UDP);
+ }
+
+ if (agent->discovery_unsched_items)
+ discovery_schedule (agent);
+ }
+
+
+ done:
+
+ agent_unlock_and_emit (agent);
+ return ret;
+}
+
+#ifdef HAVE_GUPNP
+
+static void agent_check_upnp_gathering_done (NiceAgent *agent);
+
+static gboolean priv_upnp_timeout_cb_agent_locked (NiceAgent *agent,
+ gpointer user_data)
+{
+ nice_debug ("Agent %p : UPnP port mapping timed out", agent);
+
+ /* We cannot free priv->upnp here as it may be holding mappings open which
+ * we are using (e.g. if some mappings were successful and others errored). */
+ g_slist_free_full (agent->upnp_mapping, (GDestroyNotify) nice_address_free);
+ agent->upnp_mapping = NULL;
+
+ agent_check_upnp_gathering_done (agent);
+
+ return FALSE;
+}
+
+/* Check whether UPnP gathering is done, which is true when the list of pending
+ * mappings (upnp_mapping) is empty. When it is empty, we have heard back from
+ * gupnp-igd about each of the mappings we added, either successfully or not.
+ *
+ * Note that upnp_mapping has to be a list, rather than a counter, as the
+ * mapped-external-port and error-mapping-port signals could be emitted multiple
+ * times for each mapping. */
+static void agent_check_upnp_gathering_done (NiceAgent *agent)
+{
+ if (agent->upnp_mapping != NULL)
+ return;
+
+ if (agent->upnp_timer_source != NULL) {
+ g_source_destroy (agent->upnp_timer_source);
+ g_source_unref (agent->upnp_timer_source);
+ agent->upnp_timer_source = NULL;
+ }
+
+ agent_gathering_done (agent);
+}
+
+static void _upnp_mapped_external_port (GUPnPSimpleIgd *self, gchar *proto,
+ gchar *external_ip, gchar *replaces_external_ip, guint external_port,
+ gchar *local_ip, guint local_port, gchar *description, gpointer user_data)
+{
+ NiceAgent *agent = (NiceAgent*)user_data;
+ NiceAddress localaddr;
+ NiceAddress externaddr;
+ NiceCandidateTransport transport;
+ GSList *i, *j, *k;
+
+ agent_lock (agent);
+
+ if (agent->upnp_timer_source == NULL)
+ goto end;
+
+ nice_debug ("Agent %p : Successfully mapped %s:%d to %s:%d", agent, local_ip,
+ local_port, external_ip, external_port);
+
+ if (!nice_address_set_from_string (&localaddr, local_ip))
+ goto end;
+ nice_address_set_port (&localaddr, local_port);
+
+ if (g_strcmp0 (proto, "TCP") == 0)
+ transport = NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE;
+ else
+ transport = NICE_CANDIDATE_TRANSPORT_UDP;
+
+ for (i = agent->upnp_mapping; i; i = i->next) {
+ NiceAddress *addr = i->data;
+ if (nice_address_equal (&localaddr, addr)) {
+ agent->upnp_mapping = g_slist_remove (agent->upnp_mapping, addr);
+ nice_address_free (addr);
+ break;
+ }
+ }
+
+ if (!nice_address_set_from_string (&externaddr, external_ip))
+ goto end;
+ nice_address_set_port (&externaddr, external_port);
+
+ for (i = agent->streams; i; i = i->next) {
+ NiceStream *stream = i->data;
+ for (j = stream->components; j; j = j->next) {
+ NiceComponent *component = j->data;
+ for (k = component->local_candidates; k; k = k->next) {
+ NiceCandidate *local_candidate = k->data;
+
+ if (agent->force_relay &&
+ local_candidate->type != NICE_CANDIDATE_TYPE_RELAYED)
+ continue;
+
+ if (nice_address_equal (&localaddr, &local_candidate->base_addr)) {
+ discovery_add_server_reflexive_candidate (
+ agent,
+ stream->id,
+ component->id,
+ &externaddr,
+ transport,
+ local_candidate->sockptr,
+ TRUE);
+ goto end;
+ }
+ }
+ }
+ }
+
+ end:
+ agent_check_upnp_gathering_done (agent);
+
+ agent_unlock_and_emit (agent);
+}
+
+static void _upnp_error_mapping_port (GUPnPSimpleIgd *self, GError *error,
+ gchar *proto, guint external_port, gchar *local_ip, guint local_port,
+ gchar *description, gpointer user_data)
+{
+ NiceAgent *agent = (NiceAgent*)user_data;
+ NiceAddress localaddr;
+ GSList *i;
+
+ agent_lock (agent);
+
+ nice_debug ("Agent %p : Error mapping %s:%d to %d (%d) : %s", agent, local_ip,
+ local_port, external_port, error->domain, error->message);
+ if (nice_address_set_from_string (&localaddr, local_ip)) {
+ nice_address_set_port (&localaddr, local_port);
+
+ for (i = agent->upnp_mapping; i; i = i->next) {
+ NiceAddress *addr = i->data;
+ if (nice_address_equal (&localaddr, addr)) {
+ agent->upnp_mapping = g_slist_remove (agent->upnp_mapping, addr);
+ nice_address_free (addr);
+ break;
+ }
+ }
+
+ agent_check_upnp_gathering_done (agent);
+ }
+
+ agent_unlock_and_emit (agent);
+}
+
+#endif
+
+NICEAPI_EXPORT gboolean
+nice_agent_gather_candidates (
+ NiceAgent *agent,
+ guint stream_id)
+{
+ guint cid;
+ GSList *i;
+ NiceStream *stream;
+ GSList *local_addresses = NULL;
+ gboolean ret = TRUE;
+
+ g_return_val_if_fail (NICE_IS_AGENT (agent), FALSE);
+ g_return_val_if_fail (stream_id >= 1, FALSE);
+
+ agent_lock (agent);
+
+ stream = agent_find_stream (agent, stream_id);
+ if (stream == NULL) {
+ agent_unlock_and_emit (agent);
+ return FALSE;
+ }
+
+ if (stream->gathering_started) {
+ /* Stream is already gathering, ignore this call */
+ agent_unlock_and_emit (agent);
+ return TRUE;
+ }
+
+ nice_debug ("Agent %p : In %s mode, starting candidate gathering.", agent,
+ agent->full_mode ? "ICE-FULL" : "ICE-LITE");
+
+#ifdef HAVE_GUPNP
+ if (agent->upnp_enabled && agent->upnp == NULL && !agent->force_relay) {
+ agent->upnp = gupnp_simple_igd_thread_new ();
+
+ if (agent->upnp) {
+ g_signal_connect (agent->upnp, "mapped-external-port",
+ G_CALLBACK (_upnp_mapped_external_port), agent);
+ g_signal_connect (agent->upnp, "error-mapping-port",
+ G_CALLBACK (_upnp_error_mapping_port), agent);
+ } else {
+ nice_debug ("Agent %p : Error creating UPnP Simple IGD agent", agent);
+ }
+ } else {
+ nice_debug ("Agent %p : UPnP property Disabled", agent);
+ }
+#else
+ nice_debug ("Agent %p : libnice compiled without UPnP support", agent);
+#endif
+
+ /* if no local addresses added, generate them ourselves */
+ if (agent->local_addresses == NULL) {
+ GList *addresses = nice_interfaces_get_local_ips (FALSE);
+ GList *item;
+
+ for (item = addresses; item; item = g_list_next (item)) {
+ const gchar *addr_string = item->data;
+ NiceAddress *addr = nice_address_new ();
+
+ if (nice_address_set_from_string (addr, addr_string)) {
+ local_addresses = g_slist_append (local_addresses, addr);
+ } else {
+ nice_debug ("Error: Failed to parse local address ‘%s’.", addr_string);
+ nice_address_free (addr);
+ }
+ }
+
+ g_list_free_full (addresses, (GDestroyNotify) g_free);
+ } else {
+ for (i = agent->local_addresses; i; i = i->next) {
+ NiceAddress *addr = i->data;
+ NiceAddress *dupaddr = nice_address_dup (addr);
+
+ local_addresses = g_slist_append (local_addresses, dupaddr);
+ }
+ }
+
+ for (cid = 1; cid <= stream->n_components; cid++) {
+ NiceComponent *component = nice_stream_find_component_by_id (stream, cid);
+ gboolean found_local_address = FALSE;
+ enum {
+ ADD_HOST_MIN = 0,
+ ADD_HOST_UDP = ADD_HOST_MIN,
+ ADD_HOST_TCP_ACTIVE,
+ ADD_HOST_TCP_PASSIVE,
+ ADD_HOST_MAX = ADD_HOST_TCP_PASSIVE
+ } add_type;
+
+ if (component == NULL)
+ continue;
+
+ /* generate a local host candidate for each local address */
+ for (i = local_addresses; i; i = i->next) {
+ NiceAddress *addr = i->data;
+ NiceCandidate *host_candidate;
+
+#ifdef HAVE_GUPNP
+ gchar local_ip[NICE_ADDRESS_STRING_LEN];
+ nice_address_to_string (addr, local_ip);
+#endif
+
+ for (add_type = ADD_HOST_MIN; add_type <= ADD_HOST_MAX; add_type++) {
+ NiceCandidateTransport transport;
+ guint current_port;
+ guint start_port;
+ HostCandidateResult res = HOST_CANDIDATE_CANT_CREATE_SOCKET;
+
+ if ((agent->use_ice_udp == FALSE && add_type == ADD_HOST_UDP) ||
+ (agent->use_ice_tcp == FALSE && add_type != ADD_HOST_UDP))
+ continue;
+
+ switch (add_type) {
+ default:
+ case ADD_HOST_UDP:
+ transport = NICE_CANDIDATE_TRANSPORT_UDP;
+ break;
+ case ADD_HOST_TCP_ACTIVE:
+ transport = NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE;
+ break;
+ case ADD_HOST_TCP_PASSIVE:
+ transport = NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE;
+ break;
+ }
+
+ start_port = component->min_port;
+ if(component->min_port != 0) {
+ start_port = nice_rng_generate_int(agent->rng, component->min_port, component->max_port+1);
+ }
+ current_port = start_port;
+
+ host_candidate = NULL;
+ while (res == HOST_CANDIDATE_CANT_CREATE_SOCKET) {
+ nice_debug ("Agent %p: Trying to create host candidate on port %d", agent, current_port);
+ nice_address_set_port (addr, current_port);
+ res = discovery_add_local_host_candidate (agent, stream->id, cid,
+ addr, transport, &host_candidate);
+ if (current_port > 0)
+ current_port++;
+ if (current_port > component->max_port) current_port = component->min_port;
+ if (current_port == 0 || current_port == start_port)
+ break;
+ }
+
+ if (res == HOST_CANDIDATE_REDUNDANT) {
+ nice_debug ("Agent %p: Ignoring local candidate, it's redundant",
+ agent);
+ continue;
+ } else if (res == HOST_CANDIDATE_FAILED) {
+ nice_debug ("Agent %p: Could ot retrieive component %d/%d", agent,
+ stream->id, cid);
+ continue;
+ } else if (res == HOST_CANDIDATE_CANT_CREATE_SOCKET) {
+ if (nice_debug_is_enabled ()) {
+ gchar ip[NICE_ADDRESS_STRING_LEN];
+ nice_address_to_string (addr, ip);
+ nice_debug ("Agent %p: Unable to add local host candidate %s for"
+ " s%d:%d. Invalid interface?", agent, ip, stream->id,
+ component->id);
+ }
+ continue;
+ }
+
+ found_local_address = TRUE;
+ nice_address_set_port (addr, 0);
+
+ nice_socket_set_writable_callback (host_candidate->sockptr,
+ _tcp_sock_is_writable, component);
+
+#ifdef HAVE_GUPNP
+ if (agent->upnp_enabled && agent->upnp &&
+ transport != NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE) {
+ NiceAddress *base_addr = nice_address_dup (&host_candidate->base_addr);
+ nice_debug ("Agent %p: Adding UPnP port %s:%d", agent, local_ip,
+ nice_address_get_port (base_addr));
+ gupnp_simple_igd_add_port (GUPNP_SIMPLE_IGD (agent->upnp),
+ transport == NICE_CANDIDATE_TRANSPORT_UDP ? "UDP" : "TCP",
+ 0, local_ip, nice_address_get_port (base_addr),
+ 0, PACKAGE_STRING);
+ agent->upnp_mapping = g_slist_prepend (agent->upnp_mapping, base_addr);
+
+ agent_timeout_add_with_context (agent, &agent->upnp_timer_source,
+ "UPnP timeout", agent->upnp_timeout,
+ priv_upnp_timeout_cb_agent_locked, agent);
+ }
+#endif
+
+ /* TODO: Add server-reflexive support for TCP candidates */
+ if (agent->full_mode && agent->stun_server_ip && !agent->force_relay &&
+ transport == NICE_CANDIDATE_TRANSPORT_UDP) {
+ NiceAddress stun_server;
+ if (nice_address_set_from_string (&stun_server, agent->stun_server_ip)) {
+ nice_address_set_port (&stun_server, agent->stun_server_port);
+
+ if (nice_address_ip_version (&host_candidate->addr) ==
+ nice_address_ip_version (&stun_server))
+ priv_add_new_candidate_discovery_stun (agent,
+ host_candidate->sockptr,
+ stun_server,
+ stream,
+ cid);
+ }
+ }
+
+ if (agent->full_mode && component &&
+ transport != NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE) {
+ GList *item;
+ int host_ip_version = nice_address_ip_version (&host_candidate->addr);
+
+ for (item = component->turn_servers; item; item = item->next) {
+ TurnServer *turn = item->data;
+
+ if (host_ip_version != nice_address_ip_version (&turn->server)) {
+ continue;
+ }
+
+ priv_add_new_candidate_discovery_turn (agent,
+ host_candidate->sockptr,
+ turn,
+ stream,
+ cid,
+ host_candidate->transport != NICE_CANDIDATE_TRANSPORT_UDP);
+ }
+ }
+ }
+ }
+ /* Go to error if we could not find a local address for a given
+ * component
+ */
+ if (!found_local_address) {
+ ret = FALSE;
+ goto error;
+ }
+ }
+
+ stream->gathering = TRUE;
+ stream->gathering_started = TRUE;
+
+ /* Only signal the new candidates after we're sure that the gathering was
+ * succesfful. But before sending gathering-done */
+ for (cid = 1; cid <= stream->n_components; cid++) {
+ NiceComponent *component = nice_stream_find_component_by_id (stream, cid);
+ for (i = component->local_candidates; i; i = i->next) {
+ NiceCandidate *candidate = i->data;
+
+ if (agent->force_relay && candidate->type != NICE_CANDIDATE_TYPE_RELAYED)
+ continue;
+
+ agent_signal_new_candidate (agent, candidate);
+ }
+ }
+
+ /* note: no async discoveries pending, signal that we are ready */
+ if (agent->discovery_unsched_items == 0 &&
+#ifdef HAVE_GUPNP
+ agent->upnp_mapping == NULL) {
+#else
+ TRUE) {
+#endif
+ nice_debug ("Agent %p: Candidate gathering FINISHED, no scheduled items.",
+ agent);
+ agent_gathering_done (agent);
+ } else if (agent->discovery_unsched_items) {
+ discovery_schedule (agent);
+ }
+
+ error:
+ for (i = local_addresses; i; i = i->next)
+ nice_address_free (i->data);
+ g_slist_free (local_addresses);
+
+ if (ret == FALSE) {
+ priv_stop_upnp (agent);
+ for (cid = 1; cid <= stream->n_components; cid++) {
+ NiceComponent *component = nice_stream_find_component_by_id (stream, cid);
+
+ nice_component_free_socket_sources (component);
+
+ for (i = component->local_candidates; i; i = i->next) {
+ NiceCandidate *candidate = i->data;
+
+ agent_remove_local_candidate (agent, candidate);
+
+ nice_candidate_free (candidate);
+ }
+ g_slist_free (component->local_candidates);
+ component->local_candidates = NULL;
+ }
+ discovery_prune_stream (agent, stream_id);
+ }
+
+ agent_unlock_and_emit (agent);
+
+ return ret;
+}
+
+void agent_remove_local_candidate (NiceAgent *agent, NiceCandidate *candidate)
+{
+#ifdef HAVE_GUPNP
+ gchar local_ip[NICE_ADDRESS_STRING_LEN];
+
+ if (agent->upnp == NULL)
+ return;
+
+ if (candidate->type != NICE_CANDIDATE_TYPE_HOST)
+ return;
+
+ if (nice_address_get_port (&candidate->addr) == 0)
+ return;
+
+ nice_address_to_string (&candidate->addr, local_ip);
+
+ gupnp_simple_igd_remove_port_local (GUPNP_SIMPLE_IGD (agent->upnp), "UDP",
+ local_ip, nice_address_get_port (&candidate->addr));
+#endif
+}
+
+static void priv_stop_upnp (NiceAgent *agent)
+{
+#ifdef HAVE_GUPNP
+ if (!agent->upnp)
+ return;
+
+ g_slist_free_full (agent->upnp_mapping, (GDestroyNotify) nice_address_free);
+ agent->upnp_mapping = NULL;
+
+ if (agent->upnp_timer_source != NULL) {
+ g_source_destroy (agent->upnp_timer_source);
+ g_source_unref (agent->upnp_timer_source);
+ agent->upnp_timer_source = NULL;
+ }
+#endif
+}
+
+static void priv_remove_keepalive_timer (NiceAgent *agent)
+{
+ if (agent->keepalive_timer_source != NULL) {
+ g_source_destroy (agent->keepalive_timer_source);
+ g_source_unref (agent->keepalive_timer_source);
+ agent->keepalive_timer_source = NULL;
+ }
+}
+
+static gboolean
+on_stream_refreshes_pruned (NiceAgent *agent, NiceStream *stream)
+{
+ // This is called from a timeout cb with agent lock held
+
+ nice_stream_close (agent, stream);
+
+ agent_unlock (agent);
+
+ /* Actually free the stream. This should be done with the lock released, as
+ * it could end up disposing of a NiceIOStream, which tries to take the
+ * agent lock itself. */
+ g_object_unref (stream);
+
+ agent_lock (agent);
+
+ return G_SOURCE_REMOVE;
+}
+
+NICEAPI_EXPORT void
+nice_agent_remove_stream (
+ NiceAgent *agent,
+ guint stream_id)
+{
+ guint stream_ids[] = { stream_id, 0 };
+
+ /* note that streams/candidates can be in use by other threads */
+
+ NiceStream *stream;
+
+ g_return_if_fail (NICE_IS_AGENT (agent));
+ g_return_if_fail (stream_id >= 1);
+
+ agent_lock (agent);
+ stream = agent_find_stream (agent, stream_id);
+
+ if (!stream) {
+ agent_unlock_and_emit (agent);
+ return;
+ }
+
+ /* note: remove items with matching stream_ids from both lists */
+ conn_check_prune_stream (agent, stream);
+ discovery_prune_stream (agent, stream_id);
+ refresh_prune_stream_async (agent, stream,
+ (NiceTimeoutLockedCallback) on_stream_refreshes_pruned);
+
+ /* Remove the stream and signal its removal. */
+ agent->streams = g_slist_remove (agent->streams, stream);
+
+ if (!agent->streams)
+ priv_remove_keepalive_timer (agent);
+
+ agent_queue_signal (agent, signals[SIGNAL_STREAMS_REMOVED],
+ g_memdup (stream_ids, sizeof(stream_ids)));
+
+ agent_unlock_and_emit (agent);
+}
+
+NICEAPI_EXPORT void
+nice_agent_set_port_range (NiceAgent *agent, guint stream_id, guint component_id,
+ guint min_port, guint max_port)
+{
+ NiceStream *stream;
+ NiceComponent *component;
+
+ g_return_if_fail (NICE_IS_AGENT (agent));
+ g_return_if_fail (stream_id >= 1);
+ g_return_if_fail (component_id >= 1);
+
+ agent_lock (agent);
+
+ if (agent_find_component (agent, stream_id, component_id, &stream,
+ &component)) {
+ if (stream->gathering_started) {
+ g_critical ("nice_agent_gather_candidates (stream_id=%u) already called for this stream", stream_id);
+ } else {
+ component->min_port = min_port;
+ component->max_port = max_port;
+ }
+ }
+
+ agent_unlock_and_emit (agent);
+}
+
+NICEAPI_EXPORT gboolean
+nice_agent_add_local_address (NiceAgent *agent, NiceAddress *addr)
+{
+ NiceAddress *dupaddr;
+
+ g_return_val_if_fail (NICE_IS_AGENT (agent), FALSE);
+ g_return_val_if_fail (addr != NULL, FALSE);
+
+ agent_lock (agent);
+
+ dupaddr = nice_address_dup (addr);
+ nice_address_set_port (dupaddr, 0);
+ agent->local_addresses = g_slist_append (agent->local_addresses, dupaddr);
+
+ agent_unlock_and_emit (agent);
+ return TRUE;
+}
+
+/* Recompute foundations of all candidate pairs from a given stream
+ * having a specific remote candidate
+ */
+static void priv_update_pair_foundations (NiceAgent *agent,
+ guint stream_id, NiceCandidate *remote)
+{
+ NiceStream *stream = agent_find_stream (agent, stream_id);
+ if (stream) {
+ GSList *i;
+ for (i = stream->conncheck_list; i; i = i->next) {
+ CandidateCheckPair *pair = i->data;
+ if (pair->remote == remote) {
+ g_snprintf (pair->foundation,
+ NICE_CANDIDATE_PAIR_MAX_FOUNDATION, "%s:%s",
+ pair->local->foundation, pair->remote->foundation);
+ nice_debug ("Agent %p : Updating pair %p foundation to '%s'",
+ agent, pair, pair->foundation);
+ }
+ }
+ }
+}
+
+static gboolean priv_add_remote_candidate (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ NiceCandidateType type,
+ const NiceAddress *addr,
+ const NiceAddress *base_addr,
+ NiceCandidateTransport transport,
+ guint32 priority,
+ const gchar *username,
+ const gchar *password,
+ const gchar *foundation)
+{
+ NiceComponent *component;
+ NiceCandidate *candidate;
+
+ if (transport == NICE_CANDIDATE_TRANSPORT_UDP &&
+ !agent->use_ice_udp)
+ return FALSE;
+ if (transport != NICE_CANDIDATE_TRANSPORT_UDP &&
+ !agent->use_ice_tcp)
+ return FALSE;
+
+ if (!agent_find_component (agent, stream_id, component_id, NULL, &component))
+ return FALSE;
+
+ /* step: check whether the candidate already exists */
+ candidate = nice_component_find_remote_candidate (component, addr, transport);
+
+ /* If it was a discovered remote peer reflexive candidate, then it should
+ * be updated according to RFC 5245 section 7.2.1.3 */
+ if (candidate && candidate->type == NICE_CANDIDATE_TYPE_PEER_REFLEXIVE) {
+ nice_debug ("Agent %p : Updating existing peer-rfx remote candidate to %s",
+ agent, _cand_type_to_sdp (type));
+ candidate->type = type;
+ /* If it got there, the next one will also be ran, so the foundation
+ * will be set.
+ */
+ }
+
+ if (candidate && candidate->type == type) {
+ if (nice_debug_is_enabled ()) {
+ gchar tmpbuf[INET6_ADDRSTRLEN];
+ nice_address_to_string (addr, tmpbuf);
+ nice_debug ("Agent %p : Updating existing remote candidate with addr [%s]:%u"
+ " for s%d/c%d. U/P '%s'/'%s' prio: %u", agent, tmpbuf,
+ nice_address_get_port (addr), stream_id, component_id,
+ username, password, priority);
+ }
+ /* case 1: an existing candidate, update the attributes */
+ if (base_addr)
+ candidate->base_addr = *base_addr;
+ candidate->priority = priority;
+ if (foundation)
+ g_strlcpy(candidate->foundation, foundation,
+ NICE_CANDIDATE_MAX_FOUNDATION);
+ /* note: username and password must remain the same during
+ * a session; see sect 9.1.2 in ICE ID-19 */
+
+ /* note: however, the user/pass in ID-19 is global, if the user/pass
+ * are set in the candidate here, it means they need to be updated...
+ * this is essential to overcome a race condition where we might receive
+ * a valid binding request from a valid candidate that wasn't yet added to
+ * our list of candidates.. this 'update' will make the peer-rflx a
+ * server-rflx/host candidate again */
+ if (username) {
+ if (candidate->username == NULL)
+ candidate->username = g_strdup (username);
+ else if (g_strcmp0 (username, candidate->username))
+ nice_debug ("Agent %p : Candidate username '%s' is not allowed "
+ "to change to '%s' now (ICE restart only).", agent,
+ candidate->username, username);
+ }
+ if (password) {
+ if (candidate->password == NULL)
+ candidate->password = g_strdup (password);
+ else if (g_strcmp0 (password, candidate->password))
+ nice_debug ("Agent %p : candidate password '%s' is not allowed "
+ "to change to '%s' now (ICE restart only).", agent,
+ candidate->password, password);
+ }
+
+ /* since the type of the existing candidate may have changed,
+ * the pairs priority and foundation related to this candidate need
+ * to be recomputed.
+ */
+ recalculate_pair_priorities (agent);
+ priv_update_pair_foundations (agent, stream_id, candidate);
+ }
+ else {
+ /* case 2: add a new candidate */
+
+ if (type == NICE_CANDIDATE_TYPE_PEER_REFLEXIVE) {
+ nice_debug("Agent %p : Warning: ignoring externally set peer-reflexive candidate!", agent);
+ return FALSE;
+ }
+ candidate = nice_candidate_new (type);
+ component->remote_candidates = g_slist_append (component->remote_candidates,
+ candidate);
+
+ candidate->stream_id = stream_id;
+ candidate->component_id = component_id;
+
+ candidate->type = type;
+ if (addr)
+ candidate->addr = *addr;
+
+ if (nice_debug_is_enabled ()) {
+ gchar tmpbuf[INET6_ADDRSTRLEN] = {0};
+ if (addr)
+ nice_address_to_string (addr, tmpbuf);
+ nice_debug ("Agent %p : Adding %s remote candidate with addr [%s]:%u"
+ " for s%d/c%d. U/P '%s'/'%s' prio: %u", agent,
+ _transport_to_string (transport), tmpbuf,
+ addr? nice_address_get_port (addr) : 0, stream_id, component_id,
+ username, password, priority);
+ }
+
+ if (NICE_AGENT_IS_COMPATIBLE_WITH_RFC5245_OR_OC2007R2 (agent)) {
+ /* note: If there are TCP candidates for a media stream,
+ * a controlling agent MUST use the regular selection algorithm,
+ * RFC 6544, sect 8, "Concluding ICE Processing"
+ */
+ if (agent->nomination_mode == NICE_NOMINATION_MODE_AGGRESSIVE &&
+ transport != NICE_CANDIDATE_TRANSPORT_UDP) {
+ nice_debug ("Agent %p : we have TCP candidates, switching back "
+ "to regular nomination mode", agent);
+ agent->nomination_mode = NICE_NOMINATION_MODE_REGULAR;
+ }
+ }
+
+ if (base_addr)
+ candidate->base_addr = *base_addr;
+
+ candidate->transport = transport;
+ candidate->priority = priority;
+ candidate->username = g_strdup (username);
+ candidate->password = g_strdup (password);
+
+ if (foundation)
+ g_strlcpy (candidate->foundation, foundation,
+ NICE_CANDIDATE_MAX_FOUNDATION);
+
+ /* We only create a pair when a candidate is new, and not when
+ * updating an existing one.
+ */
+ if (conn_check_add_for_candidate (agent, stream_id,
+ component, candidate) < 0)
+ goto errors;
+ }
+ return TRUE;
+
+errors:
+ nice_candidate_free (candidate);
+ return FALSE;
+}
+
+NICEAPI_EXPORT gboolean
+nice_agent_set_remote_credentials (
+ NiceAgent *agent,
+ guint stream_id,
+ const gchar *ufrag, const gchar *pwd)
+{
+ NiceStream *stream;
+ gboolean ret = FALSE;
+
+ g_return_val_if_fail (NICE_IS_AGENT (agent), FALSE);
+ g_return_val_if_fail (stream_id >= 1, FALSE);
+
+ agent_lock (agent);
+
+ stream = agent_find_stream (agent, stream_id);
+ /* note: oddly enough, ufrag and pwd can be empty strings */
+ if (stream && ufrag && pwd) {
+
+ g_strlcpy (stream->remote_ufrag, ufrag, NICE_STREAM_MAX_UFRAG);
+ g_strlcpy (stream->remote_password, pwd, NICE_STREAM_MAX_PWD);
+
+ conn_check_remote_credentials_set(agent, stream);
+
+ ret = TRUE;
+ goto done;
+ }
+
+ done:
+ agent_unlock_and_emit (agent);
+ return ret;
+}
+
+NICEAPI_EXPORT gboolean
+nice_agent_set_local_credentials (
+ NiceAgent *agent,
+ guint stream_id,
+ const gchar *ufrag,
+ const gchar *pwd)
+{
+ NiceStream *stream;
+ gboolean ret = FALSE;
+
+ g_return_val_if_fail (NICE_IS_AGENT (agent), FALSE);
+ g_return_val_if_fail (stream_id >= 1, FALSE);
+
+ agent_lock (agent);
+
+ stream = agent_find_stream (agent, stream_id);
+
+ /* note: oddly enough, ufrag and pwd can be empty strings */
+ if (stream && ufrag && pwd) {
+ g_strlcpy (stream->local_ufrag, ufrag, NICE_STREAM_MAX_UFRAG);
+ g_strlcpy (stream->local_password, pwd, NICE_STREAM_MAX_PWD);
+
+ ret = TRUE;
+ goto done;
+ }
+
+ done:
+ agent_unlock_and_emit (agent);
+ return ret;
+}
+
+
+NICEAPI_EXPORT gboolean
+nice_agent_get_local_credentials (
+ NiceAgent *agent,
+ guint stream_id,
+ gchar **ufrag, gchar **pwd)
+{
+ NiceStream *stream;
+ gboolean ret = TRUE;
+
+ g_return_val_if_fail (NICE_IS_AGENT (agent), FALSE);
+ g_return_val_if_fail (stream_id >= 1, FALSE);
+
+ agent_lock (agent);
+
+ stream = agent_find_stream (agent, stream_id);
+ if (stream == NULL) {
+ goto done;
+ }
+
+ if (!ufrag || !pwd) {
+ goto done;
+ }
+
+ *ufrag = g_strdup (stream->local_ufrag);
+ *pwd = g_strdup (stream->local_password);
+ ret = TRUE;
+
+ done:
+
+ agent_unlock_and_emit (agent);
+ return ret;
+}
+
+static int
+_set_remote_candidates_locked (NiceAgent *agent, NiceStream *stream,
+ NiceComponent *component, const GSList *candidates)
+{
+ const GSList *i;
+ int added = 0;
+
+ for (i = candidates; i && added >= 0; i = i->next) {
+ NiceCandidate *d = (NiceCandidate*) i->data;
+
+ if (nice_address_is_valid (&d->addr) == TRUE) {
+ gboolean res =
+ priv_add_remote_candidate (agent,
+ stream->id,
+ component->id,
+ d->type,
+ &d->addr,
+ &d->base_addr,
+ d->transport,
+ d->priority,
+ d->username,
+ d->password,
+ d->foundation);
+ if (res)
+ ++added;
+ }
+ }
+
+ if (added > 0) {
+ conn_check_remote_candidates_set(agent, stream, component);
+ conn_check_schedule_next (agent);
+ }
+
+ return added;
+}
+
+
+NICEAPI_EXPORT int
+nice_agent_set_remote_candidates (NiceAgent *agent, guint stream_id, guint component_id, const GSList *candidates)
+{
+ int added = 0;
+ NiceStream *stream;
+ NiceComponent *component;
+
+ g_return_val_if_fail (NICE_IS_AGENT (agent), 0);
+ g_return_val_if_fail (stream_id >= 1, 0);
+ g_return_val_if_fail (component_id >= 1, 0);
+
+ nice_debug ("Agent %p: set_remote_candidates %d %d", agent, stream_id, component_id);
+
+ agent_lock (agent);
+
+ if (!agent_find_component (agent, stream_id, component_id,
+ &stream, &component)) {
+ g_warning ("Could not find component %u in stream %u", component_id,
+ stream_id);
+ added = -1;
+ goto done;
+ }
+
+ added = _set_remote_candidates_locked (agent, stream, component, candidates);
+
+ done:
+ agent_unlock_and_emit (agent);
+
+ return added;
+}
+
+/* Return values for agent_recv_message_unlocked(). Needed purely because it
+ * must differentiate between RECV_OOB and RECV_SUCCESS. */
+typedef enum {
+ RECV_ERROR = -2,
+ RECV_WOULD_BLOCK = -1,
+ RECV_OOB = 0,
+ RECV_SUCCESS = 1,
+} RecvStatus;
+
+/*
+ * agent_recv_message_unlocked:
+ * @agent: a #NiceAgent
+ * @stream: the stream to receive from
+ * @component: the component to receive from
+ * @socket: the socket to receive on
+ * @message: the message to write into (must have at least 65536 bytes of buffer
+ * space)
+ *
+ * Receive a single message of data from the given @stream, @component and
+ * @socket tuple, in a non-blocking fashion. The caller must ensure that
+ * @message contains enough buffers to provide at least 65536 bytes of buffer
+ * space, but the buffers may be split as the caller sees fit.
+ *
+ * This must be called with the agent’s lock held.
+ *
+ * Returns: number of valid messages received on success (i.e. %RECV_SUCCESS or
+ * 1), %RECV_OOB if data was successfully received but was handled out-of-band
+ * (e.g. due to being a STUN control packet), %RECV_WOULD_BLOCK if no data is
+ * available and the call would block, or %RECV_ERROR on error
+ */
+static RecvStatus
+agent_recv_message_unlocked (
+ NiceAgent *agent,
+ NiceStream *stream,
+ NiceComponent *component,
+ NiceSocket *nicesock,
+ NiceInputMessage *message)
+{
+ NiceAddress from;
+ GList *item;
+ RecvStatus retval;
+ gint sockret;
+ gboolean is_turn = FALSE;
+
+ /* We need an address for packet parsing, below. */
+ if (message->from == NULL) {
+ message->from = &from;
+ }
+
+ /* ICE-TCP requires that all packets be framed with RFC4571 */
+ if (nice_socket_is_reliable (nicesock)) {
+ /* In the case of OC2007 and OC2007R2 which uses UDP TURN for TCP-ACTIVE
+ * and TCP-PASSIVE candidates, the recv_messages will be packetized and
+ * always return an entire frame, so we must read it as is */
+ if (nicesock->type == NICE_SOCKET_TYPE_UDP_TURN_OVER_TCP ||
+ nicesock->type == NICE_SOCKET_TYPE_UDP_TURN) {
+ GSList *cand_i;
+ GInputVector *local_bufs;
+ NiceInputMessage local_message;
+ guint n_bufs = 0;
+ guint16 rfc4571_frame;
+ guint i;
+
+ /* In case of ICE-TCP on UDP-TURN (OC2007 compat), we need to do the recv
+ * on the UDP_TURN socket, but it's possible we receive the source event
+ * on the UDP_TURN_OVER_TCP socket, so in that case, we need to replace
+ * the socket we do the recv on to the topmost socket
+ */
+ for (cand_i = component->local_candidates; cand_i; cand_i = cand_i->next) {
+ NiceCandidate *cand = cand_i->data;
+
+ if (cand->type == NICE_CANDIDATE_TYPE_RELAYED &&
+ cand->stream_id == stream->id &&
+ cand->component_id == component->id &&
+ nice_socket_is_based_on(cand->sockptr, nicesock)) {
+ nice_debug ("Agent %p : Packet received from a TURN socket.",
+ agent);
+ nicesock = cand->sockptr;
+ break;
+ }
+ }
+ /* Count the number of buffers. */
+ if (message->n_buffers == -1) {
+ for (i = 0; message->buffers[i].buffer != NULL; i++)
+ n_bufs++;
+ } else {
+ n_bufs = message->n_buffers;
+ }
+
+ local_bufs = g_alloca ((n_bufs + 1) * sizeof (GInputVector));
+ local_message.buffers = local_bufs;
+ local_message.n_buffers = n_bufs + 1;
+ local_message.from = message->from;
+ local_message.length = 0;
+
+ local_bufs[0].buffer = &rfc4571_frame;
+ local_bufs[0].size = sizeof (guint16);
+
+ for (i = 0; i < n_bufs; i++) {
+ local_bufs[i + 1].buffer = message->buffers[i].buffer;
+ local_bufs[i + 1].size = message->buffers[i].size;
+ }
+ sockret = nice_socket_recv_messages (nicesock, &local_message, 1);
+ if (sockret == 1 && local_message.length >= sizeof (guint16)) {
+ message->length = ntohs (rfc4571_frame);
+ }
+ } else {
+ if (nicesock->type == NICE_SOCKET_TYPE_TCP_PASSIVE) {
+ NiceSocket *new_socket;
+
+ /* Passive candidates when readable should accept and create a new
+ * socket. When established, the connchecks will create a peer reflexive
+ * candidate for it */
+ new_socket = nice_tcp_passive_socket_accept (nicesock);
+ if (new_socket) {
+ _priv_set_socket_tos (agent, new_socket, stream->tos);
+ nice_component_attach_socket (component, new_socket);
+ }
+ sockret = 0;
+ } else {
+ /* In the case of a real ICE-TCP connection, we can use the socket as a
+ * bytestream and do the read here with caching of data being read
+ */
+ gssize available = g_socket_get_available_bytes (nicesock->fileno);
+
+ /* TODO: Support bytestream reads */
+ message->length = 0;
+ sockret = 0;
+ if (available <= 0) {
+ sockret = available;
+
+ /* If we don't call check_connect_result on an outbound connection,
+ * then is_connected will always return FALSE. That's why we check
+ * both conditions to make sure g_socket_is_connected returns the
+ * correct result, otherwise we end up closing valid connections
+ */
+ if (g_socket_check_connect_result (nicesock->fileno, NULL) == FALSE ||
+ g_socket_is_connected (nicesock->fileno) == FALSE) {
+ /* If we receive a readable event on a TCP_BSD socket which is
+ * not connected, it means that it failed to connect, so we must
+ * return an error to make the socket fail/closed
+ */
+ sockret = -1;
+ } else {
+ gint flags = G_SOCKET_MSG_PEEK;
+
+ /* If available bytes are 0, but the socket is still considered
+ * connected, then either we're just trying to see if there's more
+ * data available or the peer closed the connection.
+ * The only way to know is to do a read, so we do here a peek and
+ * check the return value, if it's 0, it means the peer has closed
+ * the connection, so we must return an error instead of WOULD_BLOCK
+ */
+ if (g_socket_receive_message (nicesock->fileno, NULL,
+ NULL, 0, NULL, NULL, &flags, NULL, NULL) == 0)
+ sockret = -1;
+ }
+ } else if (agent->rfc4571_expecting_length == 0) {
+ if ((gsize) available >= sizeof(guint16)) {
+ guint16 rfc4571_frame;
+ GInputVector local_buf = { &rfc4571_frame, sizeof(guint16)};
+ NiceInputMessage local_message = { &local_buf, 1, message->from, 0};
+
+ sockret = nice_socket_recv_messages (nicesock, &local_message, 1);
+ if (sockret == 1 && local_message.length >= sizeof (guint16)) {
+ agent->rfc4571_expecting_length = ntohs (rfc4571_frame);
+ available = g_socket_get_available_bytes (nicesock->fileno);
+ }
+ }
+ }
+ if (agent->rfc4571_expecting_length > 0 &&
+ available >= agent->rfc4571_expecting_length) {
+ GInputVector *local_bufs;
+ NiceInputMessage local_message;
+ gsize off;
+ guint n_bufs = 0;
+ guint i;
+
+ /* Count the number of buffers. */
+ if (message->n_buffers == -1) {
+ for (i = 0; message->buffers[i].buffer != NULL; i++)
+ n_bufs++;
+ } else {
+ n_bufs = message->n_buffers;
+ }
+
+ local_bufs = g_alloca (n_bufs * sizeof (GInputVector));
+ local_message.buffers = local_bufs;
+ local_message.from = message->from;
+ local_message.length = 0;
+ local_message.n_buffers = 0;
+
+ /* Only read up to the expected number of bytes in the frame */
+ off = 0;
+ for (i = 0; i < n_bufs; i++) {
+ if (message->buffers[i].size < agent->rfc4571_expecting_length - off) {
+ local_bufs[i].buffer = message->buffers[i].buffer;
+ local_bufs[i].size = message->buffers[i].size;
+ local_message.n_buffers++;
+ off += message->buffers[i].size;
+ } else {
+ local_bufs[i].buffer = message->buffers[i].buffer;
+ local_bufs[i].size = MIN (message->buffers[i].size,
+ agent->rfc4571_expecting_length - off);
+ local_message.n_buffers++;
+ off += local_bufs[i].size;
+ }
+ }
+ sockret = nice_socket_recv_messages (nicesock, &local_message, 1);
+ if (sockret == 1) {
+ message->length = local_message.length;
+ agent->rfc4571_expecting_length -= local_message.length;
+ }
+ }
+ }
+ }
+ } else {
+ sockret = nice_socket_recv_messages (nicesock, message, 1);
+ }
+
+ if (sockret == 0) {
+ retval = RECV_WOULD_BLOCK; /* EWOULDBLOCK */
+ nice_debug_verbose ("%s: Agent %p: no message available on read attempt",
+ G_STRFUNC, agent);
+ goto done;
+ } else if (sockret < 0) {
+ nice_debug ("Agent %p: %s returned %d, errno (%d) : %s",
+ agent, G_STRFUNC, sockret, errno, g_strerror (errno));
+
+ retval = RECV_ERROR;
+ goto done;
+ } else {
+ retval = sockret;
+ }
+
+ g_assert (retval != RECV_OOB);
+ if (message->length == 0) {
+ retval = RECV_OOB;
+ nice_debug_verbose ("%s: Agent %p: message handled out-of-band", G_STRFUNC,
+ agent);
+ goto done;
+ }
+
+ if (nice_debug_is_verbose ()) {
+ gchar tmpbuf[INET6_ADDRSTRLEN];
+ nice_address_to_string (message->from, tmpbuf);
+ nice_debug_verbose ("%s: Agent %p : Packet received on local socket %p "
+ "(fd %d) from [%s]:%u (%" G_GSSIZE_FORMAT " octets).", G_STRFUNC, agent,
+ nicesock, nicesock->fileno ? g_socket_get_fd (nicesock->fileno) : -1, tmpbuf,
+ nice_address_get_port (message->from), message->length);
+ }
+
+ if (nicesock->type == NICE_SOCKET_TYPE_UDP_TURN)
+ is_turn = TRUE;
+
+ if (!is_turn && component->turn_candidate &&
+ nice_socket_is_based_on (component->turn_candidate->sockptr, nicesock) &&
+ nice_address_equal (message->from,
+ &component->turn_candidate->turn->server)) {
+ is_turn = TRUE;
+ retval = nice_udp_turn_socket_parse_recv_message (
+ component->turn_candidate->sockptr, &nicesock, message);
+ }
+
+ for (item = component->turn_servers; item && !is_turn;
+ item = g_list_next (item)) {
+ TurnServer *turn = item->data;
+ GSList *i = NULL;
+
+ if (!nice_address_equal (message->from, &turn->server))
+ continue;
+
+ nice_debug_verbose ("Agent %p : Packet received from TURN server candidate.",
+ agent);
+ is_turn = TRUE;
+
+ for (i = component->local_candidates; i; i = i->next) {
+ NiceCandidate *cand = i->data;
+
+ if (cand->type == NICE_CANDIDATE_TYPE_RELAYED &&
+ cand->turn == turn &&
+ cand->stream_id == stream->id &&
+ nice_socket_is_based_on (cand->sockptr, nicesock)) {
+ retval = nice_udp_turn_socket_parse_recv_message (cand->sockptr, &nicesock,
+ message);
+ break;
+ }
+ }
+ break;
+ }
+
+ if (agent->force_relay && !is_turn) {
+ /* Ignore messages not from TURN if TURN is required */
+ retval = RECV_WOULD_BLOCK; /* EWOULDBLOCK */
+ goto done;
+ }
+
+ if (retval == RECV_OOB)
+ goto done;
+
+ /* If the message’s stated length is equal to its actual length, it’s probably
+ * a STUN message; otherwise it’s probably data. */
+ if (stun_message_validate_buffer_length_fast (
+ (StunInputVector *) message->buffers, message->n_buffers, message->length,
+ (agent->compatibility != NICE_COMPATIBILITY_OC2007 &&
+ agent->compatibility != NICE_COMPATIBILITY_OC2007R2)) == (ssize_t) message->length) {
+ /* Slow path: If this message isn’t obviously *not* a STUN packet, compact
+ * its buffers
+ * into a single monolithic one and parse the packet properly. */
+ guint8 *big_buf;
+ gsize big_buf_len;
+ int validated_len;
+
+ big_buf = compact_input_message (message, &big_buf_len);
+
+ validated_len = stun_message_validate_buffer_length (big_buf, big_buf_len,
+ (agent->compatibility != NICE_COMPATIBILITY_OC2007 &&
+ agent->compatibility != NICE_COMPATIBILITY_OC2007R2));
+
+ if (validated_len == (gint) big_buf_len) {
+ gboolean handled;
+
+ handled =
+ conn_check_handle_inbound_stun (agent, stream, component, nicesock,
+ message->from, (gchar *) big_buf, big_buf_len);
+
+ if (handled) {
+ /* Handled STUN message. */
+ nice_debug ("%s: Valid STUN packet received.", G_STRFUNC);
+ retval = RECV_OOB;
+ g_free (big_buf);
+ agent->media_after_tick = TRUE;
+ goto done;
+ }
+ }
+
+ nice_debug ("%s: Packet passed fast STUN validation but failed "
+ "slow validation.", G_STRFUNC);
+
+ g_free (big_buf);
+ }
+
+ if (!nice_component_verify_remote_candidate (component,
+ message->from, nicesock)) {
+ if (nice_debug_is_verbose ()) {
+ gchar str[INET6_ADDRSTRLEN];
+
+ nice_address_to_string (message->from, str);
+ nice_debug_verbose ("Agent %p : %d:%d DROPPING packet from unknown source"
+ " %s:%d sock-type: %d", agent, stream->id, component->id, str,
+ nice_address_get_port (message->from), nicesock->type);
+ }
+
+ retval = RECV_OOB;
+ goto done;
+ }
+
+ agent->media_after_tick = TRUE;
+
+ /* Unhandled STUN; try handling TCP data, then pass to the client. */
+ if (message->length > 0 && agent->reliable) {
+ if (!nice_socket_is_reliable (nicesock) &&
+ !pseudo_tcp_socket_is_closed (component->tcp)) {
+ /* If we don’t yet have an underlying selected socket, queue up the
+ * incoming data to handle later. This is because we can’t send ACKs (or,
+ * more importantly for the first few packets, SYNACKs) without an
+ * underlying socket. We’d rather wait a little longer for a pair to be
+ * selected, then process the incoming packets and send out ACKs, than try
+ * to process them now, fail to send the ACKs, and incur a timeout in our
+ * pseudo-TCP state machine. */
+ if (component->selected_pair.local == NULL) {
+ GOutputVector *vec = g_slice_new (GOutputVector);
+ vec->buffer = compact_input_message (message, &vec->size);
+ g_queue_push_tail (&component->queued_tcp_packets, vec);
+ nice_debug ("%s: Queued %" G_GSSIZE_FORMAT " bytes for agent %p.",
+ G_STRFUNC, vec->size, agent);
+
+ return RECV_OOB;
+ } else {
+ process_queued_tcp_packets (agent, stream, component);
+ }
+
+ /* Received data on a reliable connection. */
+
+ nice_debug_verbose ("%s: notifying pseudo-TCP of packet, length %" G_GSIZE_FORMAT,
+ G_STRFUNC, message->length);
+ pseudo_tcp_socket_notify_message (component->tcp, message);
+
+ adjust_tcp_clock (agent, stream, component);
+
+ /* Success! Handled out-of-band. */
+ retval = RECV_OOB;
+ goto done;
+ } else if (pseudo_tcp_socket_is_closed (component->tcp)) {
+ nice_debug ("Received data on a pseudo tcp FAILED component. Ignoring.");
+
+ retval = RECV_OOB;
+ goto done;
+ }
+ }
+
+done:
+ /* Clear local modifications. */
+ if (message->from == &from) {
+ message->from = NULL;
+ }
+
+ return retval;
+}
+
+/* Print the composition of an array of messages. No-op if debugging is
+ * disabled. */
+static void
+nice_debug_input_message_composition (const NiceInputMessage *messages,
+ guint n_messages)
+{
+ guint i;
+
+ if (!nice_debug_is_verbose ())
+ return;
+
+ for (i = 0; i < n_messages; i++) {
+ const NiceInputMessage *message = &messages[i];
+ guint j;
+
+ nice_debug_verbose ("Message %p (from: %p, length: %" G_GSIZE_FORMAT ")", message,
+ message->from, message->length);
+
+ for (j = 0;
+ (message->n_buffers >= 0 && j < (guint) message->n_buffers) ||
+ (message->n_buffers < 0 && message->buffers[j].buffer != NULL);
+ j++) {
+ GInputVector *buffer = &message->buffers[j];
+
+ nice_debug_verbose ("\tBuffer %p (length: %" G_GSIZE_FORMAT ")", buffer->buffer,
+ buffer->size);
+ }
+ }
+}
+
+static guint8 *
+compact_message (const NiceOutputMessage *message, gsize buffer_length)
+{
+ guint8 *buffer;
+ gsize offset = 0;
+ guint i;
+
+ buffer = g_malloc (buffer_length);
+
+ for (i = 0;
+ (message->n_buffers >= 0 && i < (guint) message->n_buffers) ||
+ (message->n_buffers < 0 && message->buffers[i].buffer != NULL);
+ i++) {
+ gsize len = MIN (buffer_length - offset, message->buffers[i].size);
+ memcpy (buffer + offset, message->buffers[i].buffer, len);
+ offset += len;
+ }
+
+ return buffer;
+}
+
+/* Concatenate all the buffers in the given @recv_message into a single, newly
+ * allocated, monolithic buffer which is returned. The length of the new buffer
+ * is returned in @buffer_length, and should be equal to the length field of
+ * @recv_message.
+ *
+ * The return value must be freed with g_free(). */
+guint8 *
+compact_input_message (const NiceInputMessage *message, gsize *buffer_length)
+{
+ nice_debug_verbose ("%s: **WARNING: SLOW PATH**", G_STRFUNC);
+ nice_debug_input_message_composition (message, 1);
+
+ /* This works as long as NiceInputMessage is a subset of eNiceOutputMessage */
+
+ *buffer_length = message->length;
+
+ return compact_message ((NiceOutputMessage *) message, *buffer_length);
+}
+
+/* Returns the number of bytes copied. Silently drops any data from @buffer
+ * which doesn’t fit in @message. */
+gsize
+memcpy_buffer_to_input_message (NiceInputMessage *message,
+ const guint8 *buffer, gsize buffer_length)
+{
+ guint i;
+
+ nice_debug_verbose ("%s: **WARNING: SLOW PATH**", G_STRFUNC);
+
+ message->length = 0;
+
+ for (i = 0;
+ buffer_length > 0 &&
+ ((message->n_buffers >= 0 && i < (guint) message->n_buffers) ||
+ (message->n_buffers < 0 && message->buffers[i].buffer != NULL));
+ i++) {
+ gsize len;
+
+ len = MIN (message->buffers[i].size, buffer_length);
+ memcpy (message->buffers[i].buffer, buffer, len);
+
+ buffer += len;
+ buffer_length -= len;
+
+ message->length += len;
+ }
+
+ nice_debug_input_message_composition (message, 1);
+
+ if (buffer_length > 0) {
+ g_warning ("Dropped %" G_GSIZE_FORMAT " bytes of data from the end of "
+ "buffer %p (length: %" G_GSIZE_FORMAT ") due to not fitting in "
+ "message %p", buffer_length, buffer - message->length,
+ message->length + buffer_length, message);
+ }
+
+ return message->length;
+}
+
+/* Concatenate all the buffers in the given @message into a single, newly
+ * allocated, monolithic buffer which is returned. The length of the new buffer
+ * is returned in @buffer_length, and should be equal to the length field of
+ * @recv_message.
+ *
+ * The return value must be freed with g_free(). */
+guint8 *
+compact_output_message (const NiceOutputMessage *message, gsize *buffer_length)
+{
+ nice_debug ("%s: **WARNING: SLOW PATH**", G_STRFUNC);
+
+ *buffer_length = output_message_get_size (message);
+
+ return compact_message (message, *buffer_length);
+}
+
+gsize
+output_message_get_size (const NiceOutputMessage *message)
+{
+ guint i;
+ gsize message_len = 0;
+
+ /* Find the total size of the message */
+ for (i = 0;
+ (message->n_buffers >= 0 && i < (guint) message->n_buffers) ||
+ (message->n_buffers < 0 && message->buffers[i].buffer != NULL);
+ i++)
+ message_len += message->buffers[i].size;
+
+ return message_len;
+}
+
+gsize
+input_message_get_size (const NiceInputMessage *message)
+{
+ guint i;
+ gsize message_len = 0;
+
+ /* Find the total size of the message */
+ for (i = 0;
+ (message->n_buffers >= 0 && i < (guint) message->n_buffers) ||
+ (message->n_buffers < 0 && message->buffers[i].buffer != NULL);
+ i++)
+ message_len += message->buffers[i].size;
+
+ return message_len;
+}
+
+/*
+ * nice_input_message_iter_reset:
+ * @iter: a #NiceInputMessageIter
+ *
+ * Reset the given @iter to point to the beginning of the array of messages.
+ * This may be used both to initialise it and to reset it after use.
+ *
+ * Since: 0.1.5
+ */
+void
+nice_input_message_iter_reset (NiceInputMessageIter *iter)
+{
+ iter->message = 0;
+ iter->buffer = 0;
+ iter->offset = 0;
+}
+
+/*
+ * nice_input_message_iter_is_at_end:
+ * @iter: a #NiceInputMessageIter
+ * @messages: (array length=n_messages): an array of #NiceInputMessages
+ * @n_messages: number of entries in @messages
+ *
+ * Determine whether @iter points to the end of the given @messages array. If it
+ * does, the array is full: every buffer in every message is full of valid
+ * bytes.
+ *
+ * Returns: %TRUE if the messages’ buffers are full, %FALSE otherwise
+ *
+ * Since: 0.1.5
+ */
+gboolean
+nice_input_message_iter_is_at_end (NiceInputMessageIter *iter,
+ NiceInputMessage *messages, guint n_messages)
+{
+ return (iter->message == n_messages &&
+ iter->buffer == 0 && iter->offset == 0);
+}
+
+/*
+ * nice_input_message_iter_get_n_valid_messages:
+ * @iter: a #NiceInputMessageIter
+ *
+ * Calculate the number of valid messages in the messages array. A valid message
+ * is one which contains at least one valid byte of data in its buffers.
+ *
+ * Returns: number of valid messages (may be zero)
+ *
+ * Since: 0.1.5
+ */
+guint
+nice_input_message_iter_get_n_valid_messages (NiceInputMessageIter *iter)
+{
+ if (iter->buffer == 0 && iter->offset == 0)
+ return iter->message;
+ else
+ return iter->message + 1;
+}
+
+/**
+ * nice_input_message_iter_compare:
+ * @a: a #NiceInputMessageIter
+ * @b: another #NiceInputMessageIter
+ *
+ * Compare two #NiceInputMessageIters for equality, returning %TRUE if they
+ * point to the same place in the receive message array.
+ *
+ * Returns: %TRUE if the iters match, %FALSE otherwise
+ *
+ * Since: 0.1.5
+ */
+gboolean
+nice_input_message_iter_compare (const NiceInputMessageIter *a,
+ const NiceInputMessageIter *b)
+{
+ return (a->message == b->message && a->buffer == b->buffer && a->offset == b->offset);
+}
+
+/* Will fill up @messages from the first free byte onwards (as determined using
+ * @iter). This may be used in reliable or non-reliable mode; in non-reliable
+ * mode it will always increment the message index after each buffer is
+ * consumed.
+ *
+ * Updates @iter in place. No errors can occur.
+ *
+ * Returns the number of valid messages in @messages on success (which may be
+ * zero if reading into the first buffer of the message would have blocked).
+ *
+ * Must be called with the io_mutex held. */
+static gint
+pending_io_messages_recv_messages (NiceComponent *component, gboolean reliable,
+ NiceInputMessage *messages, guint n_messages, NiceInputMessageIter *iter)
+{
+ gsize len;
+ IOCallbackData *data;
+ NiceInputMessage *message = &messages[iter->message];
+
+ g_assert (component->io_callback_id == 0);
+
+ data = g_queue_peek_head (&component->pending_io_messages);
+ if (data == NULL)
+ goto done;
+
+ if (iter->buffer == 0 && iter->offset == 0) {
+ message->length = 0;
+ }
+
+ for (;
+ (message->n_buffers >= 0 && iter->buffer < (guint) message->n_buffers) ||
+ (message->n_buffers < 0 && message->buffers[iter->buffer].buffer != NULL);
+ iter->buffer++) {
+ GInputVector *buffer = &message->buffers[iter->buffer];
+
+ do {
+ len = MIN (data->buf_len - data->offset, buffer->size - iter->offset);
+ memcpy ((guint8 *) buffer->buffer + iter->offset,
+ data->buf + data->offset, len);
+
+ nice_debug ("%s: Unbuffered %" G_GSIZE_FORMAT " bytes into "
+ "buffer %p (offset %" G_GSIZE_FORMAT ", length %" G_GSIZE_FORMAT
+ ").", G_STRFUNC, len, buffer->buffer, iter->offset, buffer->size);
+
+ message->length += len;
+ iter->offset += len;
+ data->offset += len;
+ } while (iter->offset < buffer->size);
+
+ iter->offset = 0;
+ }
+
+ /* Only if we managed to consume the whole buffer should it be popped off the
+ * queue; otherwise we’ll have another go at it later. */
+ if (data->offset == data->buf_len) {
+ g_queue_pop_head (&component->pending_io_messages);
+ io_callback_data_free (data);
+
+ /* If we’ve consumed an entire message from pending_io_messages, and
+ * are in non-reliable mode, move on to the next message in
+ * @messages. */
+ if (!reliable) {
+ iter->offset = 0;
+ iter->buffer = 0;
+ iter->message++;
+ }
+ }
+
+done:
+ return nice_input_message_iter_get_n_valid_messages (iter);
+}
+
+static gboolean
+nice_agent_recv_cancelled_cb (GCancellable *cancellable, gpointer user_data)
+{
+ GError **error = user_data;
+
+ if (error && !*error)
+ g_cancellable_set_error_if_cancelled (cancellable, error);
+ return G_SOURCE_REMOVE;
+}
+
+static gint
+nice_agent_recv_messages_blocking_or_nonblocking (NiceAgent *agent,
+ guint stream_id, guint component_id, gboolean blocking,
+ NiceInputMessage *messages, guint n_messages,
+ GCancellable *cancellable, GError **error)
+{
+ GMainContext *context;
+ NiceStream *stream;
+ NiceComponent *component;
+ gint n_valid_messages = -1;
+ GSource *cancellable_source = NULL;
+ gboolean received_enough = FALSE, error_reported = FALSE;
+ gboolean all_sockets_would_block = FALSE;
+ gboolean reached_eos = FALSE;
+ GError *child_error = NULL;
+ NiceInputMessage *messages_orig = NULL;
+ guint i;
+
+ g_return_val_if_fail (NICE_IS_AGENT (agent), -1);
+ g_return_val_if_fail (stream_id >= 1, -1);
+ g_return_val_if_fail (component_id >= 1, -1);
+ g_return_val_if_fail (n_messages == 0 || messages != NULL, -1);
+ g_return_val_if_fail (
+ cancellable == NULL || G_IS_CANCELLABLE (cancellable), -1);
+ g_return_val_if_fail (error == NULL || *error == NULL, -1);
+
+ if (n_messages == 0)
+ return 0;
+
+ if (n_messages > G_MAXINT) {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ "The number of messages can't exceed G_MAXINT: %d", G_MAXINT);
+ return -1;
+ }
+
+ /* Receive buffer size must be at least 1280 for STUN */
+ if (!agent->reliable) {
+ for (i = 0; i < n_messages; i++) {
+ if (input_message_get_size (&messages[i]) < 1280) {
+ GInputVector *vec;
+
+ if (messages_orig == NULL)
+ messages_orig = g_memdup (messages,
+ sizeof (NiceInputMessage) * n_messages);
+ vec = g_slice_new (GInputVector);
+ vec->buffer = g_slice_alloc (1280);
+ vec->size = 1280;
+ messages[i].buffers = vec;
+ messages[i].n_buffers = 1;
+ }
+ }
+ }
+
+ agent_lock (agent);
+
+ if (!agent_find_component (agent, stream_id, component_id,
+ &stream, &component)) {
+ g_set_error (&child_error, G_IO_ERROR, G_IO_ERROR_BROKEN_PIPE,
+ "Invalid stream/component.");
+ goto done;
+ }
+
+ nice_debug_verbose ("%s: %p: (%s):", G_STRFUNC, agent,
+ blocking ? "blocking" : "non-blocking");
+ nice_debug_input_message_composition (messages, n_messages);
+
+ /* Disallow re-entrant reads. */
+ g_assert (component->n_recv_messages == 0 &&
+ component->recv_messages == NULL);
+
+ /* Set the component’s receive buffer. */
+ context = nice_component_dup_io_context (component);
+ nice_component_set_io_callback (component, NULL, NULL, messages, n_messages,
+ &child_error);
+
+ /* Add the cancellable as a source. */
+ if (cancellable != NULL) {
+ cancellable_source = g_cancellable_source_new (cancellable);
+ g_source_set_callback (cancellable_source,
+ (GSourceFunc) G_CALLBACK (nice_agent_recv_cancelled_cb), &child_error,
+ NULL);
+ g_source_attach (cancellable_source, context);
+ }
+
+ /* Is there already pending data left over from having an I/O callback
+ * attached and switching to using nice_agent_recv()? This is a horrifically
+ * specific use case which I hope nobody ever tries. And yet, it still must be
+ * supported. */
+ g_mutex_lock (&component->io_mutex);
+
+ while (!received_enough &&
+ !g_queue_is_empty (&component->pending_io_messages)) {
+ pending_io_messages_recv_messages (component, agent->reliable,
+ component->recv_messages, component->n_recv_messages,
+ &component->recv_messages_iter);
+
+ nice_debug_verbose ("%s: %p: Received %d valid messages from pending I/O buffer.",
+ G_STRFUNC, agent,
+ nice_input_message_iter_get_n_valid_messages (
+ &component->recv_messages_iter));
+
+ received_enough =
+ nice_input_message_iter_is_at_end (&component->recv_messages_iter,
+ component->recv_messages, component->n_recv_messages);
+ }
+
+ g_mutex_unlock (&component->io_mutex);
+
+ /* For a reliable stream, grab any data from the pseudo-TCP input buffer
+ * before trying the sockets. */
+ if (agent->reliable &&
+ pseudo_tcp_socket_get_available_bytes (component->tcp) > 0) {
+ pseudo_tcp_socket_recv_messages (component->tcp,
+ component->recv_messages, component->n_recv_messages,
+ &component->recv_messages_iter, &child_error);
+ adjust_tcp_clock (agent, stream, component);
+
+ nice_debug_verbose ("%s: %p: Received %d valid messages from pseudo-TCP read "
+ "buffer.", G_STRFUNC, agent,
+ nice_input_message_iter_get_n_valid_messages (
+ &component->recv_messages_iter));
+
+ received_enough =
+ nice_input_message_iter_is_at_end (&component->recv_messages_iter,
+ component->recv_messages, component->n_recv_messages);
+ error_reported = (child_error != NULL);
+ }
+
+ /* Each iteration of the main context will either receive some data, a
+ * cancellation error or a socket error. In non-reliable mode, the iter’s
+ * @message counter will be incremented after each read.
+ *
+ * In blocking, reliable mode, iterate the loop enough to fill exactly
+ * @n_messages messages. In blocking, non-reliable mode, iterate the loop to
+ * receive @n_messages messages (which may not fill all the buffers). In
+ * non-blocking mode, stop iterating the loop if all sockets would block (i.e.
+ * if no data was received for an iteration; in which case @child_error will
+ * be set to %G_IO_ERROR_WOULD_BLOCK).
+ */
+ while (!received_enough && !error_reported && !all_sockets_would_block &&
+ !reached_eos) {
+ NiceInputMessageIter prev_recv_messages_iter;
+
+ g_clear_error (&child_error);
+ memcpy (&prev_recv_messages_iter, &component->recv_messages_iter,
+ sizeof (NiceInputMessageIter));
+
+ agent_unlock (agent);
+ g_main_context_iteration (context, blocking);
+ agent_lock (agent);
+
+ if (!agent_find_component (agent, stream_id, component_id,
+ &stream, &component)) {
+ g_clear_error (&child_error);
+ g_set_error (&child_error, G_IO_ERROR, G_IO_ERROR_BROKEN_PIPE,
+ "Component removed during call.");
+
+ component = NULL;
+
+ goto recv_error;
+ }
+
+ received_enough =
+ nice_input_message_iter_is_at_end (&component->recv_messages_iter,
+ component->recv_messages, component->n_recv_messages);
+ error_reported = (child_error != NULL &&
+ !g_error_matches (child_error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK));
+ reached_eos = (agent->reliable &&
+ pseudo_tcp_socket_is_closed_remotely (component->tcp) &&
+ nice_input_message_iter_compare (&prev_recv_messages_iter,
+ &component->recv_messages_iter));
+ all_sockets_would_block = (!blocking && !reached_eos &&
+ nice_input_message_iter_compare (&prev_recv_messages_iter,
+ &component->recv_messages_iter));
+ }
+
+ n_valid_messages =
+ nice_input_message_iter_get_n_valid_messages (
+ &component->recv_messages_iter); /* grab before resetting the iter */
+
+ nice_component_set_io_callback (component, NULL, NULL, NULL, 0, NULL);
+
+recv_error:
+ /* Tidy up. Below this point, @component may be %NULL. */
+ if (cancellable_source != NULL) {
+ g_source_destroy (cancellable_source);
+ g_source_unref (cancellable_source);
+ }
+
+ g_main_context_unref (context);
+
+ /* Handle errors and cancellations. */
+ if (child_error != NULL) {
+ n_valid_messages = -1;
+ } else if (n_valid_messages == 0 && all_sockets_would_block) {
+ g_set_error_literal (&child_error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK,
+ g_strerror (EAGAIN));
+ n_valid_messages = -1;
+ }
+
+ nice_debug_verbose ("%s: %p: n_valid_messages: %d, n_messages: %u", G_STRFUNC, agent,
+ n_valid_messages, n_messages);
+
+done:
+ g_assert ((child_error != NULL) == (n_valid_messages == -1));
+ g_assert (n_valid_messages < 0 || (guint) n_valid_messages <= n_messages);
+ g_assert (n_valid_messages != 0 || reached_eos);
+
+ if (child_error != NULL)
+ g_propagate_error (error, child_error);
+
+ agent_unlock_and_emit (agent);
+
+ if (messages_orig) {
+ for (i = 0; i < n_messages; i++) {
+ if (messages[i].buffers != messages_orig[i].buffers) {
+ g_assert_cmpint (messages[i].n_buffers, ==, 1);
+
+ memcpy_buffer_to_input_message (&messages_orig[i],
+ messages[i].buffers[0].buffer, messages[i].length);
+
+ g_slice_free1 (1280, messages[i].buffers[0].buffer);
+ g_slice_free (GInputVector, messages[i].buffers);
+
+ messages[i].buffers = messages_orig[i].buffers;
+ messages[i].n_buffers = messages_orig[i].n_buffers;
+ messages[i].length = messages_orig[i].length;
+ }
+ }
+ g_free (messages_orig);
+ }
+
+ return n_valid_messages;
+}
+
+NICEAPI_EXPORT gint
+nice_agent_recv_messages (NiceAgent *agent, guint stream_id, guint component_id,
+ NiceInputMessage *messages, guint n_messages, GCancellable *cancellable,
+ GError **error)
+{
+ return nice_agent_recv_messages_blocking_or_nonblocking (agent, stream_id,
+ component_id, TRUE, messages, n_messages, cancellable, error);
+}
+
+NICEAPI_EXPORT gssize
+nice_agent_recv (NiceAgent *agent, guint stream_id, guint component_id,
+ guint8 *buf, gsize buf_len, GCancellable *cancellable, GError **error)
+{
+ gint n_valid_messages;
+ GInputVector local_bufs = { buf, buf_len };
+ NiceInputMessage local_messages = { &local_bufs, 1, NULL, 0 };
+
+ g_return_val_if_fail (NICE_IS_AGENT (agent), -1);
+ g_return_val_if_fail (stream_id >= 1, -1);
+ g_return_val_if_fail (component_id >= 1, -1);
+ g_return_val_if_fail (buf != NULL || buf_len == 0, -1);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), -1);
+ g_return_val_if_fail (error == NULL || *error == NULL, -1);
+
+ if (buf_len > G_MAXSSIZE) {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ "The buffer length can't exceed G_MAXSSIZE: %" G_GSSIZE_FORMAT,
+ G_MAXSSIZE);
+ return -1;
+ }
+
+ n_valid_messages = nice_agent_recv_messages (agent, stream_id, component_id,
+ &local_messages, 1, cancellable, error);
+
+ if (n_valid_messages <= 0)
+ return n_valid_messages;
+
+ return local_messages.length;
+}
+
+NICEAPI_EXPORT gint
+nice_agent_recv_messages_nonblocking (NiceAgent *agent, guint stream_id,
+ guint component_id, NiceInputMessage *messages, guint n_messages,
+ GCancellable *cancellable, GError **error)
+{
+ return nice_agent_recv_messages_blocking_or_nonblocking (agent, stream_id,
+ component_id, FALSE, messages, n_messages, cancellable, error);
+}
+
+NICEAPI_EXPORT gssize
+nice_agent_recv_nonblocking (NiceAgent *agent, guint stream_id,
+ guint component_id, guint8 *buf, gsize buf_len, GCancellable *cancellable,
+ GError **error)
+{
+ gint n_valid_messages;
+ GInputVector local_bufs = { buf, buf_len };
+ NiceInputMessage local_messages = { &local_bufs, 1, NULL, 0 };
+
+ g_return_val_if_fail (NICE_IS_AGENT (agent), -1);
+ g_return_val_if_fail (stream_id >= 1, -1);
+ g_return_val_if_fail (component_id >= 1, -1);
+ g_return_val_if_fail (buf != NULL || buf_len == 0, -1);
+ g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), -1);
+ g_return_val_if_fail (error == NULL || *error == NULL, -1);
+
+ if (buf_len > G_MAXSSIZE) {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ "The buffer length can't exceed G_MAXSSIZE: %" G_GSSIZE_FORMAT,
+ G_MAXSSIZE);
+ return -1;
+ }
+
+ n_valid_messages = nice_agent_recv_messages_nonblocking (agent, stream_id,
+ component_id, &local_messages, 1, cancellable, error);
+
+ if (n_valid_messages <= 0)
+ return n_valid_messages;
+
+ return local_messages.length;
+}
+
+/* nice_agent_send_messages_nonblocking_internal:
+ *
+ * Returns: number of bytes sent if allow_partial is %TRUE, the number
+ * of messages otherwise.
+ */
+
+static gint
+nice_agent_send_messages_nonblocking_internal (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ const NiceOutputMessage *messages,
+ guint n_messages,
+ gboolean allow_partial,
+ GError **error)
+{
+ NiceStream *stream;
+ NiceComponent *component;
+ gint n_sent = -1; /* is in bytes if allow_partial is TRUE,
+ otherwise in messages */
+ GError *child_error = NULL;
+
+ g_assert (n_messages == 1 || !allow_partial);
+
+ agent_lock (agent);
+
+ if (!agent_find_component (agent, stream_id, component_id,
+ &stream, &component)) {
+ g_set_error (&child_error, G_IO_ERROR, G_IO_ERROR_BROKEN_PIPE,
+ "Invalid stream/component.");
+ goto done;
+ }
+
+ /* FIXME: Cancellation isn’t yet supported, but it doesn’t matter because
+ * we only deal with non-blocking writes. */
+ if (component->selected_pair.local != NULL) {
+ if (nice_debug_is_enabled ()) {
+ gchar tmpbuf[INET6_ADDRSTRLEN];
+ nice_address_to_string (&component->selected_pair.remote->addr, tmpbuf);
+
+ nice_debug_verbose ("Agent %p : s%d:%d: sending %u messages to "
+ "[%s]:%d", agent, stream_id, component_id, n_messages, tmpbuf,
+ nice_address_get_port (&component->selected_pair.remote->addr));
+ }
+
+ if(agent->reliable &&
+ !nice_socket_is_reliable (component->selected_pair.local->sockptr)) {
+ if (!pseudo_tcp_socket_is_closed (component->tcp)) {
+ /* Send on the pseudo-TCP socket. */
+ n_sent = pseudo_tcp_socket_send_messages (component->tcp, messages,
+ n_messages, allow_partial, &child_error);
+ adjust_tcp_clock (agent, stream, component);
+
+ if (!pseudo_tcp_socket_can_send (component->tcp))
+ g_cancellable_reset (component->tcp_writable_cancellable);
+ if (n_sent < 0 && !g_error_matches (child_error, G_IO_ERROR,
+ G_IO_ERROR_WOULD_BLOCK)) {
+ /* Signal errors */
+ priv_pseudo_tcp_error (agent, component);
+ }
+ } else {
+ g_set_error (&child_error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Pseudo-TCP socket not connected.");
+ }
+ } else {
+ NiceSocket *sock;
+ NiceAddress *addr;
+
+ sock = component->selected_pair.local->sockptr;
+ addr = &component->selected_pair.remote->addr;
+
+ if (nice_socket_is_reliable (sock)) {
+ guint i;
+
+ /* ICE-TCP requires that all packets be framed with RFC4571 */
+ n_sent = 0;
+ for (i = 0; i < n_messages; i++) {
+ const NiceOutputMessage *message = &messages[i];
+ gsize message_len = output_message_get_size (message);
+ gsize offset = 0;
+ gsize current_offset = 0;
+ gsize offset_in_buffer = 0;
+ gint n_sent_framed;
+ GOutputVector *local_bufs;
+ NiceOutputMessage local_message;
+ guint j;
+ guint n_bufs = 0;
+
+ /* Count the number of buffers. */
+ if (message->n_buffers == -1) {
+ for (j = 0; message->buffers[j].buffer != NULL; j++)
+ n_bufs++;
+ } else {
+ n_bufs = message->n_buffers;
+ }
+
+ local_bufs = g_malloc_n (n_bufs + 1, sizeof (GOutputVector));
+ local_message.buffers = local_bufs;
+
+ while (message_len > 0) {
+ guint16 packet_len;
+ guint16 rfc4571_frame;
+
+ /* Split long messages into 62KB packets, leaving enough space
+ * for TURN overhead as well */
+ if (message_len > 0xF800)
+ packet_len = 0xF800;
+ else
+ packet_len = (guint16) message_len;
+ message_len -= packet_len;
+ rfc4571_frame = htons (packet_len);
+
+ local_bufs[0].buffer = &rfc4571_frame;
+ local_bufs[0].size = sizeof (guint16);
+
+ local_message.n_buffers = 1;
+ /* If we had to split the message, we need to find which buffer
+ * to start copying from and our offset within that buffer */
+ offset_in_buffer = 0;
+ current_offset = 0;
+ for (j = 0; j < n_bufs; j++) {
+ if (message->buffers[j].size < offset - current_offset) {
+ current_offset += message->buffers[j].size;
+ continue;
+ } else {
+ offset_in_buffer = offset - current_offset;
+ current_offset = offset;
+ break;
+ }
+ }
+
+ /* Keep j position in array and start copying from there */
+ for (; j < n_bufs; j++) {
+ local_bufs[local_message.n_buffers].buffer =
+ ((guint8 *) message->buffers[j].buffer) + offset_in_buffer;
+ local_bufs[local_message.n_buffers].size =
+ MIN (message->buffers[j].size, packet_len);
+ packet_len -= local_bufs[local_message.n_buffers].size;
+ offset += local_bufs[local_message.n_buffers++].size;
+ offset_in_buffer = 0;
+ }
+
+ /* If we sent part of the message already, then send the rest
+ * reliably so the message is sent as a whole even if it's split */
+ if (current_offset == 0)
+ n_sent_framed = nice_socket_send_messages (sock, addr,
+ &local_message, 1);
+ else
+ n_sent_framed = nice_socket_send_messages_reliable (sock, addr,
+ &local_message, 1);
+
+ if (component->tcp_writable_cancellable &&
+ !nice_socket_can_send (sock, addr))
+ g_cancellable_reset (component->tcp_writable_cancellable);
+
+ if (n_sent_framed < 0 && n_sent == 0)
+ n_sent = n_sent_framed;
+ if (n_sent_framed != 1)
+ break;
+ /* This is the last split frame, increment n_sent */
+ if (message_len == 0)
+ n_sent ++;
+ }
+ g_free (local_bufs);
+ }
+
+ } else {
+ n_sent = nice_socket_send_messages (sock, addr, messages, n_messages);
+ }
+
+ if (n_sent < 0) {
+ g_set_error (&child_error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Error writing data to socket.");
+ } else if (n_sent > 0 && allow_partial) {
+ g_assert (n_messages == 1);
+ n_sent = output_message_get_size (messages);
+ }
+ }
+ } else {
+ /* Socket isn’t properly open yet. */
+ n_sent = 0; /* EWOULDBLOCK */
+ }
+
+ /* Handle errors and cancellations. */
+ if (n_sent == 0) {
+ g_set_error_literal (&child_error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK,
+ g_strerror (EAGAIN));
+ n_sent = -1;
+ }
+
+ nice_debug_verbose ("%s: n_sent: %d, n_messages: %u", G_STRFUNC,
+ n_sent, n_messages);
+
+done:
+ g_assert ((child_error != NULL) == (n_sent == -1));
+ g_assert (n_sent != 0);
+ g_assert (n_sent < 0 ||
+ (!allow_partial && (guint) n_sent <= n_messages) ||
+ (allow_partial && n_messages == 1 &&
+ (gsize) n_sent <= output_message_get_size (&messages[0])));
+
+ if (child_error != NULL)
+ g_propagate_error (error, child_error);
+
+ agent_unlock_and_emit (agent);
+
+ return n_sent;
+}
+
+NICEAPI_EXPORT gint
+nice_agent_send_messages_nonblocking (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ const NiceOutputMessage *messages,
+ guint n_messages,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_return_val_if_fail (NICE_IS_AGENT (agent), -1);
+ g_return_val_if_fail (stream_id >= 1, -1);
+ g_return_val_if_fail (component_id >= 1, -1);
+ g_return_val_if_fail (n_messages == 0 || messages != NULL, -1);
+ g_return_val_if_fail (
+ cancellable == NULL || G_IS_CANCELLABLE (cancellable), -1);
+ g_return_val_if_fail (error == NULL || *error == NULL, -1);
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, error))
+ return -1;
+
+ return nice_agent_send_messages_nonblocking_internal (agent, stream_id,
+ component_id, messages, n_messages, FALSE, error);
+}
+
+NICEAPI_EXPORT gint
+nice_agent_send (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ guint len,
+ const gchar *buf)
+{
+ GOutputVector local_buf = { buf, len };
+ NiceOutputMessage local_message = { &local_buf, 1 };
+ gint n_sent_bytes;
+
+ g_return_val_if_fail (NICE_IS_AGENT (agent), -1);
+ g_return_val_if_fail (stream_id >= 1, -1);
+ g_return_val_if_fail (component_id >= 1, -1);
+ g_return_val_if_fail (buf != NULL, -1);
+
+ n_sent_bytes = nice_agent_send_messages_nonblocking_internal (agent,
+ stream_id, component_id, &local_message, 1, TRUE, NULL);
+
+ return n_sent_bytes;
+}
+
+NICEAPI_EXPORT GSList *
+nice_agent_get_local_candidates (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id)
+{
+ NiceComponent *component;
+ GSList * ret = NULL;
+ GSList * item = NULL;
+
+ g_return_val_if_fail (NICE_IS_AGENT (agent), NULL);
+ g_return_val_if_fail (stream_id >= 1, NULL);
+ g_return_val_if_fail (component_id >= 1, NULL);
+
+ agent_lock (agent);
+
+ if (!agent_find_component (agent, stream_id, component_id, NULL, &component)) {
+ goto done;
+ }
+
+ for (item = component->local_candidates; item; item = item->next) {
+ NiceCandidate *cand = item->data;
+
+ if (agent->force_relay && cand->type != NICE_CANDIDATE_TYPE_RELAYED)
+ continue;
+
+ ret = g_slist_append (ret, nice_candidate_copy (cand));
+ }
+
+ done:
+ agent_unlock_and_emit (agent);
+ return ret;
+}
+
+
+NICEAPI_EXPORT GSList *
+nice_agent_get_remote_candidates (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id)
+{
+ NiceComponent *component;
+ GSList *ret = NULL, *item = NULL;
+
+ g_return_val_if_fail (NICE_IS_AGENT (agent), NULL);
+ g_return_val_if_fail (stream_id >= 1, NULL);
+ g_return_val_if_fail (component_id >= 1, NULL);
+
+ agent_lock (agent);
+ if (!agent_find_component (agent, stream_id, component_id, NULL, &component))
+ {
+ goto done;
+ }
+
+ for (item = component->remote_candidates; item; item = item->next)
+ ret = g_slist_append (ret, nice_candidate_copy (item->data));
+
+ done:
+ agent_unlock_and_emit (agent);
+ return ret;
+}
+
+gboolean
+nice_agent_restart (
+ NiceAgent *agent)
+{
+ GSList *i;
+
+ agent_lock (agent);
+
+ /* step: regenerate tie-breaker value */
+ priv_generate_tie_breaker (agent);
+
+ /* step: reset controlling mode from the property value */
+ agent->controlling_mode = agent->saved_controlling_mode;
+ nice_debug ("Agent %p : ICE restart, reset role to \"%s\".",
+ agent, agent->controlling_mode ? "controlling" : "controlled");
+
+ for (i = agent->streams; i; i = i->next) {
+ NiceStream *stream = i->data;
+
+ /* step: reset local credentials for the stream and
+ * clean up the list of remote candidates */
+ nice_stream_restart (stream, agent);
+ }
+
+ agent_unlock_and_emit (agent);
+ return TRUE;
+}
+
+gboolean
+nice_agent_restart_stream (
+ NiceAgent *agent,
+ guint stream_id)
+{
+ gboolean res = FALSE;
+ NiceStream *stream;
+
+ agent_lock (agent);
+
+ stream = agent_find_stream (agent, stream_id);
+ if (!stream) {
+ g_warning ("Could not find stream %u", stream_id);
+ goto done;
+ }
+
+ /* step: reset local credentials for the stream and
+ * clean up the list of remote candidates */
+ nice_stream_restart (stream, agent);
+
+ res = TRUE;
+ done:
+ agent_unlock_and_emit (agent);
+ return res;
+}
+
+
+static void
+nice_agent_dispose (GObject *object)
+{
+ GSList *i;
+ QueuedSignal *sig;
+ NiceAgent *agent = NICE_AGENT (object);
+
+ agent_lock (agent);
+
+ /* step: free resources for the binding discovery timers */
+ discovery_free (agent);
+ g_assert (agent->discovery_list == NULL);
+
+ /* step: free resources for the connectivity check timers */
+ conn_check_free (agent);
+
+ priv_remove_keepalive_timer (agent);
+
+ for (i = agent->local_addresses; i; i = i->next)
+ {
+ NiceAddress *a = i->data;
+
+ nice_address_free (a);
+ }
+
+ g_slist_free (agent->local_addresses);
+ agent->local_addresses = NULL;
+
+ while (agent->streams) {
+ NiceStream *s = agent->streams->data;
+
+ nice_stream_close (agent, s);
+ g_object_unref (s);
+
+ agent->streams = g_slist_delete_link(agent->streams, agent->streams);
+ }
+
+ while ((sig = g_queue_pop_head (&agent->pending_signals))) {
+ free_queued_signal (sig);
+ }
+
+ g_free (agent->stun_server_ip);
+ agent->stun_server_ip = NULL;
+
+ g_free (agent->proxy_ip);
+ agent->proxy_ip = NULL;
+ g_free (agent->proxy_username);
+ agent->proxy_username = NULL;
+ g_free (agent->proxy_password);
+ agent->proxy_password = NULL;
+
+ nice_rng_free (agent->rng);
+ agent->rng = NULL;
+
+ priv_stop_upnp (agent);
+
+#ifdef HAVE_GUPNP
+ if (agent->upnp) {
+ g_object_unref (agent->upnp);
+ agent->upnp = NULL;
+ }
+#endif
+
+ g_free (agent->software_attribute);
+ agent->software_attribute = NULL;
+
+ if (agent->main_context != NULL)
+ g_main_context_unref (agent->main_context);
+ agent->main_context = NULL;
+
+ agent_unlock (agent);
+
+ g_mutex_clear (&agent->agent_mutex);
+
+ if (G_OBJECT_CLASS (nice_agent_parent_class)->dispose)
+ G_OBJECT_CLASS (nice_agent_parent_class)->dispose (object);
+
+}
+
+gboolean
+component_io_cb (GSocket *gsocket, GIOCondition condition, gpointer user_data)
+{
+ SocketSource *socket_source = user_data;
+ NiceComponent *component;
+ NiceAgent *agent;
+ NiceStream *stream;
+ gboolean has_io_callback;
+ gboolean remove_source = FALSE;
+
+ component = socket_source->component;
+
+ agent = g_weak_ref_get (&component->agent_ref);
+ if (agent == NULL)
+ return G_SOURCE_REMOVE;
+
+ agent_lock (agent);
+
+ stream = agent_find_stream (agent, component->stream_id);
+
+ if (stream == NULL) {
+ nice_debug ("%s: stream %d destroyed", G_STRFUNC, component->stream_id);
+
+ agent_unlock (agent);
+ g_object_unref (agent);
+ return G_SOURCE_REMOVE;
+ }
+
+ if (g_source_is_destroyed (g_main_current_source ())) {
+ /* Silently return FALSE. */
+ nice_debug ("%s: source %p destroyed", G_STRFUNC, g_main_current_source ());
+
+ agent_unlock (agent);
+ g_object_unref (agent);
+ return G_SOURCE_REMOVE;
+ }
+
+ /* Remove disconnected sockets when we get a HUP */
+ if (condition & G_IO_HUP) {
+ nice_debug ("Agent %p: NiceSocket %p has received HUP", agent,
+ socket_source->socket);
+ if (component->selected_pair.local &&
+ component->selected_pair.local->sockptr == socket_source->socket &&
+ component->state == NICE_COMPONENT_STATE_READY) {
+ nice_debug ("Agent %p: Selected pair socket %p has HUP, declaring failed",
+ agent, socket_source->socket);
+ agent_signal_component_state_change (agent,
+ stream->id, component->id, NICE_COMPONENT_STATE_FAILED);
+ }
+
+ nice_component_remove_socket (agent, component, socket_source->socket);
+ agent_unlock (agent);
+ g_object_unref (agent);
+ return G_SOURCE_REMOVE;
+ }
+
+ has_io_callback = nice_component_has_io_callback (component);
+
+ /* Choose which receive buffer to use. If we’re reading for
+ * nice_agent_attach_recv(), use a local static buffer. If we’re reading for
+ * nice_agent_recv_messages(), use the buffer provided by the client.
+ *
+ * has_io_callback cannot change throughout this function, as we operate
+ * entirely with the agent lock held, and nice_component_set_io_callback()
+ * would need to take the agent lock to change the Component’s
+ * io_callback. */
+ g_assert (!has_io_callback || component->recv_messages == NULL);
+
+ if (agent->reliable && !nice_socket_is_reliable (socket_source->socket)) {
+#define TCP_HEADER_SIZE 24 /* bytes */
+ guint8 local_header_buf[TCP_HEADER_SIZE];
+ /* FIXME: Currently, the critical path for reliable packet delivery has two
+ * memcpy()s: one into the pseudo-TCP receive buffer, and one out of it.
+ * This could moderately easily be reduced to one memcpy() in the common
+ * case of in-order packet delivery, by replacing local_body_buf with a
+ * pointer into the pseudo-TCP receive buffer. If it turns out the packet
+ * is out-of-order (which we can only know after parsing its header), the
+ * data will need to be moved in the buffer. If the packet *is* in order,
+ * however, the only memcpy() then needed is from the pseudo-TCP receive
+ * buffer to the client’s message buffers.
+ *
+ * In fact, in the case of a reliable agent with I/O callbacks, zero
+ * memcpy()s can be achieved (for in-order packet delivery) by emittin the
+ * I/O callback directly from the pseudo-TCP receive buffer. */
+ guint8 local_body_buf[MAX_BUFFER_SIZE];
+ GInputVector local_bufs[] = {
+ { local_header_buf, sizeof (local_header_buf) },
+ { local_body_buf, sizeof (local_body_buf) },
+ };
+ NiceInputMessage local_message = {
+ local_bufs, G_N_ELEMENTS (local_bufs), NULL, 0
+ };
+ RecvStatus retval = 0;
+
+ if (pseudo_tcp_socket_is_closed (component->tcp)) {
+ nice_debug ("Agent %p: not handling incoming packet for s%d:%d "
+ "because pseudo-TCP socket does not exist in reliable mode.", agent,
+ stream->id, component->id);
+ remove_source = TRUE;
+ goto done;
+ }
+
+ while (has_io_callback ||
+ (component->recv_messages != NULL &&
+ !nice_input_message_iter_is_at_end (&component->recv_messages_iter,
+ component->recv_messages, component->n_recv_messages))) {
+ /* Receive a single message. This will receive it into the given
+ * @local_bufs then, for pseudo-TCP, emit I/O callbacks or copy it into
+ * component->recv_messages in pseudo_tcp_socket_readable(). STUN packets
+ * will be parsed in-place. */
+ retval = agent_recv_message_unlocked (agent, stream, component,
+ socket_source->socket, &local_message);
+
+ nice_debug_verbose ("%s: %p: received %d valid messages with %" G_GSSIZE_FORMAT
+ " bytes", G_STRFUNC, agent, retval, local_message.length);
+
+ /* Don’t expect any valid messages to escape pseudo_tcp_socket_readable()
+ * when in reliable mode. */
+ g_assert_cmpint (retval, !=, RECV_SUCCESS);
+
+ if (retval == RECV_WOULD_BLOCK) {
+ /* EWOULDBLOCK. */
+ break;
+ } else if (retval == RECV_ERROR) {
+ /* Other error. */
+ nice_debug ("%s: error receiving message", G_STRFUNC);
+ remove_source = TRUE;
+ break;
+ }
+
+ has_io_callback = nice_component_has_io_callback (component);
+ }
+ } else if (has_io_callback) {
+ while (has_io_callback) {
+ guint8 local_buf[MAX_BUFFER_SIZE];
+ GInputVector local_bufs = { local_buf, sizeof (local_buf) };
+ NiceInputMessage local_message = { &local_bufs, 1, NULL, 0 };
+ RecvStatus retval;
+
+ /* Receive a single message. */
+ retval = agent_recv_message_unlocked (agent, stream, component,
+ socket_source->socket, &local_message);
+
+ if (retval == RECV_WOULD_BLOCK) {
+ /* EWOULDBLOCK. */
+ nice_debug_verbose ("%s: %p: no message available on read attempt",
+ G_STRFUNC, agent);
+ break;
+ } else if (retval == RECV_ERROR) {
+ /* Other error. */
+ nice_debug ("%s: %p: error receiving message", G_STRFUNC, agent);
+ remove_source = TRUE;
+ break;
+ }
+
+ if (retval == RECV_SUCCESS) {
+ nice_debug_verbose ("%s: %p: received a valid message with %" G_GSSIZE_FORMAT
+ " bytes", G_STRFUNC, agent, local_message.length);
+
+ if (local_message.length > 0) {
+ nice_component_emit_io_callback (agent, component, local_buf,
+ local_message.length);
+ }
+ }
+
+ if (g_source_is_destroyed (g_main_current_source ())) {
+ nice_debug ("Component IO source disappeared during the callback");
+ goto out;
+ }
+ has_io_callback = nice_component_has_io_callback (component);
+ }
+ } else if (component->recv_messages != NULL) {
+ RecvStatus retval;
+
+ /* Don’t want to trample over partially-valid buffers. */
+ g_assert (component->recv_messages_iter.buffer == 0);
+ g_assert (component->recv_messages_iter.offset == 0);
+
+ while (!nice_input_message_iter_is_at_end (&component->recv_messages_iter,
+ component->recv_messages, component->n_recv_messages)) {
+ /* Receive a single message. This will receive it into the given
+ * user-provided #NiceInputMessage, which it’s the user’s responsibility
+ * to ensure is big enough to avoid data loss (since we’re in non-reliable
+ * mode). Iterate to receive as many messages as possible.
+ *
+ * STUN packets will be parsed in-place. */
+ retval = agent_recv_message_unlocked (agent, stream, component,
+ socket_source->socket,
+ &component->recv_messages[component->recv_messages_iter.message]);
+
+ nice_debug_verbose ("%s: %p: received %d valid messages", G_STRFUNC, agent,
+ retval);
+
+ if (retval == RECV_SUCCESS) {
+ /* Successfully received a single message. */
+ component->recv_messages_iter.message++;
+ g_clear_error (component->recv_buf_error);
+ } else if (retval == RECV_WOULD_BLOCK) {
+ /* EWOULDBLOCK. */
+ if (component->recv_messages_iter.message == 0 &&
+ component->recv_buf_error != NULL &&
+ *component->recv_buf_error == NULL) {
+ g_set_error_literal (component->recv_buf_error, G_IO_ERROR,
+ G_IO_ERROR_WOULD_BLOCK, g_strerror (EAGAIN));
+ }
+ break;
+ } else if (retval == RECV_ERROR) {
+ /* Other error. */
+ remove_source = TRUE;
+ break;
+ } /* else if (retval == RECV_OOB) { ignore me and continue; } */
+ }
+ }
+
+done:
+
+ if (remove_source)
+ nice_component_remove_socket (agent, component, socket_source->socket);
+
+ /* If we’re in the middle of a read, don’t emit any signals, or we could cause
+ * re-entrancy by (e.g.) emitting component-state-changed and having the
+ * client perform a read. */
+ if (component->n_recv_messages == 0 && component->recv_messages == NULL) {
+ agent_unlock_and_emit (agent);
+ } else {
+ agent_unlock (agent);
+ }
+
+ g_object_unref (agent);
+
+ return !remove_source;
+
+out:
+ agent_unlock_and_emit (agent);
+
+ g_object_unref (agent);
+
+ return G_SOURCE_REMOVE;
+}
+
+NICEAPI_EXPORT gboolean
+nice_agent_attach_recv (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ GMainContext *ctx,
+ NiceAgentRecvFunc func,
+ gpointer data)
+{
+ NiceComponent *component = NULL;
+ NiceStream *stream = NULL;
+ gboolean ret = FALSE;
+
+ g_return_val_if_fail (NICE_IS_AGENT (agent), FALSE);
+ g_return_val_if_fail (stream_id >= 1, FALSE);
+ g_return_val_if_fail (component_id >= 1, FALSE);
+
+ agent_lock (agent);
+
+ /* attach candidates */
+
+ /* step: check that params specify an existing pair */
+ if (!agent_find_component (agent, stream_id, component_id, &stream, &component)) {
+ g_warning ("Could not find component %u in stream %u", component_id,
+ stream_id);
+ goto done;
+ }
+
+ if (ctx == NULL)
+ ctx = g_main_context_default ();
+
+ /* Set the component’s I/O context. */
+ nice_component_set_io_context (component, ctx);
+ nice_component_set_io_callback (component, func, data, NULL, 0, NULL);
+ ret = TRUE;
+
+ if (func) {
+ /* If we got detached, maybe our readable callback didn't finish reading
+ * all available data in the pseudotcp, so we need to make sure we free
+ * our recv window, so the readable callback can be triggered again on the
+ * next incoming data.
+ * but only do this if we know we're already readable, otherwise we might
+ * trigger an error in the initial, pre-connection attach. */
+ if (agent->reliable && !pseudo_tcp_socket_is_closed (component->tcp) &&
+ component->tcp_readable)
+ pseudo_tcp_socket_readable (component->tcp, component);
+ }
+
+ done:
+ agent_unlock_and_emit (agent);
+ return ret;
+}
+
+NICEAPI_EXPORT gboolean
+nice_agent_set_selected_pair (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ const gchar *lfoundation,
+ const gchar *rfoundation)
+{
+ NiceComponent *component;
+ NiceStream *stream;
+ CandidatePair pair;
+ gboolean ret = FALSE;
+
+ g_return_val_if_fail (NICE_IS_AGENT (agent), FALSE);
+ g_return_val_if_fail (stream_id >= 1, FALSE);
+ g_return_val_if_fail (component_id >= 1, FALSE);
+ g_return_val_if_fail (lfoundation, FALSE);
+ g_return_val_if_fail (rfoundation, FALSE);
+
+ agent_lock (agent);
+
+ /* step: check that params specify an existing pair */
+ if (!agent_find_component (agent, stream_id, component_id, &stream, &component)) {
+ goto done;
+ }
+
+ if (!nice_component_find_pair (component, agent, lfoundation, rfoundation, &pair)){
+ goto done;
+ }
+
+ /* step: stop connectivity checks (note: for the whole stream) */
+ conn_check_prune_stream (agent, stream);
+
+ if (agent->reliable && !nice_socket_is_reliable (pair.local->sockptr) &&
+ pseudo_tcp_socket_is_closed (component->tcp)) {
+ nice_debug ("Agent %p: not setting selected pair for s%d:%d because "
+ "pseudo tcp socket does not exist in reliable mode", agent,
+ stream->id, component->id);
+ goto done;
+ }
+
+ /* step: change component state; we could be in STATE_DISCONNECTED; skip
+ * STATE_GATHERING and continue through the states to give client code a nice
+ * logical progression. See http://phabricator.freedesktop.org/D218 for
+ * discussion. */
+ if (component->state < NICE_COMPONENT_STATE_CONNECTING ||
+ component->state == NICE_COMPONENT_STATE_FAILED)
+ agent_signal_component_state_change (agent, stream_id, component_id,
+ NICE_COMPONENT_STATE_CONNECTING);
+ if (component->state < NICE_COMPONENT_STATE_CONNECTED)
+ agent_signal_component_state_change (agent, stream_id, component_id,
+ NICE_COMPONENT_STATE_CONNECTED);
+ agent_signal_component_state_change (agent, stream_id, component_id,
+ NICE_COMPONENT_STATE_READY);
+
+ /* step: set the selected pair */
+ nice_component_update_selected_pair (agent, component, &pair);
+ agent_signal_new_selected_pair (agent, stream_id, component_id,
+ pair.local, pair.remote);
+
+ ret = TRUE;
+
+ done:
+ agent_unlock_and_emit (agent);
+ return ret;
+}
+
+NICEAPI_EXPORT gboolean
+nice_agent_get_selected_pair (NiceAgent *agent, guint stream_id,
+ guint component_id, NiceCandidate **local, NiceCandidate **remote)
+{
+ NiceComponent *component;
+ NiceStream *stream;
+ gboolean ret = FALSE;
+
+ g_return_val_if_fail (NICE_IS_AGENT (agent), FALSE);
+ g_return_val_if_fail (stream_id >= 1, FALSE);
+ g_return_val_if_fail (component_id >= 1, FALSE);
+ g_return_val_if_fail (local != NULL, FALSE);
+ g_return_val_if_fail (remote != NULL, FALSE);
+
+ agent_lock (agent);
+
+ /* step: check that params specify an existing pair */
+ if (!agent_find_component (agent, stream_id, component_id,
+ &stream, &component))
+ goto done;
+
+ if (component->selected_pair.local && component->selected_pair.remote) {
+ *local = component->selected_pair.local;
+ *remote = component->selected_pair.remote;
+ ret = TRUE;
+ }
+
+ done:
+ agent_unlock_and_emit (agent);
+
+ return ret;
+}
+
+NICEAPI_EXPORT GSocket *
+nice_agent_get_selected_socket (NiceAgent *agent, guint stream_id,
+ guint component_id)
+{
+ NiceComponent *component;
+ NiceStream *stream;
+ NiceSocket *nice_socket;
+ GSocket *g_socket = NULL;
+
+ g_return_val_if_fail (NICE_IS_AGENT (agent), NULL);
+ g_return_val_if_fail (stream_id >= 1, NULL);
+ g_return_val_if_fail (component_id >= 1, NULL);
+
+ agent_lock (agent);
+
+ /* Reliable streams are pseudotcp or MUST use RFC 4571 framing */
+ if (agent->reliable)
+ goto done;
+
+ /* step: check that params specify an existing pair */
+ if (!agent_find_component (agent, stream_id, component_id,
+ &stream, &component))
+ goto done;
+
+ if (!component->selected_pair.local || !component->selected_pair.remote)
+ goto done;
+
+ if (component->selected_pair.local->type == NICE_CANDIDATE_TYPE_RELAYED)
+ goto done;
+
+ /* ICE-TCP requires RFC4571 framing, even if unreliable */
+ if (component->selected_pair.local->transport != NICE_CANDIDATE_TRANSPORT_UDP)
+ goto done;
+
+ nice_socket = (NiceSocket *)component->selected_pair.local->sockptr;
+ if (nice_socket->fileno)
+ g_socket = g_object_ref (nice_socket->fileno);
+
+ done:
+ agent_unlock_and_emit (agent);
+
+ return g_socket;
+}
+
+typedef struct _TimeoutData
+{
+ GWeakRef/*<NiceAgent>*/ agent_ref;
+ NiceTimeoutLockedCallback function;
+ gpointer user_data;
+} TimeoutData;
+
+static void
+timeout_data_destroy (TimeoutData *data)
+{
+ g_weak_ref_clear (&data->agent_ref);
+ g_slice_free (TimeoutData, data);
+}
+
+static TimeoutData *
+timeout_data_new (NiceAgent *agent, NiceTimeoutLockedCallback function,
+ gpointer user_data)
+{
+ TimeoutData *data = g_slice_new0 (TimeoutData);
+
+ g_weak_ref_init (&data->agent_ref, agent);
+ data->function = function;
+ data->user_data = user_data;
+
+ return data;
+}
+
+static gboolean
+timeout_cb (gpointer user_data)
+{
+ TimeoutData *data = user_data;
+ NiceAgent *agent;
+ gboolean ret = G_SOURCE_REMOVE;
+
+ agent = g_weak_ref_get (&data->agent_ref);
+ if (agent == NULL) {
+ return G_SOURCE_REMOVE;
+ }
+
+ agent_lock (agent);
+
+ /* A race condition might happen where the mutex above waits for the lock
+ * and in the meantime another thread destroys the source.
+ * In that case, we don't need to run the function since it should
+ * have been cancelled */
+ if (g_source_is_destroyed (g_main_current_source ())) {
+ nice_debug ("Source was destroyed. Avoided race condition in timeout_cb");
+
+ agent_unlock (agent);
+ goto end;
+ }
+
+ ret = data->function (agent, data->user_data);
+
+ agent_unlock_and_emit (agent);
+
+ end:
+ g_object_unref (agent);
+
+ return ret;
+}
+
+/* Create a new timer GSource with the given @name, @interval, callback
+ * @function and @data, and assign it to @out, destroying and freeing any
+ * existing #GSource in @out first.
+ *
+ * This guarantees that a timer won’t be overwritten without being destroyed.
+ *
+ * @interval is given in milliseconds.
+ */
+static void agent_timeout_add_with_context_internal (NiceAgent *agent,
+ GSource **out, const gchar *name, guint interval, gboolean seconds,
+ NiceTimeoutLockedCallback function, gpointer user_data)
+{
+ GSource *source;
+ TimeoutData *data;
+
+ g_return_if_fail (function != NULL);
+ g_return_if_fail (out != NULL);
+
+ /* Destroy any existing source. */
+ if (*out != NULL) {
+ g_source_destroy (*out);
+ g_source_unref (*out);
+ *out = NULL;
+ }
+
+ /* Create the new source. */
+ if (seconds)
+ source = g_timeout_source_new_seconds (interval);
+ else
+ source = g_timeout_source_new (interval);
+
+ g_source_set_name (source, name);
+ data = timeout_data_new (agent, function, user_data);
+ g_source_set_callback (source, timeout_cb, data,
+ (GDestroyNotify)timeout_data_destroy);
+ g_source_attach (source, agent->main_context);
+
+ /* Return it! */
+ *out = source;
+}
+
+void agent_timeout_add_with_context (NiceAgent *agent,
+ GSource **out, const gchar *name, guint interval,
+ NiceTimeoutLockedCallback function, gpointer user_data)
+{
+ agent_timeout_add_with_context_internal (agent, out, name, interval, FALSE,
+ function, user_data);
+}
+
+void agent_timeout_add_seconds_with_context (NiceAgent *agent,
+ GSource **out, const gchar *name, guint interval,
+ NiceTimeoutLockedCallback function, gpointer user_data)
+{
+ agent_timeout_add_with_context_internal (agent, out, name, interval, TRUE,
+ function, user_data);
+}
+
+NICEAPI_EXPORT gboolean
+nice_agent_set_selected_remote_candidate (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ NiceCandidate *candidate)
+{
+ NiceComponent *component;
+ NiceStream *stream;
+ NiceCandidate *lcandidate = NULL;
+ gboolean ret = FALSE;
+ NiceCandidate *local = NULL, *remote = NULL;
+ guint64 priority;
+
+ g_return_val_if_fail (NICE_IS_AGENT (agent), FALSE);
+ g_return_val_if_fail (stream_id != 0, FALSE);
+ g_return_val_if_fail (component_id != 0, FALSE);
+ g_return_val_if_fail (candidate != NULL, FALSE);
+
+ agent_lock (agent);
+
+ /* step: check if the component exists*/
+ if (!agent_find_component (agent, stream_id, component_id, &stream, &component)) {
+ goto done;
+ }
+
+ /* step: stop connectivity checks (note: for the whole stream) */
+ conn_check_prune_stream (agent, stream);
+
+ /* Store previous selected pair */
+ local = component->selected_pair.local;
+ remote = component->selected_pair.remote;
+ priority = component->selected_pair.priority;
+
+ /* step: set the selected pair */
+ lcandidate = nice_component_set_selected_remote_candidate (component, agent,
+ candidate);
+ if (!lcandidate)
+ goto done;
+
+ if (agent->reliable && !nice_socket_is_reliable (lcandidate->sockptr) &&
+ pseudo_tcp_socket_is_closed (component->tcp)) {
+ nice_debug ("Agent %p: not setting selected remote candidate s%d:%d because"
+ " pseudo tcp socket does not exist in reliable mode", agent,
+ stream->id, component->id);
+ /* Revert back to previous selected pair */
+ /* FIXME: by doing this, we lose the keepalive tick */
+ component->selected_pair.local = local;
+ component->selected_pair.remote = remote;
+ component->selected_pair.priority = priority;
+ goto done;
+ }
+
+ /* step: change component state; we could be in STATE_DISCONNECTED; skip
+ * STATE_GATHERING and continue through the states to give client code a nice
+ * logical progression. See http://phabricator.freedesktop.org/D218 for
+ * discussion. */
+ if (component->state < NICE_COMPONENT_STATE_CONNECTING ||
+ component->state == NICE_COMPONENT_STATE_FAILED)
+ agent_signal_component_state_change (agent, stream_id, component_id,
+ NICE_COMPONENT_STATE_CONNECTING);
+ if (component->state < NICE_COMPONENT_STATE_CONNECTED)
+ agent_signal_component_state_change (agent, stream_id, component_id,
+ NICE_COMPONENT_STATE_CONNECTED);
+ agent_signal_component_state_change (agent, stream_id, component_id,
+ NICE_COMPONENT_STATE_READY);
+
+ agent_signal_new_selected_pair (agent, stream_id, component_id,
+ lcandidate, candidate);
+
+ ret = TRUE;
+
+ done:
+ agent_unlock_and_emit (agent);
+ return ret;
+}
+
+void
+_priv_set_socket_tos (NiceAgent *agent, NiceSocket *sock, gint tos)
+{
+ if (sock->fileno == NULL)
+ return;
+
+ if (setsockopt (g_socket_get_fd (sock->fileno), IPPROTO_IP,
+ IP_TOS, (const char *) &tos, sizeof (tos)) < 0) {
+ nice_debug ("Agent %p: Could not set socket ToS: %s", agent,
+ g_strerror (errno));
+ }
+#ifdef IPV6_TCLASS
+ if (setsockopt (g_socket_get_fd (sock->fileno), IPPROTO_IPV6,
+ IPV6_TCLASS, (const char *) &tos, sizeof (tos)) < 0) {
+ nice_debug ("Agent %p: Could not set IPV6 socket ToS: %s", agent,
+ g_strerror (errno));
+ }
+#endif
+}
+
+
+NICEAPI_EXPORT void
+nice_agent_set_stream_tos (NiceAgent *agent,
+ guint stream_id, gint tos)
+{
+ GSList *i, *j;
+ NiceStream *stream;
+
+ g_return_if_fail (NICE_IS_AGENT (agent));
+ g_return_if_fail (stream_id >= 1);
+
+ agent_lock (agent);
+
+ stream = agent_find_stream (agent, stream_id);
+ if (stream == NULL)
+ goto done;
+
+ stream->tos = tos;
+ for (i = stream->components; i; i = i->next) {
+ NiceComponent *component = i->data;
+
+ for (j = component->local_candidates; j; j = j->next) {
+ NiceCandidate *local_candidate = j->data;
+
+ _priv_set_socket_tos (agent, local_candidate->sockptr, tos);
+ }
+ }
+
+ done:
+ agent_unlock_and_emit (agent);
+}
+
+NICEAPI_EXPORT void
+nice_agent_set_software (NiceAgent *agent, const gchar *software)
+{
+ g_return_if_fail (NICE_IS_AGENT (agent));
+
+ agent_lock (agent);
+
+ g_free (agent->software_attribute);
+ if (software)
+ agent->software_attribute = g_strdup_printf ("%s/%s",
+ software, PACKAGE_STRING);
+ else
+ agent->software_attribute = NULL;
+
+ nice_agent_reset_all_stun_agents (agent, TRUE);
+
+ agent_unlock_and_emit (agent);
+}
+
+NICEAPI_EXPORT gboolean
+nice_agent_set_stream_name (NiceAgent *agent, guint stream_id,
+ const gchar *name)
+{
+ NiceStream *stream_to_name = NULL;
+ GSList *i;
+ gboolean ret = FALSE;
+
+ g_return_val_if_fail (NICE_IS_AGENT (agent), FALSE);
+ g_return_val_if_fail (stream_id >= 1, FALSE);
+ g_return_val_if_fail (name, FALSE);
+
+ if (strcmp (name, "audio") &&
+ strcmp (name, "video") &&
+ strcmp (name, "text") &&
+ strcmp (name, "application") &&
+ strcmp (name, "message") &&
+ strcmp (name, "image")) {
+ g_critical ("Stream name %s will produce invalid SDP, only \"audio\","
+ " \"video\", \"text\", \"application\", \"image\" and \"message\""
+ " are valid", name);
+ }
+
+ agent_lock (agent);
+
+ for (i = agent->streams; i; i = i->next) {
+ NiceStream *stream = i->data;
+
+ if (stream->id != stream_id &&
+ g_strcmp0 (stream->name, name) == 0)
+ goto done;
+ else if (stream->id == stream_id)
+ stream_to_name = stream;
+ }
+
+ if (stream_to_name == NULL)
+ goto done;
+
+ if (stream_to_name->name)
+ g_free (stream_to_name->name);
+ stream_to_name->name = g_strdup (name);
+ ret = TRUE;
+
+ done:
+ agent_unlock_and_emit (agent);
+
+ return ret;
+}
+
+NICEAPI_EXPORT const gchar *
+nice_agent_get_stream_name (NiceAgent *agent, guint stream_id)
+{
+ NiceStream *stream;
+ gchar *name = NULL;
+
+ g_return_val_if_fail (NICE_IS_AGENT (agent), NULL);
+ g_return_val_if_fail (stream_id >= 1, NULL);
+
+ agent_lock (agent);
+
+ stream = agent_find_stream (agent, stream_id);
+ if (stream == NULL)
+ goto done;
+
+ name = stream->name;
+
+ done:
+ agent_unlock_and_emit (agent);
+ return name;
+}
+
+static NiceCandidate *
+_get_default_local_candidate_locked (NiceAgent *agent,
+ NiceStream *stream, NiceComponent *component)
+{
+ GSList *i;
+ NiceCandidate *default_candidate = NULL;
+ NiceCandidate *default_rtp_candidate = NULL;
+
+ if (component->id != NICE_COMPONENT_TYPE_RTP) {
+ NiceComponent *rtp_component;
+
+ if (!agent_find_component (agent, stream->id, NICE_COMPONENT_TYPE_RTP,
+ NULL, &rtp_component))
+ goto done;
+
+ default_rtp_candidate = _get_default_local_candidate_locked (agent, stream,
+ rtp_component);
+ if (default_rtp_candidate == NULL)
+ goto done;
+ }
+
+
+ for (i = component->local_candidates; i; i = i->next) {
+ NiceCandidate *local_candidate = i->data;
+
+ if (agent->force_relay &&
+ local_candidate->type != NICE_CANDIDATE_TYPE_RELAYED)
+ continue;
+
+ /* Only check for ipv4 candidates */
+ if (nice_address_ip_version (&local_candidate->addr) != 4)
+ continue;
+ if (component->id == NICE_COMPONENT_TYPE_RTP) {
+ if (default_candidate == NULL ||
+ local_candidate->priority < default_candidate->priority) {
+ default_candidate = local_candidate;
+ }
+ } else if (strncmp (local_candidate->foundation,
+ default_rtp_candidate->foundation,
+ NICE_CANDIDATE_MAX_FOUNDATION) == 0) {
+ default_candidate = local_candidate;
+ break;
+ }
+ }
+
+ done:
+ return default_candidate;
+}
+
+NICEAPI_EXPORT NiceCandidate *
+nice_agent_get_default_local_candidate (NiceAgent *agent,
+ guint stream_id, guint component_id)
+{
+ NiceStream *stream = NULL;
+ NiceComponent *component = NULL;
+ NiceCandidate *default_candidate = NULL;
+
+ g_return_val_if_fail (NICE_IS_AGENT (agent), NULL);
+ g_return_val_if_fail (stream_id >= 1, NULL);
+ g_return_val_if_fail (component_id >= 1, NULL);
+
+ agent_lock (agent);
+
+ /* step: check if the component exists*/
+ if (!agent_find_component (agent, stream_id, component_id,
+ &stream, &component))
+ goto done;
+
+ default_candidate = _get_default_local_candidate_locked (agent, stream,
+ component);
+ if (default_candidate)
+ default_candidate = nice_candidate_copy (default_candidate);
+
+ done:
+ agent_unlock_and_emit (agent);
+
+ return default_candidate;
+}
+
+static const gchar *
+_cand_type_to_sdp (NiceCandidateType type) {
+ switch(type) {
+ case NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE:
+ return "srflx";
+ case NICE_CANDIDATE_TYPE_PEER_REFLEXIVE:
+ return "prflx";
+ case NICE_CANDIDATE_TYPE_RELAYED:
+ return "relay";
+ case NICE_CANDIDATE_TYPE_HOST:
+ default:
+ return "host";
+ }
+}
+
+static const gchar *
+_transport_to_sdp (NiceCandidateTransport type) {
+ switch(type) {
+ case NICE_CANDIDATE_TRANSPORT_UDP:
+ return "UDP";
+ case NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE:
+ case NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE:
+ case NICE_CANDIDATE_TRANSPORT_TCP_SO:
+ return "TCP";
+ default:
+ return "???";
+ }
+}
+
+static const gchar *
+_transport_to_sdp_tcptype (NiceCandidateTransport type) {
+ switch(type) {
+ case NICE_CANDIDATE_TRANSPORT_UDP:
+ return "";
+ case NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE:
+ return "active";
+ case NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE:
+ return "passive";
+ case NICE_CANDIDATE_TRANSPORT_TCP_SO:
+ return "so";
+ default:
+ return "";
+ }
+}
+
+static void
+_generate_candidate_sdp (NiceAgent *agent,
+ NiceCandidate *candidate, GString *sdp)
+{
+ gchar ip4[INET6_ADDRSTRLEN];
+ guint16 port;
+
+ nice_address_to_string (&candidate->addr, ip4);
+ port = nice_address_get_port (&candidate->addr);
+ g_string_append_printf (sdp, "a=candidate:%.*s %d %s %d %s %d",
+ NICE_CANDIDATE_MAX_FOUNDATION, candidate->foundation,
+ candidate->component_id,
+ _transport_to_sdp (candidate->transport),
+ candidate->priority, ip4, port == 0 ? 9 : port);
+ g_string_append_printf (sdp, " typ %s", _cand_type_to_sdp (candidate->type));
+ if (nice_address_is_valid (&candidate->base_addr) &&
+ !nice_address_equal (&candidate->addr, &candidate->base_addr)) {
+ port = nice_address_get_port (&candidate->base_addr);
+ nice_address_to_string (&candidate->base_addr, ip4);
+ g_string_append_printf (sdp, " raddr %s rport %d", ip4,
+ port == 0 ? 9 : port);
+ }
+ if (candidate->transport != NICE_CANDIDATE_TRANSPORT_UDP) {
+ g_string_append_printf (sdp, " tcptype %s",
+ _transport_to_sdp_tcptype (candidate->transport));
+ }
+}
+
+static void
+_generate_stream_sdp (NiceAgent *agent, NiceStream *stream,
+ GString *sdp, gboolean include_non_ice)
+{
+ GSList *i, *j;
+
+ if (include_non_ice) {
+ NiceAddress rtp, rtcp;
+ gchar ip4[INET6_ADDRSTRLEN] = "";
+
+ nice_address_init (&rtp);
+ nice_address_set_ipv4 (&rtp, 0);
+ nice_address_init (&rtcp);
+ nice_address_set_ipv4 (&rtcp, 0);
+
+ /* Find default candidates */
+ for (i = stream->components; i; i = i->next) {
+ NiceComponent *component = i->data;
+ NiceCandidate *default_candidate;
+
+ if (component->id == NICE_COMPONENT_TYPE_RTP) {
+ default_candidate = _get_default_local_candidate_locked (agent, stream,
+ component);
+ if (default_candidate)
+ rtp = default_candidate->addr;
+ } else if (component->id == NICE_COMPONENT_TYPE_RTCP) {
+ default_candidate = _get_default_local_candidate_locked (agent, stream,
+ component);
+ if (default_candidate)
+ rtcp = default_candidate->addr;
+ }
+ }
+
+ nice_address_to_string (&rtp, ip4);
+ g_string_append_printf (sdp, "m=%s %d ICE/SDP\n",
+ stream->name ? stream->name : "-", nice_address_get_port (&rtp));
+ g_string_append_printf (sdp, "c=IN IP4 %s\n", ip4);
+ if (nice_address_get_port (&rtcp) != 0)
+ g_string_append_printf (sdp, "a=rtcp:%d\n",
+ nice_address_get_port (&rtcp));
+ }
+
+ g_string_append_printf (sdp, "a=ice-ufrag:%s\n", stream->local_ufrag);
+ g_string_append_printf (sdp, "a=ice-pwd:%s\n", stream->local_password);
+
+ for (i = stream->components; i; i = i->next) {
+ NiceComponent *component = i->data;
+
+ for (j = component->local_candidates; j; j = j->next) {
+ NiceCandidate *candidate = j->data;
+
+ if (agent->force_relay && candidate->type != NICE_CANDIDATE_TYPE_RELAYED)
+ continue;
+
+ _generate_candidate_sdp (agent, candidate, sdp);
+ g_string_append (sdp, "\n");
+ }
+ }
+}
+
+NICEAPI_EXPORT gchar *
+nice_agent_generate_local_sdp (NiceAgent *agent)
+{
+ GString * sdp = g_string_new (NULL);
+ GSList *i;
+
+ g_return_val_if_fail (NICE_IS_AGENT (agent), NULL);
+
+ agent_lock (agent);
+
+ for (i = agent->streams; i; i = i->next) {
+ NiceStream *stream = i->data;
+
+ _generate_stream_sdp (agent, stream, sdp, TRUE);
+ }
+
+ agent_unlock_and_emit (agent);
+
+ return g_string_free (sdp, FALSE);
+}
+
+NICEAPI_EXPORT gchar *
+nice_agent_generate_local_stream_sdp (NiceAgent *agent, guint stream_id,
+ gboolean include_non_ice)
+{
+ GString *sdp = NULL;
+ gchar *ret = NULL;
+ NiceStream *stream;
+
+ g_return_val_if_fail (NICE_IS_AGENT (agent), NULL);
+ g_return_val_if_fail (stream_id >= 1, NULL);
+
+ agent_lock (agent);
+
+ stream = agent_find_stream (agent, stream_id);
+ if (stream == NULL)
+ goto done;
+
+ sdp = g_string_new (NULL);
+ _generate_stream_sdp (agent, stream, sdp, include_non_ice);
+ ret = g_string_free (sdp, FALSE);
+
+ done:
+ agent_unlock_and_emit (agent);
+
+ return ret;
+}
+
+NICEAPI_EXPORT gchar *
+nice_agent_generate_local_candidate_sdp (NiceAgent *agent,
+ NiceCandidate *candidate)
+{
+ GString *sdp = NULL;
+
+ g_return_val_if_fail (NICE_IS_AGENT (agent), NULL);
+ g_return_val_if_fail (candidate != NULL, NULL);
+
+ agent_lock (agent);
+
+ sdp = g_string_new (NULL);
+ _generate_candidate_sdp (agent, candidate, sdp);
+
+ agent_unlock_and_emit (agent);
+
+ return g_string_free (sdp, FALSE);
+}
+
+NICEAPI_EXPORT gint
+nice_agent_parse_remote_sdp (NiceAgent *agent, const gchar *sdp)
+{
+ NiceStream *current_stream = NULL;
+ gchar **sdp_lines = NULL;
+ GSList *stream_item = NULL;
+ gint i;
+ gint ret = 0;
+
+ g_return_val_if_fail (NICE_IS_AGENT (agent), -1);
+ g_return_val_if_fail (sdp != NULL, -1);
+
+ agent_lock (agent);
+
+ sdp_lines = g_strsplit (sdp, "\n", 0);
+ for (i = 0; sdp_lines && sdp_lines[i]; i++) {
+ if (g_str_has_prefix (sdp_lines[i], "m=")) {
+ if (stream_item == NULL)
+ stream_item = agent->streams;
+ else
+ stream_item = stream_item->next;
+ if (!stream_item) {
+ g_critical("More streams in SDP than in agent");
+ ret = -1;
+ goto done;
+ }
+ current_stream = stream_item->data;
+ } else if (g_str_has_prefix (sdp_lines[i], "a=ice-ufrag:")) {
+ if (current_stream == NULL) {
+ ret = -1;
+ goto done;
+ }
+ g_strlcpy (current_stream->remote_ufrag, sdp_lines[i] + 12,
+ NICE_STREAM_MAX_UFRAG);
+ } else if (g_str_has_prefix (sdp_lines[i], "a=ice-pwd:")) {
+ if (current_stream == NULL) {
+ ret = -1;
+ goto done;
+ }
+ g_strlcpy (current_stream->remote_password, sdp_lines[i] + 10,
+ NICE_STREAM_MAX_PWD);
+ } else if (g_str_has_prefix (sdp_lines[i], "a=candidate:")) {
+ NiceCandidate *candidate = NULL;
+ NiceComponent *component = NULL;
+ GSList *cands = NULL;
+ gint added;
+
+ if (current_stream == NULL) {
+ ret = -1;
+ goto done;
+ }
+ candidate = nice_agent_parse_remote_candidate_sdp (agent,
+ current_stream->id, sdp_lines[i]);
+ if (candidate == NULL) {
+ ret = -1;
+ goto done;
+ }
+
+ if (!agent_find_component (agent, candidate->stream_id,
+ candidate->component_id, NULL, &component)) {
+ nice_candidate_free (candidate);
+ ret = -1;
+ goto done;
+ }
+ cands = g_slist_prepend (cands, candidate);
+ added = _set_remote_candidates_locked (agent, current_stream,
+ component, cands);
+ g_slist_free_full(cands, (GDestroyNotify)&nice_candidate_free);
+ if (added > 0)
+ ret++;
+ }
+ }
+
+ done:
+ if (sdp_lines)
+ g_strfreev(sdp_lines);
+
+ agent_unlock_and_emit (agent);
+
+ return ret;
+}
+
+NICEAPI_EXPORT GSList *
+nice_agent_parse_remote_stream_sdp (NiceAgent *agent, guint stream_id,
+ const gchar *sdp, gchar **ufrag, gchar **pwd)
+{
+ NiceStream *stream = NULL;
+ gchar **sdp_lines = NULL;
+ GSList *candidates = NULL;
+ gint i;
+
+ g_return_val_if_fail (NICE_IS_AGENT (agent), NULL);
+ g_return_val_if_fail (stream_id >= 1, NULL);
+ g_return_val_if_fail (sdp != NULL, NULL);
+
+ agent_lock (agent);
+
+ stream = agent_find_stream (agent, stream_id);
+ if (stream == NULL) {
+ goto done;
+ }
+
+ sdp_lines = g_strsplit (sdp, "\n", 0);
+ for (i = 0; sdp_lines && sdp_lines[i]; i++) {
+ if (ufrag && g_str_has_prefix (sdp_lines[i], "a=ice-ufrag:")) {
+ *ufrag = g_strdup (sdp_lines[i] + 12);
+ } else if (pwd && g_str_has_prefix (sdp_lines[i], "a=ice-pwd:")) {
+ *pwd = g_strdup (sdp_lines[i] + 10);
+ } else if (g_str_has_prefix (sdp_lines[i], "a=candidate:")) {
+ NiceCandidate *candidate = NULL;
+
+ candidate = nice_agent_parse_remote_candidate_sdp (agent, stream->id,
+ sdp_lines[i]);
+ if (candidate == NULL) {
+ g_slist_free_full(candidates, (GDestroyNotify)&nice_candidate_free);
+ candidates = NULL;
+ break;
+ }
+ candidates = g_slist_prepend (candidates, candidate);
+ }
+ }
+
+ done:
+ if (sdp_lines)
+ g_strfreev(sdp_lines);
+
+ agent_unlock_and_emit (agent);
+
+ return candidates;
+}
+
+NICEAPI_EXPORT NiceCandidate *
+nice_agent_parse_remote_candidate_sdp (NiceAgent *agent, guint stream_id,
+ const gchar *sdp)
+{
+ NiceCandidate *candidate = NULL;
+ int ntype = -1;
+ gchar **tokens = NULL;
+ const gchar *foundation = NULL;
+ guint component_id = 0;
+ const gchar *transport = NULL;
+ guint32 priority = 0;
+ const gchar *addr = NULL;
+ guint16 port = 0;
+ const gchar *type = NULL;
+ const gchar *tcptype = NULL;
+ const gchar *raddr = NULL;
+ guint16 rport = 0;
+ static const gchar *type_names[] = {"host", "srflx", "prflx", "relay"};
+ NiceCandidateTransport ctransport;
+ guint i;
+
+ g_return_val_if_fail (NICE_IS_AGENT (agent), NULL);
+ g_return_val_if_fail (stream_id >= 1, NULL);
+ g_return_val_if_fail (sdp != NULL, NULL);
+
+ if (!g_str_has_prefix (sdp, "a=candidate:"))
+ goto done;
+
+ tokens = g_strsplit (sdp + 12, " ", 0);
+ for (i = 0; tokens && tokens[i]; i++) {
+ switch (i) {
+ case 0:
+ foundation = tokens[i];
+ break;
+ case 1:
+ component_id = (guint) g_ascii_strtoull (tokens[i], NULL, 10);
+ break;
+ case 2:
+ transport = tokens[i];
+ break;
+ case 3:
+ priority = (guint32) g_ascii_strtoull (tokens[i], NULL, 10);
+ break;
+ case 4:
+ addr = tokens[i];
+ break;
+ case 5:
+ port = (guint16) g_ascii_strtoull (tokens[i], NULL, 10);
+ break;
+ default:
+ if (tokens[i + 1] == NULL)
+ goto done;
+
+ if (g_strcmp0 (tokens[i], "typ") == 0) {
+ type = tokens[i + 1];
+ } else if (g_strcmp0 (tokens[i], "raddr") == 0) {
+ raddr = tokens[i + 1];
+ } else if (g_strcmp0 (tokens[i], "rport") == 0) {
+ rport = (guint16) g_ascii_strtoull (tokens[i + 1], NULL, 10);
+ } else if (g_strcmp0 (tokens[i], "tcptype") == 0) {
+ tcptype = tokens[i + 1];
+ }
+ i++;
+ break;
+ }
+ }
+ if (type == NULL)
+ goto done;
+
+ ntype = -1;
+ for (i = 0; i < G_N_ELEMENTS (type_names); i++) {
+ if (g_strcmp0 (type, type_names[i]) == 0) {
+ ntype = i;
+ break;
+ }
+ }
+ if (ntype == -1)
+ goto done;
+
+ if (g_ascii_strcasecmp (transport, "UDP") == 0)
+ ctransport = NICE_CANDIDATE_TRANSPORT_UDP;
+ else if (g_ascii_strcasecmp (transport, "TCP-SO") == 0)
+ ctransport = NICE_CANDIDATE_TRANSPORT_TCP_SO;
+ else if (g_ascii_strcasecmp (transport, "TCP-ACT") == 0)
+ ctransport = NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE;
+ else if (g_ascii_strcasecmp (transport, "TCP-PASS") == 0)
+ ctransport = NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE;
+ else if (g_ascii_strcasecmp (transport, "TCP") == 0) {
+ if (g_ascii_strcasecmp (tcptype, "so") == 0)
+ ctransport = NICE_CANDIDATE_TRANSPORT_TCP_SO;
+ else if (g_ascii_strcasecmp (tcptype, "active") == 0)
+ ctransport = NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE;
+ else if (g_ascii_strcasecmp (tcptype, "passive") == 0)
+ ctransport = NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE;
+ else
+ goto done;
+ } else
+ goto done;
+
+ candidate = nice_candidate_new(ntype);
+ candidate->component_id = component_id;
+ candidate->stream_id = stream_id;
+ candidate->transport = ctransport;
+ g_strlcpy(candidate->foundation, foundation, NICE_CANDIDATE_MAX_FOUNDATION);
+ candidate->priority = priority;
+
+ if (!nice_address_set_from_string (&candidate->addr, addr)) {
+ nice_candidate_free (candidate);
+ candidate = NULL;
+ goto done;
+ }
+ nice_address_set_port (&candidate->addr, port);
+
+ if (raddr && rport) {
+ if (!nice_address_set_from_string (&candidate->base_addr, raddr)) {
+ nice_candidate_free (candidate);
+ candidate = NULL;
+ goto done;
+ }
+ nice_address_set_port (&candidate->base_addr, rport);
+ }
+
+ done:
+ if (tokens)
+ g_strfreev(tokens);
+
+ return candidate;
+}
+
+
+NICEAPI_EXPORT GIOStream *
+nice_agent_get_io_stream (NiceAgent *agent, guint stream_id,
+ guint component_id)
+{
+ GIOStream *iostream = NULL;
+ NiceComponent *component;
+
+ g_return_val_if_fail (NICE_IS_AGENT (agent), NULL);
+ g_return_val_if_fail (stream_id >= 1, NULL);
+ g_return_val_if_fail (component_id >= 1, NULL);
+
+ g_return_val_if_fail (agent->reliable, NULL);
+
+ agent_lock (agent);
+
+ if (!agent_find_component (agent, stream_id, component_id, NULL, &component))
+ goto done;
+
+ if (component->iostream == NULL)
+ component->iostream = nice_io_stream_new (agent, stream_id, component_id);
+
+ iostream = g_object_ref (component->iostream);
+
+ done:
+ agent_unlock_and_emit (agent);
+
+ return iostream;
+}
+
+NICEAPI_EXPORT gboolean
+nice_agent_forget_relays (NiceAgent *agent, guint stream_id, guint component_id)
+{
+ NiceComponent *component;
+ gboolean ret = TRUE;
+
+ g_return_val_if_fail (NICE_IS_AGENT (agent), FALSE);
+ g_return_val_if_fail (stream_id >= 1, FALSE);
+ g_return_val_if_fail (component_id >= 1, FALSE);
+
+ agent_lock (agent);
+
+ if (!agent_find_component (agent, stream_id, component_id, NULL, &component)) {
+ ret = FALSE;
+ goto done;
+ }
+
+ nice_component_clean_turn_servers (agent, component);
+
+ done:
+ agent_unlock_and_emit (agent);
+
+ return ret;
+}
+
+/* Helper function to allow us to send connchecks reliably.
+ * If the transport is reliable, then we request a reliable send, which will
+ * either send the data, or queue it in the case of unestablished http/socks5
+ * proxies or tcp-turn. If the transport is not reliable, then it could be an
+ * unreliable tcp-bsd, so we still try a reliable send to see if it can succeed
+ * meaning the message was queued, or if it failed, then it was either udp-bsd
+ * or turn and so we retry with a non reliable send and let the retransmissions
+ * take care of the rest.
+ * This is in order to avoid having to retransmit something if the underlying
+ * socket layer can queue the message and send it once a connection is
+ * established.
+ */
+gssize
+agent_socket_send (NiceSocket *sock, const NiceAddress *addr, gsize len,
+ const gchar *buf)
+{
+ if (nice_socket_is_reliable (sock)) {
+ guint16 rfc4571_frame = htons (len);
+ GOutputVector local_buf[2] = {{&rfc4571_frame, 2}, { buf, len }};
+ NiceOutputMessage local_message = { local_buf, 2};
+ gint ret;
+
+ /* ICE-TCP requires that all packets be framed with RFC4571 */
+ ret = nice_socket_send_messages_reliable (sock, addr, &local_message, 1);
+ if (ret == 1)
+ return len;
+ return ret;
+ } else {
+ gssize ret = nice_socket_send_reliable (sock, addr, len, buf);
+ if (ret < 0)
+ ret = nice_socket_send (sock, addr, len, buf);
+ return ret;
+ }
+}
+
+NiceComponentState
+nice_agent_get_component_state (NiceAgent *agent,
+ guint stream_id, guint component_id)
+{
+ NiceComponentState state = NICE_COMPONENT_STATE_FAILED;
+ NiceComponent *component;
+
+ agent_lock (agent);
+
+ if (agent_find_component (agent, stream_id, component_id, NULL, &component))
+ state = component->state;
+
+ agent_unlock (agent);
+
+ return state;
+}
+
+gboolean
+nice_agent_peer_candidate_gathering_done (NiceAgent *agent, guint stream_id)
+{
+ NiceStream *stream;
+ gboolean result = FALSE;
+
+ agent_lock (agent);
+
+ stream = agent_find_stream (agent, stream_id);
+ if (stream) {
+ stream->peer_gathering_done = TRUE;
+ result = TRUE;
+ }
+
+ agent_unlock (agent);
+
+ return result;
+}
+
+static gboolean
+on_agent_refreshes_pruned (NiceAgent *agent, gpointer user_data)
+{
+ GTask *task = user_data;
+
+ /* This is called from a timeout cb with agent lock held */
+
+ agent_unlock (agent);
+
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
+
+ agent_lock (agent);
+
+ return G_SOURCE_REMOVE;
+}
+
+void
+nice_agent_close_async (NiceAgent *agent, GAsyncReadyCallback callback,
+ gpointer callback_data)
+{
+ GTask *task;
+
+ task = g_task_new (agent, NULL, callback, callback_data);
+ g_task_set_source_tag (task, nice_agent_close_async);
+
+ agent_lock (agent);
+
+ refresh_prune_agent_async (agent, on_agent_refreshes_pruned, task);
+
+ agent_unlock (agent);
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2006-2010 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2006-2010 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Dafydd Harries, Collabora Ltd.
+ * Youness Alaoui, Collabora Ltd.
+ * Kai Vehmanen, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef __LIBNICE_AGENT_H__
+#define __LIBNICE_AGENT_H__
+
+/**
+ * SECTION:agent
+ * @short_description: ICE agent API implementation
+ * @see_also: #NiceCandidate, #NiceAddress
+ * @include: agent.h
+ * @stability: Stable
+ *
+ * The #NiceAgent is your main object when using libnice.
+ * It is the agent that will take care of everything relating to ICE.
+ * It will take care of discovering your local candidates and do
+ * connectivity checks to create a stream of data between you and your peer.
+ *
+ * A #NiceAgent must always be used with a #GMainLoop running the #GMainContext
+ * passed into nice_agent_new() (or nice_agent_new_reliable()). Without the
+ * #GMainContext being iterated, the agent’s timers will not fire, etc.
+ *
+ * Streams and their components are referenced by integer IDs (with respect to a
+ * given #NiceAgent). These IDs are guaranteed to be positive (i.e. non-zero)
+ * for valid streams/components.
+ *
+ * To complete the ICE connectivity checks, the user must either register
+ * an I/O callback (with nice_agent_attach_recv()) or call nice_agent_recv_messages()
+ * in a loop on a dedicated thread.
+ * Technically, #NiceAgent does not poll the streams on its own, since
+ * user data could arrive at any time; to receive STUN packets
+ * required for establishing ICE connectivity, it is backpiggying
+ * on the facility chosen by the user. #NiceAgent will handle all STUN
+ * packets internally; they're never actually passed to the I/O callback
+ * or returned from nice_agent_recv_messages() and related functions.
+ *
+ * Each stream can receive data in one of two ways: using
+ * nice_agent_attach_recv() or nice_agent_recv_messages() (and the derived
+ * #NiceInputStream and #NiceIOStream classes accessible using
+ * nice_agent_get_io_stream()). nice_agent_attach_recv() is non-blocking: it
+ * takes a user-provided callback function and attaches the stream’s socket to
+ * the provided #GMainContext, invoking the callback in that context for every
+ * packet received. nice_agent_recv_messages() instead blocks on receiving a
+ * packet, and writes it directly into a user-provided buffer. This reduces the
+ * number of callback invokations and (potentially) buffer copies required to
+ * receive packets. nice_agent_recv_messages() (or #NiceInputStream) is designed
+ * to be used in a blocking loop in a separate thread.
+ *
+ * <example>
+ * <title>Simple example on how to use libnice</title>
+ * <programlisting>
+ * guint stream_id;
+ * gchar buffer[] = "hello world!";
+ * gchar *ufrag = NULL, *pwd = NULL;
+ * gchar *remote_ufrag, *remote_pwd;
+ * GSList *lcands = NULL;
+ *
+ * // Create a nice agent, passing in the global default GMainContext.
+ * NiceAgent *agent = nice_agent_new (NULL, NICE_COMPATIBILITY_RFC5245);
+ * spawn_thread_to_run_main_loop (g_main_loop_new (NULL, FALSE));
+ *
+ * // Connect the signals
+ * g_signal_connect (G_OBJECT (agent), "candidate-gathering-done",
+ * G_CALLBACK (cb_candidate_gathering_done), NULL);
+ * g_signal_connect (G_OBJECT (agent), "component-state-changed",
+ * G_CALLBACK (cb_component_state_changed), NULL);
+ * g_signal_connect (G_OBJECT (agent), "new-selected-pair",
+ * G_CALLBACK (cb_new_selected_pair), NULL);
+ *
+ * // Create a new stream with one component and start gathering candidates
+ * stream_id = nice_agent_add_stream (agent, 1);
+ * nice_agent_gather_candidates (agent, stream_id);
+ *
+ * // Attach I/O callback the component to ensure that:
+ * // 1) agent gets its STUN packets (not delivered to cb_nice_recv)
+ * // 2) you get your own data
+ * nice_agent_attach_recv (agent, stream_id, 1, NULL,
+ * cb_nice_recv, NULL);
+ *
+ * // ... Wait until the signal candidate-gathering-done is fired ...
+ * lcands = nice_agent_get_local_candidates(agent, stream_id, 1);
+
+ * nice_agent_get_local_credentials(agent, stream_id, &ufrag, &pwd);
+ *
+ * // ... Send local candidates and credentials to the peer
+ *
+ * // Set the peer's remote credentials and remote candidates
+ * nice_agent_set_remote_credentials (agent, stream_id, remote_ufrag, remote_pwd);
+ * nice_agent_set_remote_candidates (agent, stream_id, 1, rcands);
+ *
+ * // ... Wait until the signal new-selected-pair is fired ...
+ * // Send our message!
+ * nice_agent_send (agent, stream_id, 1, sizeof(buffer), buffer);
+ *
+ * // Anything received will be received through the cb_nice_recv callback.
+ * // You must be running a GMainLoop on the global default GMainContext in
+ * // another thread for this to work.
+ *
+ * // Destroy the object
+ * g_object_unref(agent);
+ *
+ * </programlisting>
+ * </example>
+ *
+ * Refer to the examples in the examples/ subdirectory of the libnice source for
+ * more complete examples.
+ *
+ */
+
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+/**
+ * NiceAgent:
+ *
+ * The #NiceAgent is the main GObject of the libnice library and represents
+ * the ICE agent.
+ */
+typedef struct _NiceAgent NiceAgent;
+
+#include "address.h"
+#include "candidate.h"
+#include "debug.h"
+
+
+G_BEGIN_DECLS
+
+/**
+ * NiceInputMessage:
+ * @buffers: (array length=n_buffers): unowned array of #GInputVector buffers to
+ * store data in for this message
+ * @n_buffers: number of #GInputVectors in @buffers, or -1 to indicate @buffers
+ * is %NULL-terminated
+ * @from: (allow-none): return location to store the address of the peer who
+ * transmitted the message, or %NULL
+ * @length: total number of valid bytes contiguously stored in @buffers
+ *
+ * Represents a single message received off the network. For reliable
+ * connections, this is essentially just an array of buffers (specifically,
+ * @from can be ignored). for non-reliable connections, it represents a single
+ * packet as received from the OS.
+ *
+ * @n_buffers may be -1 to indicate that @buffers is terminated by a
+ * #GInputVector with a %NULL buffer pointer.
+ *
+ * By providing arrays of #NiceInputMessages to functions like
+ * nice_agent_recv_messages(), multiple messages may be received with a single
+ * call, which is more efficient than making multiple calls in a loop. In this
+ * manner, nice_agent_recv_messages() is analogous to recvmmsg(); and
+ * #NiceInputMessage to struct mmsghdr.
+ *
+ * Since: 0.1.5
+ */
+typedef struct {
+ GInputVector *buffers;
+ gint n_buffers; /* may be -1 to indicate @buffers is NULL-terminated */
+ NiceAddress *from; /* return location for address of message sender */
+ gsize length; /* sum of the lengths of @buffers */
+} NiceInputMessage;
+
+/**
+ * NiceOutputMessage:
+ * @buffers: (array length=n_buffers): unowned array of #GOutputVector buffers
+ * which contain data to transmit for this message
+ * @n_buffers: number of #GOutputVectors in @buffers, or -1 to indicate @buffers
+ * is %NULL-terminated
+ *
+ * Represents a single message to transmit on the network. For
+ * reliable connections, this is essentially just an array of
+ * buffer. for non-reliable connections, it represents a single packet
+ * to send to the OS.
+ *
+ * @n_buffers may be -1 to indicate that @buffers is terminated by a
+ * #GOutputVector with a %NULL buffer pointer.
+ *
+ * By providing arrays of #NiceOutputMessages to functions like
+ * nice_agent_send_messages_nonblocking(), multiple messages may be transmitted
+ * with a single call, which is more efficient than making multiple calls in a
+ * loop. In this manner, nice_agent_send_messages_nonblocking() is analogous to
+ * sendmmsg(); and #NiceOutputMessage to struct mmsghdr.
+ *
+ * Since: 0.1.5
+ */
+typedef struct {
+ GOutputVector *buffers;
+ gint n_buffers;
+} NiceOutputMessage;
+
+
+#define NICE_TYPE_AGENT nice_agent_get_type()
+
+#define NICE_AGENT(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
+ NICE_TYPE_AGENT, NiceAgent))
+
+#define NICE_AGENT_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), \
+ NICE_TYPE_AGENT, NiceAgentClass))
+
+#define NICE_IS_AGENT(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
+ NICE_TYPE_AGENT))
+
+#define NICE_IS_AGENT_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), \
+ NICE_TYPE_AGENT))
+
+#define NICE_AGENT_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), \
+ NICE_TYPE_AGENT, NiceAgentClass))
+
+typedef struct _NiceAgentClass NiceAgentClass;
+
+struct _NiceAgentClass
+{
+ GObjectClass parent_class;
+};
+
+
+GType nice_agent_get_type (void);
+
+
+/**
+ * NICE_AGENT_MAX_REMOTE_CANDIDATES:
+ *
+ * A hard limit for the number of remote candidates. This
+ * limit is enforced to protect against malevolent remote
+ * clients.
+ */
+#define NICE_AGENT_MAX_REMOTE_CANDIDATES 25
+
+/**
+ * NiceComponentState:
+ * @NICE_COMPONENT_STATE_DISCONNECTED: No activity scheduled
+ * @NICE_COMPONENT_STATE_GATHERING: Gathering local candidates
+ * @NICE_COMPONENT_STATE_CONNECTING: Establishing connectivity
+ * @NICE_COMPONENT_STATE_CONNECTED: At least one working candidate pair
+ * @NICE_COMPONENT_STATE_READY: ICE concluded, candidate pair selection
+ * is now final
+ * @NICE_COMPONENT_STATE_FAILED: Connectivity checks have been completed,
+ * but connectivity was not established
+ * @NICE_COMPONENT_STATE_LAST: Dummy state
+ *
+ * An enum representing the state of a component.
+ * <para> See also: #NiceAgent::component-state-changed </para>
+ */
+typedef enum
+{
+ NICE_COMPONENT_STATE_DISCONNECTED,
+ NICE_COMPONENT_STATE_GATHERING,
+ NICE_COMPONENT_STATE_CONNECTING,
+ NICE_COMPONENT_STATE_CONNECTED,
+ NICE_COMPONENT_STATE_READY,
+ NICE_COMPONENT_STATE_FAILED,
+ NICE_COMPONENT_STATE_LAST
+} NiceComponentState;
+
+
+/**
+ * NiceComponentType:
+ * @NICE_COMPONENT_TYPE_RTP: RTP Component type
+ * @NICE_COMPONENT_TYPE_RTCP: RTCP Component type
+ *
+ * Convenience enum representing the type of a component for use as the
+ * component_id for RTP/RTCP usages.
+ <example>
+ <title>Example of use.</title>
+ <programlisting>
+ nice_agent_send (agent, stream_id, NICE_COMPONENT_TYPE_RTP, len, buf);
+ </programlisting>
+ </example>
+ */
+typedef enum
+{
+ NICE_COMPONENT_TYPE_RTP = 1,
+ NICE_COMPONENT_TYPE_RTCP = 2
+} NiceComponentType;
+
+
+/**
+ * NiceCompatibility:
+ * @NICE_COMPATIBILITY_RFC5245: Use compatibility with the RFC5245 ICE-UDP specs
+ * and RFC6544 ICE-TCP specs
+ * @NICE_COMPATIBILITY_GOOGLE: Use compatibility for Google Talk specs
+ * @NICE_COMPATIBILITY_MSN: Use compatibility for MSN Messenger specs
+ * @NICE_COMPATIBILITY_WLM2009: Use compatibility with Windows Live Messenger
+ * 2009
+ * @NICE_COMPATIBILITY_OC2007: Use compatibility with Microsoft Office Communicator 2007
+ * @NICE_COMPATIBILITY_OC2007R2: Use compatibility with Microsoft Office Communicator 2007 R2
+ * @NICE_COMPATIBILITY_DRAFT19: Use compatibility for ICE Draft 19 specs
+ * @NICE_COMPATIBILITY_LAST: Dummy last compatibility mode
+ *
+ * An enum to specify which compatible specifications the #NiceAgent should use.
+ * Use with nice_agent_new()
+ *
+ * <warning>@NICE_COMPATIBILITY_DRAFT19 is deprecated and should not be used
+ * in newly-written code. It is kept for compatibility reasons and
+ * represents the same compatibility as @NICE_COMPATIBILITY_RFC5245 </warning>
+ <note>
+ <para>
+ If @NICE_COMPATIBILITY_RFC5245 compatibility mode is used for a non-reliable
+ agent, then ICE-UDP will be used with higher priority and ICE-TCP will also
+ be used when the UDP connectivity fails. If it is used with a reliable agent,
+ then ICE-UDP will be used with the TCP-Over-UDP (#PseudoTcpSocket) if ICE-TCP
+ fails and ICE-UDP succeeds.
+ </para>
+ </note>
+ *
+ */
+typedef enum
+{
+ NICE_COMPATIBILITY_RFC5245 = 0,
+ NICE_COMPATIBILITY_DRAFT19 = NICE_COMPATIBILITY_RFC5245,
+ NICE_COMPATIBILITY_GOOGLE,
+ NICE_COMPATIBILITY_MSN,
+ NICE_COMPATIBILITY_WLM2009,
+ NICE_COMPATIBILITY_OC2007,
+ NICE_COMPATIBILITY_OC2007R2,
+ NICE_COMPATIBILITY_LAST = NICE_COMPATIBILITY_OC2007R2,
+} NiceCompatibility;
+
+/**
+ * NiceProxyType:
+ * @NICE_PROXY_TYPE_NONE: Do not use a proxy
+ * @NICE_PROXY_TYPE_SOCKS5: Use a SOCKS5 proxy
+ * @NICE_PROXY_TYPE_HTTP: Use an HTTP proxy
+ * @NICE_PROXY_TYPE_LAST: Dummy last proxy type
+ *
+ * An enum to specify which proxy type to use for relaying.
+ * Note that the proxies will only be used with TCP TURN relaying.
+ * <para> See also: #NiceAgent:proxy-type </para>
+ *
+ * Since: 0.0.4
+ */
+typedef enum
+{
+ NICE_PROXY_TYPE_NONE = 0,
+ NICE_PROXY_TYPE_SOCKS5,
+ NICE_PROXY_TYPE_HTTP,
+ NICE_PROXY_TYPE_LAST = NICE_PROXY_TYPE_HTTP,
+} NiceProxyType;
+
+/**
+ * NiceNominationMode:
+ * @NICE_NOMINATION_MODE_AGGRESSIVE: Aggressive nomination mode
+ * @NICE_NOMINATION_MODE_REGULAR: Regular nomination mode
+ *
+ * An enum to specity the kind of nomination mode to use by
+ * the agent, as described in RFC 5245. Two modes exists,
+ * regular and aggressive. They differ by the way the controlling
+ * agent chooses to put the USE-CANDIDATE attribute in its STUN
+ * messages. The aggressive mode is supposed to nominate a pair
+ * faster, than the regular mode, potentially causing the nominated
+ * pair to change until the connection check completes.
+ *
+ * Since: 0.1.15
+ */
+typedef enum
+{
+ NICE_NOMINATION_MODE_REGULAR = 0,
+ NICE_NOMINATION_MODE_AGGRESSIVE,
+} NiceNominationMode;
+
+/**
+ * NiceAgentOption:
+ * @NICE_AGENT_OPTION_REGULAR_NOMINATION: Enables regular nomination, default
+ * is aggrssive mode (see #NiceNominationMode).
+ * @NICE_AGENT_OPTION_RELIABLE: Enables reliable mode, possibly using PseudoTCP, * see nice_agent_new_reliable().
+ * @NICE_AGENT_OPTION_LITE_MODE: Enable lite mode
+ * @NICE_AGENT_OPTION_ICE_TRICKLE: Enable ICE trickle mode
+ * @NICE_AGENT_OPTION_SUPPORT_RENOMINATION: Enable renomination triggered by NOMINATION STUN attribute
+ * proposed here: https://tools.ietf.org/html/draft-thatcher-ice-renomination-00
+ *
+ * These are options that can be passed to nice_agent_new_full(). They set
+ * various properties on the agent. Not including them sets the property to
+ * the other value.
+ *
+ * Since: 0.1.15
+ */
+typedef enum {
+ NICE_AGENT_OPTION_REGULAR_NOMINATION = 1 << 0,
+ NICE_AGENT_OPTION_RELIABLE = 1 << 1,
+ NICE_AGENT_OPTION_LITE_MODE = 1 << 2,
+ NICE_AGENT_OPTION_ICE_TRICKLE = 1 << 3,
+ NICE_AGENT_OPTION_SUPPORT_RENOMINATION = 1 << 4,
+} NiceAgentOption;
+
+/**
+ * NiceAgentRecvFunc:
+ * @agent: The #NiceAgent Object
+ * @stream_id: The id of the stream
+ * @component_id: The id of the component of the stream
+ * which received the data
+ * @len: The length of the data
+ * @buf: The buffer containing the data received
+ * @user_data: The user data set in nice_agent_attach_recv()
+ *
+ * Callback function when data is received on a component
+ *
+ */
+typedef void (*NiceAgentRecvFunc) (
+ NiceAgent *agent, guint stream_id, guint component_id, guint len,
+ gchar *buf, gpointer user_data);
+
+
+/**
+ * nice_agent_new:
+ * @ctx: The Glib Mainloop Context to use for timers
+ * @compat: The compatibility mode of the agent
+ *
+ * Create a new #NiceAgent.
+ * The returned object must be freed with g_object_unref()
+ *
+ * Returns: The new agent GObject
+ */
+NiceAgent *
+nice_agent_new (GMainContext *ctx, NiceCompatibility compat);
+
+
+/**
+ * nice_agent_new_reliable:
+ * @ctx: The Glib Mainloop Context to use for timers
+ * @compat: The compatibility mode of the agent
+ *
+ * Create a new #NiceAgent in reliable mode. If the connectivity is established
+ * through ICE-UDP, then a #PseudoTcpSocket will be transparently used to
+ * ensure reliability of the messages.
+ * The returned object must be freed with g_object_unref()
+ * <para> See also: #NiceAgent::reliable-transport-writable </para>
+ *
+ * Since: 0.0.11
+ *
+ * Returns: The new agent GObject
+ */
+NiceAgent *
+nice_agent_new_reliable (GMainContext *ctx, NiceCompatibility compat);
+
+/**
+ * nice_agent_new_full:
+ * @ctx: The Glib Mainloop Context to use for timers
+ * @compat: The compatibility mode of the agent
+ * @flags: Flags to set the properties
+ *
+ * Create a new #NiceAgent with parameters that must be be defined at
+ * construction time.
+ * The returned object must be freed with g_object_unref()
+ * <para> See also: #NiceNominationMode and #NiceAgentOption</para>
+ *
+ * Since: 0.1.15
+ *
+ * Returns: The new agent GObject
+ */
+NiceAgent *
+nice_agent_new_full (GMainContext *ctx,
+ NiceCompatibility compat,
+ NiceAgentOption flags);
+
+/**
+ * nice_agent_add_local_address:
+ * @agent: The #NiceAgent Object
+ * @addr: The address to listen to
+ * If the port is 0, then a random port will be chosen by the system
+ *
+ * Add a local address from which to derive local host candidates for
+ * candidate gathering.
+ * <para>
+ * Since 0.0.5, if this method is not called, libnice will automatically
+ * discover the local addresses available
+ * </para>
+ *
+ * See also: nice_agent_gather_candidates()
+ * Returns: %TRUE on success, %FALSE on fatal (memory allocation) errors
+ */
+gboolean
+nice_agent_add_local_address (NiceAgent *agent, NiceAddress *addr);
+
+/**
+ * nice_agent_add_stream:
+ * @agent: The #NiceAgent Object
+ * @n_components: The number of components to add to the stream
+ *
+ * Adds a data stream to @agent containing @n_components components. The
+ * returned stream ID is guaranteed to be positive on success.
+ *
+ * Returns: The ID of the new stream, 0 on failure
+ **/
+guint
+nice_agent_add_stream (
+ NiceAgent *agent,
+ guint n_components);
+
+/**
+ * nice_agent_remove_stream:
+ * @agent: The #NiceAgent Object
+ * @stream_id: The ID of the stream to remove
+ *
+ * Remove and free a previously created data stream from @agent. If any I/O
+ * streams have been created using nice_agent_get_io_stream(), they should be
+ * closed completely using g_io_stream_close() before this is called, or they
+ * will get broken pipe errors.
+ *
+ **/
+void
+nice_agent_remove_stream (
+ NiceAgent *agent,
+ guint stream_id);
+
+
+/**
+ * nice_agent_set_port_range:
+ * @agent: The #NiceAgent Object
+ * @stream_id: The ID of the stream
+ * @component_id: The ID of the component
+ * @min_port: The minimum port to use
+ * @max_port: The maximum port to use
+ *
+ * Sets a preferred port range for allocating host candidates.
+ * <para>
+ * If a local host candidate cannot be created on that port
+ * range, then the nice_agent_gather_candidates() call will fail.
+ * </para>
+ * <para>
+ * This MUST be called before nice_agent_gather_candidates()
+ * </para>
+ *
+ */
+void
+nice_agent_set_port_range (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ guint min_port,
+ guint max_port);
+
+/**
+ * nice_agent_set_relay_info:
+ * @agent: The #NiceAgent Object
+ * @stream_id: The ID of the stream
+ * @component_id: The ID of the component
+ * @server_ip: The IP address of the TURN server
+ * @server_port: The port of the TURN server
+ * @username: The TURN username to use for the allocate
+ * @password: The TURN password to use for the allocate
+ * @type: The type of relay to use
+ *
+ * Sets the settings for using a relay server during the candidate discovery.
+ * This may be called multiple times to add multiple relay servers to the
+ * discovery process; one TCP and one UDP, for example.
+ *
+ * Returns: %TRUE if the TURN settings were accepted.
+ * %FALSE if the address was invalid.
+ */
+gboolean nice_agent_set_relay_info(
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ const gchar *server_ip,
+ guint server_port,
+ const gchar *username,
+ const gchar *password,
+ NiceRelayType type);
+
+/**
+ * nice_agent_gather_candidates:
+ * @agent: The #NiceAgent object
+ * @stream_id: The ID of the stream to start
+ *
+ * Allocate and start listening on local candidate ports and start the remote
+ * candidate gathering process.
+ * Once done, #NiceAgent::candidate-gathering-done is called for the stream.
+ * As soon as this function is called, #NiceAgent::new-candidate signals may be
+ * emitted, even before this function returns.
+ *
+ * nice_agent_get_local_candidates() will only return non-empty results after
+ * calling this function.
+ *
+ * <para>See also: nice_agent_add_local_address()</para>
+ * <para>See also: nice_agent_set_port_range()</para>
+ *
+ * Returns: %FALSE if the stream ID is invalid or if a host candidate couldn't
+ * be allocated on the requested interfaces/ports; %TRUE otherwise
+ *
+ <note>
+ <para>
+ Local addresses can be previously set with nice_agent_add_local_address()
+ </para>
+ <para>
+ Since 0.0.5, If no local address was previously added, then the nice agent
+ will automatically detect the local address using
+ nice_interfaces_get_local_ips()
+ </para>
+ </note>
+ */
+gboolean
+nice_agent_gather_candidates (
+ NiceAgent *agent,
+ guint stream_id);
+
+/**
+ * nice_agent_set_remote_credentials:
+ * @agent: The #NiceAgent Object
+ * @stream_id: The ID of the stream
+ * @ufrag: nul-terminated string containing an ICE username fragment
+ * (length must be between 22 and 256 chars)
+ * @pwd: nul-terminated string containing an ICE password
+ * (length must be between 4 and 256 chars)
+ *
+ * Sets the remote credentials for stream @stream_id.
+ *
+ <note>
+ <para>
+ Stream credentials do not override per-candidate credentials if set
+ </para>
+ <para>
+ Due to the native of peer-reflexive candidates, any agent using a per-stream
+ credentials (RFC5245, WLM2009, OC2007R2 and DRAFT19) instead of
+ per-candidate credentials (GOOGLE, MSN, OC2007), must
+ use the nice_agent_set_remote_credentials() API instead of setting the
+ username and password on the candidates.
+ </para>
+ </note>
+ *
+ * Returns: %TRUE on success, %FALSE on error.
+ */
+gboolean
+nice_agent_set_remote_credentials (
+ NiceAgent *agent,
+ guint stream_id,
+ const gchar *ufrag, const gchar *pwd);
+
+
+/**
+ * nice_agent_set_local_credentials:
+ * @agent: The #NiceAgent Object
+ * @stream_id: The ID of the stream
+ * @ufrag: nul-terminated string containing an ICE username fragment
+ * (length must be between 22 and 256 chars)
+ * @pwd: nul-terminated string containing an ICE password
+ * (length must be between 4 and 256 chars)
+ *
+ * Sets the local credentials for stream @stream_id.
+ *
+ <note>
+ <para>
+ This is only effective before ICE negotiation has started.
+ </para>
+ </note>
+ *
+ * Since 0.1.11
+ * Returns: %TRUE on success, %FALSE on error.
+ */
+gboolean
+nice_agent_set_local_credentials (
+ NiceAgent *agent,
+ guint stream_id,
+ const gchar *ufrag,
+ const gchar *pwd);
+
+
+/**
+ * nice_agent_get_local_credentials:
+ * @agent: The #NiceAgent Object
+ * @stream_id: The ID of the stream
+ * @ufrag: (out callee-allocates): return location for a nul-terminated string
+ * containing an ICE username fragment; must be freed with g_free()
+ * @pwd: (out callee-allocates): return location for a nul-terminated string
+ * containing an ICE password; must be freed with g_free()
+ *
+ * Gets the local credentials for stream @stream_id. This may be called any time
+ * after creating a stream using nice_agent_add_stream().
+ *
+ * An error will be returned if this is called for a non-existent stream, or if
+ * either of @ufrag or @pwd are %NULL.
+ *
+ * Returns: %TRUE on success, %FALSE on error.
+ */
+gboolean
+nice_agent_get_local_credentials (
+ NiceAgent *agent,
+ guint stream_id,
+ gchar **ufrag, gchar **pwd);
+
+/**
+ * nice_agent_set_remote_candidates:
+ * @agent: The #NiceAgent Object
+ * @stream_id: The ID of the stream the candidates are for
+ * @component_id: The ID of the component the candidates are for
+ * @candidates: (element-type NiceCandidate) (transfer none): a #GSList of
+ * #NiceCandidate items describing each candidate to add
+ *
+ * Sets, adds or updates the remote candidates for a component of a stream.
+ *
+ <note>
+ <para>
+ NICE_AGENT_MAX_REMOTE_CANDIDATES is the absolute maximum limit
+ for remote candidates.
+ </para>
+ <para>
+ You must first call nice_agent_gather_candidates() and wait for the
+ #NiceAgent::candidate-gathering-done signale before
+ calling nice_agent_set_remote_candidates()
+ </para>
+ <para>
+ Since 0.1.3, there is no need to wait for the candidate-gathering-done signal.
+ Remote candidates can be set even while gathering local candidates.
+ Newly discovered local candidates will automatically be paired with
+ existing remote candidates.
+ </para>
+ </note>
+ *
+ * Returns: The number of candidates added, negative on errors (memory
+ * allocation error or invalid component)
+ **/
+int
+nice_agent_set_remote_candidates (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ const GSList *candidates);
+
+
+/**
+ * nice_agent_send:
+ * @agent: The #NiceAgent Object
+ * @stream_id: The ID of the stream to send to
+ * @component_id: The ID of the component to send to
+ * @len: The length of the buffer to send
+ * @buf: The buffer of data to send
+ *
+ * Sends a data payload over a stream's component.
+ *
+ <note>
+ <para>
+ Component state MUST be NICE_COMPONENT_STATE_READY, or as a special case,
+ in any state if component was in READY state before and was then restarted
+ </para>
+ <para>
+ In reliable mode, the -1 error value means either that you are not yet
+ connected or that the send buffer is full (equivalent to EWOULDBLOCK).
+ In both cases, you simply need to wait for the
+ #NiceAgent::reliable-transport-writable signal to be fired before resending
+ the data.
+ </para>
+ <para>
+ In non-reliable mode, it will virtually never happen with UDP sockets, but
+ it might happen if the active candidate is a TURN-TCP connection that got
+ disconnected.
+ </para>
+ <para>
+ In both reliable and non-reliable mode, a -1 error code could also mean that
+ the stream_id and/or component_id are invalid.
+ </para>
+</note>
+ *
+ * Returns: The number of bytes sent, or negative error code
+ */
+gint
+nice_agent_send (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ guint len,
+ const gchar *buf);
+
+/**
+ * nice_agent_send_messages_nonblocking:
+ * @agent: a #NiceAgent
+ * @stream_id: the ID of the stream to send to
+ * @component_id: the ID of the component to send to
+ * @messages: (array length=n_messages): array of messages to send, of at least
+ * @n_messages entries in length
+ * @n_messages: number of entries in @messages
+ * @cancellable: (allow-none): a #GCancellable to cancel the operation from
+ * another thread, or %NULL
+ * @error: (allow-none): return location for a #GError, or %NULL
+ *
+ * Sends multiple messages on the socket identified by the given
+ * stream/component pair. Transmission is non-blocking, so a
+ * %G_IO_ERROR_WOULD_BLOCK error may be returned if the send buffer is full.
+ *
+ * As with nice_agent_send(), the given component must be in
+ * %NICE_COMPONENT_STATE_READY or, as a special case, in any state if it was
+ * previously ready and was then restarted.
+ *
+ * On success, the number of messages written to the socket will be returned,
+ * which may be less than @n_messages if transmission would have blocked
+ * part-way through. Zero will be returned if @n_messages is zero, or if
+ * transmission would have blocked on the first message.
+ *
+ * In reliable mode, it is instead recommended to use
+ * nice_agent_send(). The return value can be less than @n_messages
+ * or 0 even if it is still possible to send a partial message. In
+ * this case, "nice-agent-writable" will never be triggered, so the
+ * application would have to use nice_agent_sent() to fill the buffer or have
+ * to retry sending at a later point.
+ *
+ * On failure, -1 will be returned and @error will be set. If the #NiceAgent is
+ * reliable and the socket is not yet connected, %G_IO_ERROR_BROKEN_PIPE will be
+ * returned; if the write buffer is full, %G_IO_ERROR_WOULD_BLOCK will be
+ * returned. In both cases, wait for the #NiceAgent::reliable-transport-writable
+ * signal before trying again. If the given @stream_id or @component_id are
+ * invalid or not yet connected, %G_IO_ERROR_BROKEN_PIPE will be returned.
+ * %G_IO_ERROR_FAILED will be returned for other errors.
+ *
+ * Returns: the number of messages sent (may be zero), or -1 on error
+ *
+ * Since: 0.1.5
+ */
+gint
+nice_agent_send_messages_nonblocking (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ const NiceOutputMessage *messages,
+ guint n_messages,
+ GCancellable *cancellable,
+ GError **error);
+
+/**
+ * nice_agent_get_local_candidates:
+ * @agent: The #NiceAgent Object
+ * @stream_id: The ID of the stream
+ * @component_id: The ID of the component
+ *
+ * Retrieve from the agent the list of all local candidates
+ * for a stream's component
+ *
+ <note>
+ <para>
+ The caller owns the returned GSList as well as the candidates contained
+ within it.
+ To get full results, the client should wait for the
+ #NiceAgent::candidate-gathering-done signal.
+ </para>
+ </note>
+ *
+ * Returns: (element-type NiceCandidate) (transfer full): a #GSList of
+ * #NiceCandidate objects representing the local candidates of @agent
+ **/
+GSList *
+nice_agent_get_local_candidates (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id);
+
+
+/**
+ * nice_agent_get_remote_candidates:
+ * @agent: The #NiceAgent Object
+ * @stream_id: The ID of the stream
+ * @component_id: The ID of the component
+ *
+ * Get a list of the remote candidates set on a stream's component
+ *
+ <note>
+ <para>
+ The caller owns the returned GSList as well as the candidates contained
+ within it.
+ </para>
+ <para>
+ The list of remote candidates can change during processing.
+ The client should register for the #NiceAgent::new-remote-candidate signal
+ to get notified of new remote candidates.
+ </para>
+ </note>
+ *
+ * Returns: (element-type NiceCandidate) (transfer full): a #GSList of
+ * #NiceCandidates objects representing the remote candidates set on the @agent
+ **/
+GSList *
+nice_agent_get_remote_candidates (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id);
+
+/**
+ * nice_agent_restart:
+ * @agent: The #NiceAgent Object
+ *
+ * Restarts the session as defined in ICE draft 19. This function
+ * needs to be called both when initiating (ICE spec section 9.1.1.1.
+ * "ICE Restarts"), as well as when reacting (spec section 9.2.1.1.
+ * "Detecting ICE Restart") to a restart.
+ *
+ * Returns: %TRUE on success %FALSE on error
+ **/
+gboolean
+nice_agent_restart (
+ NiceAgent *agent);
+
+/**
+ * nice_agent_restart_stream:
+ * @agent: The #NiceAgent Object
+ * @stream_id: The ID of the stream
+ *
+ * Restarts a single stream as defined in RFC 5245. This function
+ * needs to be called both when initiating (ICE spec section 9.1.1.1.
+ * "ICE Restarts"), as well as when reacting (spec section 9.2.1.1.
+ * "Detecting ICE Restart") to a restart.
+ *
+ * Unlike nice_agent_restart(), this applies to a single stream. It also
+ * does not generate a new tie breaker.
+ *
+ * Returns: %TRUE on success %FALSE on error
+ *
+ * Since: 0.1.6
+ **/
+gboolean
+nice_agent_restart_stream (
+ NiceAgent *agent,
+ guint stream_id);
+
+
+/**
+ * nice_agent_attach_recv: (skip)
+ * @agent: The #NiceAgent Object
+ * @stream_id: The ID of stream
+ * @component_id: The ID of the component
+ * @ctx: The Glib Mainloop Context to use for listening on the component
+ * @func: The callback function to be called when data is received on
+ * the stream's component (will not be called for STUN messages that
+ * should be handled by #NiceAgent itself)
+ * @data: user data associated with the callback
+ *
+ * Attaches the stream's component's sockets to the Glib Mainloop Context in
+ * order to be notified whenever data becomes available for a component,
+ * and to enable #NiceAgent to receive STUN messages (during the
+ * establishment of ICE connectivity).
+ *
+ * This must not be used in combination with nice_agent_recv_messages() (or
+ * #NiceIOStream or #NiceInputStream) on the same stream/component pair.
+ *
+ * Calling nice_agent_attach_recv() with a %NULL @func will detach any existing
+ * callback and cause reception to be paused for the given stream/component
+ * pair. You must iterate the previously specified #GMainContext sufficiently to
+ * ensure all pending I/O callbacks have been received before calling this
+ * function to unset @func, otherwise data loss of received packets may occur.
+ *
+ * Returns: %TRUE on success, %FALSE if the stream or component IDs are invalid.
+ */
+gboolean
+nice_agent_attach_recv (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ GMainContext *ctx,
+ NiceAgentRecvFunc func,
+ gpointer data);
+
+/**
+ * nice_agent_recv:
+ * @agent: a #NiceAgent
+ * @stream_id: the ID of the stream to receive on
+ * @component_id: the ID of the component to receive on
+ * @buf: (array length=buf_len) (out caller-allocates): caller-allocated buffer
+ * to write the received data into, of length at least @buf_len
+ * @buf_len: length of @buf
+ * @cancellable: (allow-none): a #GCancellable to allow the operation to be
+ * cancelled from another thread, or %NULL
+ * @error: (allow-none): return location for a #GError, or %NULL
+ *
+ * A single-message version of nice_agent_recv_messages().
+ *
+ * Returns: the number of bytes written to @buf on success (guaranteed to be
+ * greater than 0 unless @buf_len is 0), 0 if in reliable mode and the remote
+ * peer closed the stream, or -1 on error
+ *
+ * Since: 0.1.5
+ */
+gssize
+nice_agent_recv (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ guint8 *buf,
+ gsize buf_len,
+ GCancellable *cancellable,
+ GError **error);
+
+/**
+ * nice_agent_recv_messages:
+ * @agent: a #NiceAgent
+ * @stream_id: the ID of the stream to receive on
+ * @component_id: the ID of the component to receive on
+ * @messages: (array length=n_messages) (out caller-allocates): caller-allocated
+ * array of #NiceInputMessages to write the received messages into, of length at
+ * least @n_messages
+ * @n_messages: number of entries in @messages
+ * @cancellable: (allow-none): a #GCancellable to allow the operation to be
+ * cancelled from another thread, or %NULL
+ * @error: (allow-none): return location for a #GError, or %NULL
+ *
+ * Block on receiving data from the given stream/component combination on
+ * @agent, returning only once exactly @n_messages messages have been received
+ * and written into @messages, the stream is closed by the other end or by
+ * calling nice_agent_remove_stream(), or @cancellable is cancelled.
+ *
+ * Any STUN packets received will not be added to @messages; instead,
+ * they'll be passed for processing to #NiceAgent itself. Since #NiceAgent
+ * does not poll for messages on its own, it's therefore essential to keep
+ * calling this function for ICE connection establishment to work.
+ *
+ * In the non-error case, in reliable mode, this will block until all buffers in
+ * all @n_messages have been filled with received data (i.e. @messages is
+ * treated as a large, flat array of buffers). In non-reliable mode, it will
+ * block until @n_messages messages have been received, each of which does not
+ * have to fill all the buffers in its #NiceInputMessage. In the non-reliable
+ * case, each #NiceInputMessage must have enough buffers to contain an entire
+ * message (65536 bytes), or any excess data may be silently dropped.
+ *
+ * For each received message, #NiceInputMessage::length will be set to the
+ * number of valid bytes stored in the message’s buffers. The bytes are stored
+ * sequentially in the buffers; there are no gaps apart from at the end of the
+ * buffer array (in non-reliable mode). If non-%NULL on input,
+ * #NiceInputMessage::from will have the address of the sending peer stored in
+ * it. The base addresses, sizes, and number of buffers in each message will not
+ * be modified in any case.
+ *
+ * This must not be used in combination with nice_agent_attach_recv() on the
+ * same stream/component pair.
+ *
+ * If the stream/component pair doesn’t exist, or if a suitable candidate socket
+ * hasn’t yet been selected for it, a %G_IO_ERROR_BROKEN_PIPE error will be
+ * returned. A %G_IO_ERROR_CANCELLED error will be returned if the operation was
+ * cancelled. %G_IO_ERROR_FAILED will be returned for other errors.
+ *
+ * Returns: the number of valid messages written to @messages on success
+ * (guaranteed to be greater than 0 unless @n_messages is 0), 0 if the remote
+ * peer closed the stream, or -1 on error
+ *
+ * Since: 0.1.5
+ */
+gint
+nice_agent_recv_messages (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ NiceInputMessage *messages,
+ guint n_messages,
+ GCancellable *cancellable,
+ GError **error);
+
+/**
+ * nice_agent_recv_nonblocking:
+ * @agent: a #NiceAgent
+ * @stream_id: the ID of the stream to receive on
+ * @component_id: the ID of the component to receive on
+ * @buf: (array length=buf_len) (out caller-allocates): caller-allocated buffer
+ * to write the received data into, of length at least @buf_len
+ * @buf_len: length of @buf
+ * @cancellable: (allow-none): a #GCancellable to allow the operation to be
+ * cancelled from another thread, or %NULL
+ * @error: (allow-none): return location for a #GError, or %NULL
+ *
+ * A single-message version of nice_agent_recv_messages_nonblocking().
+ *
+ * Returns: the number of bytes received into @buf on success (guaranteed to be
+ * greater than 0 unless @buf_len is 0), 0 if in reliable mode and the remote
+ * peer closed the stream, or -1 on error
+ *
+ * Since: 0.1.5
+ */
+gssize
+nice_agent_recv_nonblocking (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ guint8 *buf,
+ gsize buf_len,
+ GCancellable *cancellable,
+ GError **error);
+
+/**
+ * nice_agent_recv_messages_nonblocking:
+ * @agent: a #NiceAgent
+ * @stream_id: the ID of the stream to receive on
+ * @component_id: the ID of the component to receive on
+ * @messages: (array length=n_messages) (out caller-allocates): caller-allocated
+ * array of #NiceInputMessages to write the received messages into, of length at
+ * least @n_messages
+ * @n_messages: number of entries in @messages
+ * @cancellable: (allow-none): a #GCancellable to allow the operation to be
+ * cancelled from another thread, or %NULL
+ * @error: (allow-none): return location for a #GError, or %NULL
+ *
+ * Try to receive data from the given stream/component combination on @agent,
+ * without blocking. If receiving data would block, -1 is returned and
+ * %G_IO_ERROR_WOULD_BLOCK is set in @error. If any other error occurs, -1 is
+ * returned and @error is set accordingly. Otherwise, 0 is returned if (and only
+ * if) @n_messages is 0. In all other cases, the number of valid messages stored
+ * in @messages is returned, and will be greater than 0.
+ *
+ * This function behaves similarly to nice_agent_recv_messages(), except that it
+ * will not block on filling (in reliable mode) or receiving (in non-reliable
+ * mode) exactly @n_messages messages. In reliable mode, it will receive bytes
+ * into @messages until it would block; in non-reliable mode, it will receive
+ * messages until it would block.
+ *
+ * Any STUN packets received will not be added to @messages; instead,
+ * they'll be passed for processing to #NiceAgent itself. Since #NiceAgent
+ * does not poll for messages on its own, it's therefore essential to keep
+ * calling this function for ICE connection establishment to work.
+ *
+ * As this function is non-blocking, @cancellable is included only for parity
+ * with nice_agent_recv_messages(). If @cancellable is cancelled before this
+ * function is called, a %G_IO_ERROR_CANCELLED error will be returned
+ * immediately.
+ *
+ * This must not be used in combination with nice_agent_attach_recv() on the
+ * same stream/component pair.
+ *
+ * Returns: the number of valid messages written to @messages on success
+ * (guaranteed to be greater than 0 unless @n_messages is 0), 0 if in reliable
+ * mode and the remote peer closed the stream, or -1 on error
+ *
+ * Since: 0.1.5
+ */
+gint
+nice_agent_recv_messages_nonblocking (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ NiceInputMessage *messages,
+ guint n_messages,
+ GCancellable *cancellable,
+ GError **error);
+
+/**
+ * nice_agent_set_selected_pair:
+ * @agent: The #NiceAgent Object
+ * @stream_id: The ID of the stream
+ * @component_id: The ID of the component
+ * @lfoundation: The local foundation of the candidate to use
+ * @rfoundation: The remote foundation of the candidate to use
+ *
+ * Sets the selected candidate pair for media transmission
+ * for a given stream's component. Calling this function will
+ * disable all further ICE processing (connection check,
+ * state machine updates, etc). Note that keepalives will
+ * continue to be sent.
+ *
+ * Returns: %TRUE on success, %FALSE if the candidate pair cannot be found
+ */
+gboolean
+nice_agent_set_selected_pair (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ const gchar *lfoundation,
+ const gchar *rfoundation);
+
+/**
+ * nice_agent_get_selected_pair:
+ * @agent: The #NiceAgent Object
+ * @stream_id: The ID of the stream
+ * @component_id: The ID of the component
+ * @local: The local selected candidate
+ * @remote: The remote selected candidate
+ *
+ * Retreive the selected candidate pair for media transmission
+ * for a given stream's component.
+ *
+ * Returns: %TRUE on success, %FALSE if there is no selected candidate pair
+ */
+gboolean
+nice_agent_get_selected_pair (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ NiceCandidate **local,
+ NiceCandidate **remote);
+
+/**
+ * nice_agent_get_selected_socket:
+ * @agent: The #NiceAgent Object
+ * @stream_id: The ID of the stream
+ * @component_id: The ID of the component
+ *
+ * Retreive the local socket associated with the selected candidate pair
+ * for media transmission for a given stream's component.
+ *
+ * This is useful for adding ICE support to legacy applications that already
+ * have a protocol that maintains a connection. If the socket is duplicated
+ * before unrefing the agent, the application can take over and continue to use
+ * it. New applications are encouraged to use the built in libnice stream
+ * handling instead and let libnice handle the connection maintenance.
+ *
+ * Users of this method are encouraged to not use a TURN relay or any kind
+ * of proxy, as in this case, the socket will not be available to the
+ * application because the packets are encapsulated.
+ *
+ * Returns: (transfer full) (nullable): pointer to the #GSocket, or %NULL if
+ * there is no selected candidate or if the selected candidate is a relayed
+ * candidate.
+ *
+ * Since: 0.1.5
+ */
+GSocket *
+nice_agent_get_selected_socket (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id);
+
+/**
+ * nice_agent_set_selected_remote_candidate:
+ * @agent: The #NiceAgent Object
+ * @stream_id: The ID of the stream
+ * @component_id: The ID of the component
+ * @candidate: The #NiceCandidate to select
+ *
+ * Sets the selected remote candidate for media transmission
+ * for a given stream's component. This is used to force the selection of
+ * a specific remote candidate even when connectivity checks are failing
+ * (e.g. non-ICE compatible candidates).
+ * Calling this function will disable all further ICE processing
+ * (connection check, state machine updates, etc). Note that keepalives will
+ * continue to be sent.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ */
+gboolean
+nice_agent_set_selected_remote_candidate (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ NiceCandidate *candidate);
+
+
+/**
+ * nice_agent_set_stream_tos:
+ * @agent: The #NiceAgent Object
+ * @stream_id: The ID of the stream
+ * @tos: The ToS to set
+ *
+ * Sets the IP_TOS and/or IPV6_TCLASS field on the stream's sockets' options
+ *
+ * Since: 0.0.9
+ */
+void nice_agent_set_stream_tos (
+ NiceAgent *agent,
+ guint stream_id,
+ gint tos);
+
+
+
+/**
+ * nice_agent_set_software:
+ * @agent: The #NiceAgent Object
+ * @software: The value of the SOFTWARE attribute to add.
+ *
+ * This function will set the value of the SOFTWARE attribute to be added to
+ * STUN requests, responses and error responses sent during connectivity checks.
+ * <para>
+ * The SOFTWARE attribute will only be added in the #NICE_COMPATIBILITY_RFC5245
+ * and #NICE_COMPATIBILITY_WLM2009 compatibility modes.
+ *
+ * </para>
+ * <note>
+ <para>
+ The @software argument will be appended with the libnice version before
+ being sent.
+ </para>
+ <para>
+ The @software argument must be in UTF-8 encoding and only the first
+ 128 characters will be sent.
+ </para>
+ </note>
+ *
+ * Since: 0.0.10
+ *
+ */
+void nice_agent_set_software (
+ NiceAgent *agent,
+ const gchar *software);
+
+/**
+ * nice_agent_set_stream_name:
+ * @agent: The #NiceAgent Object
+ * @stream_id: The ID of the stream to change
+ * @name: The new name of the stream or %NULL
+ *
+ * This function will assign a media type to a stream. The only values
+ * that can be used to produce a valid SDP are: "audio", "video",
+ * "text", "application", "image" and "message".
+ *
+ * This is only useful when parsing and generating an SDP of the
+ * candidates.
+ *
+ * <para>See also: nice_agent_generate_local_sdp()</para>
+ * <para>See also: nice_agent_parse_remote_sdp()</para>
+ * <para>See also: nice_agent_get_stream_name()</para>
+ *
+ * Returns: %TRUE if the name has been set. %FALSE in case of error
+ * (invalid stream or duplicate name).
+ * Since: 0.1.4
+ */
+gboolean nice_agent_set_stream_name (
+ NiceAgent *agent,
+ guint stream_id,
+ const gchar *name);
+
+/**
+ * nice_agent_get_stream_name:
+ * @agent: The #NiceAgent Object
+ * @stream_id: The ID of the stream to change
+ *
+ * This function will return the name assigned to a stream.
+
+ * <para>See also: nice_agent_set_stream_name()</para>
+ *
+ * Returns: The name of the stream. The name is only valid while the stream
+ * exists or until it changes through a call to nice_agent_set_stream_name().
+ *
+ *
+ * Since: 0.1.4
+ */
+const gchar *nice_agent_get_stream_name (
+ NiceAgent *agent,
+ guint stream_id);
+
+/**
+ * nice_agent_get_default_local_candidate:
+ * @agent: The #NiceAgent Object
+ * @stream_id: The ID of the stream
+ * @component_id: The ID of the component
+ *
+ * This helper function will return the recommended default candidate to be
+ * used for non-ICE compatible clients. This will usually be the candidate
+ * with the lowest priority, since it will be the longest path but the one with
+ * the most chances of success.
+ * <note>
+ <para>
+ This function is only useful in order to manually generate the
+ local SDP
+ </para>
+ * </note>
+ *
+ * Returns: The candidate to be used as the default candidate, or %NULL in case
+ * of error. Must be freed with nice_candidate_free() once done.
+ *
+ */
+NiceCandidate *
+nice_agent_get_default_local_candidate (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id);
+
+/**
+ * nice_agent_generate_local_sdp:
+ * @agent: The #NiceAgent Object
+ *
+ * Generate an SDP string containing the local candidates and credentials for
+ * all streams and components in the agent.
+ *
+ <note>
+ <para>
+ The SDP will not contain any codec lines and the 'm' line will not list
+ any payload types.
+ </para>
+ <para>
+ It is highly recommended to set names on the streams prior to calling this
+ function. Unnamed streams will show up as '-' in the 'm' line, but the SDP
+ will not be parseable with nice_agent_parse_remote_sdp() if a stream is
+ unnamed.
+ </para>
+ <para>
+ The default candidate in the SDP will be selected based on the lowest
+ priority candidate for the first component.
+ </para>
+ </note>
+ *
+ * <para>See also: nice_agent_set_stream_name() </para>
+ * <para>See also: nice_agent_parse_remote_sdp() </para>
+ * <para>See also: nice_agent_generate_local_stream_sdp() </para>
+ * <para>See also: nice_agent_generate_local_candidate_sdp() </para>
+ * <para>See also: nice_agent_get_default_local_candidate() </para>
+ *
+ * Returns: A string representing the local SDP. Must be freed with g_free()
+ * once done.
+ *
+ * Since: 0.1.4
+ **/
+gchar *
+nice_agent_generate_local_sdp (
+ NiceAgent *agent);
+
+/**
+ * nice_agent_generate_local_stream_sdp:
+ * @agent: The #NiceAgent Object
+ * @stream_id: The ID of the stream
+ * @include_non_ice: Whether or not to include non ICE specific lines
+ * (m=, c= and a=rtcp: lines)
+ *
+ * Generate an SDP string containing the local candidates and credentials
+ * for a stream.
+ *
+ <note>
+ <para>
+ The SDP will not contain any codec lines and the 'm' line will not list
+ any payload types.
+ </para>
+ <para>
+ It is highly recommended to set the name of the stream prior to calling this
+ function. Unnamed streams will show up as '-' in the 'm' line.
+ </para>
+ <para>
+ The default candidate in the SDP will be selected based on the lowest
+ priority candidate.
+ </para>
+ </note>
+ *
+ * <para>See also: nice_agent_set_stream_name() </para>
+ * <para>See also: nice_agent_parse_remote_stream_sdp() </para>
+ * <para>See also: nice_agent_generate_local_sdp() </para>
+ * <para>See also: nice_agent_generate_local_candidate_sdp() </para>
+ * <para>See also: nice_agent_get_default_local_candidate() </para>
+ *
+ * Returns: A string representing the local SDP for the stream. Must be freed
+ * with g_free() once done.
+ *
+ * Since: 0.1.4
+ **/
+gchar *
+nice_agent_generate_local_stream_sdp (
+ NiceAgent *agent,
+ guint stream_id,
+ gboolean include_non_ice);
+
+/**
+ * nice_agent_generate_local_candidate_sdp:
+ * @agent: The #NiceAgent Object
+ * @candidate: The candidate to generate
+ *
+ * Generate an SDP string representing a local candidate.
+ *
+ * <para>See also: nice_agent_parse_remote_candidate_sdp() </para>
+ * <para>See also: nice_agent_generate_local_sdp() </para>
+ * <para>See also: nice_agent_generate_local_stream_sdp() </para>
+ *
+ * Returns: A string representing the SDP for the candidate. Must be freed
+ * with g_free() once done.
+ *
+ * Since: 0.1.4
+ **/
+gchar *
+nice_agent_generate_local_candidate_sdp (
+ NiceAgent *agent,
+ NiceCandidate *candidate);
+
+/**
+ * nice_agent_parse_remote_sdp:
+ * @agent: The #NiceAgent Object
+ * @sdp: The remote SDP to parse
+ *
+ * Parse an SDP string and extracts candidates and credentials from it and sets
+ * them on the agent.
+ *
+ * <para>See also: nice_agent_set_stream_name() </para>
+ * <para>See also: nice_agent_generate_local_sdp() </para>
+ * <para>See also: nice_agent_parse_remote_stream_sdp() </para>
+ * <para>See also: nice_agent_parse_remote_candidate_sdp() </para>
+ *
+ * Returns: The number of candidates added, negative on errors
+ *
+ * Since: 0.1.4
+ **/
+int
+nice_agent_parse_remote_sdp (
+ NiceAgent *agent,
+ const gchar *sdp);
+
+
+/**
+ * nice_agent_parse_remote_stream_sdp:
+ * @agent: The #NiceAgent Object
+ * @stream_id: The ID of the stream to parse
+ * @sdp: The remote SDP to parse
+ * @ufrag: Pointer to store the ice ufrag if non %NULL. Must be freed with
+ * g_free() after use
+ * @pwd: Pointer to store the ice password if non %NULL. Must be freed with
+ * g_free() after use
+ *
+ * Parse an SDP string representing a single stream and extracts candidates
+ * and credentials from it.
+ *
+ * <para>See also: nice_agent_generate_local_stream_sdp() </para>
+ * <para>See also: nice_agent_parse_remote_sdp() </para>
+ * <para>See also: nice_agent_parse_remote_candidate_sdp() </para>
+ *
+ * Returns: (element-type NiceCandidate) (transfer full): A #GSList of
+ * candidates parsed from the SDP, or %NULL in case of errors
+ *
+ * Since: 0.1.4
+ **/
+GSList *
+nice_agent_parse_remote_stream_sdp (
+ NiceAgent *agent,
+ guint stream_id,
+ const gchar *sdp,
+ gchar **ufrag,
+ gchar **pwd);
+
+
+/**
+ * nice_agent_parse_remote_candidate_sdp:
+ * @agent: The #NiceAgent Object
+ * @stream_id: The ID of the stream the candidate belongs to
+ * @sdp: The remote SDP to parse
+ *
+ * Parse an SDP string and extracts the candidate from it.
+ *
+ * <para>See also: nice_agent_generate_local_candidate_sdp() </para>
+ * <para>See also: nice_agent_parse_remote_sdp() </para>
+ * <para>See also: nice_agent_parse_remote_stream_sdp() </para>
+ *
+ * Returns: The parsed candidate or %NULL if there was an error.
+ *
+ * Since: 0.1.4
+ **/
+NiceCandidate *
+nice_agent_parse_remote_candidate_sdp (
+ NiceAgent *agent,
+ guint stream_id,
+ const gchar *sdp);
+
+/**
+ * nice_agent_get_io_stream:
+ * @agent: A #NiceAgent
+ * @stream_id: The ID of the stream to wrap
+ * @component_id: The ID of the component to wrap
+ *
+ * Gets a #GIOStream wrapper around the given stream and component in
+ * @agent. The I/O stream will be valid for as long as @stream_id is valid.
+ * The #GInputStream and #GOutputStream implement #GPollableInputStream and
+ * #GPollableOutputStream.
+ *
+ * This function may only be called on reliable #NiceAgents. It is a
+ * programming error to try and create an I/O stream wrapper for an
+ * unreliable stream.
+ *
+ * Returns: (transfer full): A #GIOStream.
+ *
+ * Since: 0.1.5
+ */
+GIOStream *
+nice_agent_get_io_stream (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id);
+
+/**
+ * nice_component_state_to_string:
+ * @state: a #NiceComponentState
+ *
+ * Returns a string representation of the state, generally to use in debug
+ * messages.
+ *
+ * Returns: (transfer none): a string representation of @state
+ * Since: 0.1.6
+ */
+const gchar *
+nice_component_state_to_string (NiceComponentState state);
+
+/**
+ * nice_agent_forget_relays:
+ * @agent: The #NiceAgent Object
+ * @stream_id: The ID of the stream
+ * @component_id: The ID of the component
+ *
+ * Forget all the relay servers previously added using
+ * nice_agent_set_relay_info(). Currently connected streams will keep
+ * using the relay as long as they have not been restarted and haven't
+ * succesfully negotiated a different path.
+ *
+ * Returns: %FALSE if the component could not be found, %TRUE otherwise
+ *
+ * Since: 0.1.6
+ */
+gboolean
+nice_agent_forget_relays (NiceAgent *agent,
+ guint stream_id,
+ guint component_id);
+
+/**
+ * nice_agent_get_component_state:
+ * @agent: The #NiceAgent Object
+ * @stream_id: The ID of the stream
+ * @component_id: The ID of the component
+ *
+ * Retrieves the current state of a component.
+ *
+ * Returns: the #NiceComponentState of the component and
+ * %NICE_COMPONENT_STATE_FAILED if the component was invalid.
+ *
+ * Since: 0.1.8
+ */
+NiceComponentState
+nice_agent_get_component_state (NiceAgent *agent,
+ guint stream_id,
+ guint component_id);
+
+/**
+ * nice_agent_peer_candidate_gathering_done:
+ * @agent: The #NiceAgent Object
+ * @stream_id: The ID of the stream
+ *
+ * Notifies the agent that the remote peer has concluded candidate gathering and
+ * thus no more remote candidates are expected to arrive for @stream_id.
+ *
+ * This will allow the stream components without a successful connectivity check
+ * to stop waiting for more candidates to come and finally transit into
+ * %NICE_COMPONENT_STATE_FAILED.
+ *
+ * Calling the function has an effect only when #NiceAgent:trickle-ice is %TRUE.
+ *
+ * Returns: %FALSE if the stream could not be found, %TRUE otherwise
+ *
+ * Since: 0.1.16
+ */
+gboolean
+nice_agent_peer_candidate_gathering_done (
+ NiceAgent *agent,
+ guint stream_id);
+
+/**
+ * nice_agent_close_async:
+ * @agent: The #NiceAgent object
+ * @callback: (nullable): A callback that will be called when the closing is
+ * complete
+ * @callback_data: (nullable): A pointer that will be passed to the callback
+ *
+ * Asynchronously closes resources the agent has allocated on remote servers.
+ *
+ * The agent will call the callback in the current #GMainContext in
+ * which this function is called. The #GAsyncResult in the callback
+ * can be ignored as this operation never fails.
+ *
+ * Calling this function before freeing the agent makes sure the allocated relay
+ * ports aren't left behind on TURN server but properly removed.
+ *
+ * Since: 0.1.16
+ */
+void
+nice_agent_close_async (NiceAgent *agent, GAsyncReadyCallback callback,
+ gpointer callback_data);
+
+G_END_DECLS
+
+#endif /* __LIBNICE_AGENT_H__ */
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2006-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2006-2009 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Dafydd Harries, Collabora Ltd.
+ * Youness Alaoui, Collabora Ltd.
+ * Kai Vehmanen, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+/*
+ * @file candidate.c
+ * @brief ICE candidate functions
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#else
+#define NICEAPI_EXPORT
+#endif
+
+#include <string.h>
+
+#include "agent.h"
+#include "component.h"
+#include "interfaces.h"
+
+G_DEFINE_BOXED_TYPE (NiceCandidate, nice_candidate, nice_candidate_copy,
+ nice_candidate_free);
+
+/* (ICE 4.1.1 "Gathering Candidates") ""Every candidate is a transport
+ * address. It also has a type and a base. Three types are defined and
+ * gathered by this specification - host candidates, server reflexive
+ * candidates, and relayed candidates."" (ID-19) */
+
+NICEAPI_EXPORT NiceCandidate *
+nice_candidate_new (NiceCandidateType type)
+{
+ NiceCandidate *candidate;
+
+ candidate = g_slice_new0 (NiceCandidate);
+ candidate->type = type;
+ return candidate;
+}
+
+
+NICEAPI_EXPORT void
+nice_candidate_free (NiceCandidate *candidate)
+{
+ /* better way of checking if socket is allocated? */
+
+ if (candidate->username)
+ g_free (candidate->username);
+
+ if (candidate->password)
+ g_free (candidate->password);
+
+ if (candidate->turn)
+ turn_server_unref (candidate->turn);
+
+ g_slice_free (NiceCandidate, candidate);
+}
+
+
+guint32
+nice_candidate_jingle_priority (NiceCandidate *candidate)
+{
+ switch (candidate->type)
+ {
+ case NICE_CANDIDATE_TYPE_HOST: return 1000;
+ case NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE: return 900;
+ case NICE_CANDIDATE_TYPE_PEER_REFLEXIVE: return 900;
+ case NICE_CANDIDATE_TYPE_RELAYED: return 500;
+ default: return 0;
+ }
+}
+
+guint32
+nice_candidate_msn_priority (NiceCandidate *candidate)
+{
+ switch (candidate->type)
+ {
+ case NICE_CANDIDATE_TYPE_HOST: return 830;
+ case NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE: return 550;
+ case NICE_CANDIDATE_TYPE_PEER_REFLEXIVE: return 550;
+ case NICE_CANDIDATE_TYPE_RELAYED: return 450;
+ default: return 0;
+ }
+}
+
+
+/*
+ * ICE 4.1.2.1. "Recommended Formula" (ID-19):
+ * returns number between 1 and 0x7effffff
+ */
+guint32
+nice_candidate_ice_priority_full (
+ // must be ∈ (0, 126) (max 2^7 - 2)
+ guint type_preference,
+ // must be ∈ (0, 65535) (max 2^16 - 1)
+ guint local_preference,
+ // must be ∈ (0, 255) (max 2 ^ 8 - 1)
+ guint component_id)
+{
+ return (
+ 0x1000000 * type_preference +
+ 0x100 * local_preference +
+ (0x100 - component_id));
+}
+
+static guint32
+nice_candidate_ice_local_preference_full (guint direction_preference,
+ guint other_preference)
+{
+ return (0x2000 * direction_preference +
+ other_preference);
+}
+
+static guint8
+nice_candidate_ip_local_preference (const NiceCandidate *candidate)
+{
+ guint8 preference = 0;
+ gchar ip_string[INET6_ADDRSTRLEN];
+ GList/*<owned gchar*>*/ *ips = NULL;
+ GList/*<unowned gchar*>*/ *iter;
+
+ /* Ensure otherwise identical host candidates with only different IP addresses
+ * (multihomed host) get assigned different priorities. Position of the IP in
+ * the list obtained from nice_interfaces_get_local_ips() serves here as the
+ * distinguishing value of other_preference. Reflexive and relayed candidates
+ * are likewise differentiated by their base address.
+ *
+ * This is required by RFC 5245 Section 4.1.2.1:
+ * https://tools.ietf.org/html/rfc5245#section-4.1.2.1
+ */
+ if (candidate->type == NICE_CANDIDATE_TYPE_HOST) {
+ nice_address_to_string (&candidate->addr, ip_string);
+ } else {
+ nice_address_to_string (&candidate->base_addr, ip_string);
+ }
+
+ ips = nice_interfaces_get_local_ips (TRUE);
+
+ for (iter = ips; iter; iter = g_list_next (iter)) {
+ if (g_strcmp0 (ip_string, iter->data) == 0) {
+ break;
+ }
+ ++preference;
+ }
+
+ g_list_free_full (ips, g_free);
+
+ return preference;
+}
+
+static guint16
+nice_candidate_ice_local_preference (const NiceCandidate *candidate)
+{
+ guint direction_preference;
+
+ switch (candidate->transport)
+ {
+ case NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE:
+ if (candidate->type == NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE ||
+ candidate->type == NICE_CANDIDATE_TYPE_HOST)
+ direction_preference = 4;
+ else
+ direction_preference = 6;
+ break;
+ case NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE:
+ if (candidate->type == NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE ||
+ candidate->type == NICE_CANDIDATE_TYPE_HOST)
+ direction_preference = 2;
+ else
+ direction_preference = 4;
+ break;
+ case NICE_CANDIDATE_TRANSPORT_TCP_SO:
+ if (candidate->type == NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE ||
+ candidate->type == NICE_CANDIDATE_TYPE_HOST)
+ direction_preference = 6;
+ else
+ direction_preference = 2;
+ break;
+ case NICE_CANDIDATE_TRANSPORT_UDP:
+ default:
+ return 1;
+ break;
+ }
+
+ return nice_candidate_ice_local_preference_full (direction_preference,
+ nice_candidate_ip_local_preference (candidate));
+}
+
+static guint32
+nice_candidate_ms_ice_local_preference_full (guint transport_preference,
+ guint direction_preference, guint other_preference)
+{
+ return 0x1000 * transport_preference +
+ 0x200 * direction_preference +
+ 0x1 * other_preference;
+}
+
+static guint32
+nice_candidate_ms_ice_local_preference (const NiceCandidate *candidate)
+{
+ guint8 transport_preference = 0;
+ guint8 direction_preference = 0;
+
+ switch (candidate->transport)
+ {
+ case NICE_CANDIDATE_TRANSPORT_TCP_SO:
+ case NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE:
+ transport_preference = NICE_CANDIDATE_TRANSPORT_MS_PREF_TCP;
+ direction_preference = NICE_CANDIDATE_DIRECTION_MS_PREF_ACTIVE;
+ break;
+ case NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE:
+ transport_preference = NICE_CANDIDATE_TRANSPORT_MS_PREF_TCP;
+ direction_preference = NICE_CANDIDATE_DIRECTION_MS_PREF_PASSIVE;
+ break;
+ case NICE_CANDIDATE_TRANSPORT_UDP:
+ default:
+ transport_preference = NICE_CANDIDATE_TRANSPORT_MS_PREF_UDP;
+ break;
+ }
+
+ return nice_candidate_ms_ice_local_preference_full(transport_preference,
+ direction_preference, nice_candidate_ip_local_preference (candidate));
+}
+
+static guint8
+nice_candidate_ice_type_preference (const NiceCandidate *candidate,
+ gboolean reliable, gboolean nat_assisted)
+{
+ guint8 type_preference;
+
+ switch (candidate->type)
+ {
+ case NICE_CANDIDATE_TYPE_HOST:
+ type_preference = NICE_CANDIDATE_TYPE_PREF_HOST;
+ break;
+ case NICE_CANDIDATE_TYPE_PEER_REFLEXIVE:
+ type_preference = NICE_CANDIDATE_TYPE_PREF_PEER_REFLEXIVE;
+ break;
+ case NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE:
+ if (nat_assisted)
+ type_preference = NICE_CANDIDATE_TYPE_PREF_NAT_ASSISTED;
+ else
+ type_preference = NICE_CANDIDATE_TYPE_PREF_SERVER_REFLEXIVE;
+ break;
+ case NICE_CANDIDATE_TYPE_RELAYED:
+ if (candidate->turn->type == NICE_RELAY_TYPE_TURN_UDP)
+ type_preference = NICE_CANDIDATE_TYPE_PREF_RELAYED_UDP;
+ else
+ type_preference = NICE_CANDIDATE_TYPE_PREF_RELAYED;
+ break;
+ default:
+ type_preference = 0;
+ break;
+ }
+
+ if ((reliable && candidate->transport == NICE_CANDIDATE_TRANSPORT_UDP) ||
+ (!reliable && candidate->transport != NICE_CANDIDATE_TRANSPORT_UDP)) {
+ type_preference = type_preference / 2;
+ }
+
+ return type_preference;
+}
+
+guint32
+nice_candidate_ice_priority (const NiceCandidate *candidate,
+ gboolean reliable, gboolean nat_assisted)
+{
+ guint8 type_preference;
+ guint16 local_preference;
+
+ type_preference = nice_candidate_ice_type_preference (candidate, reliable,
+ nat_assisted);
+ local_preference = nice_candidate_ice_local_preference (candidate);
+
+ return nice_candidate_ice_priority_full (type_preference, local_preference,
+ candidate->component_id);
+}
+
+guint32
+nice_candidate_ms_ice_priority (const NiceCandidate *candidate,
+ gboolean reliable, gboolean nat_assisted)
+{
+ guint8 type_preference;
+ guint16 local_preference;
+
+ type_preference = nice_candidate_ice_type_preference (candidate, reliable,
+ nat_assisted);
+ local_preference = nice_candidate_ms_ice_local_preference (candidate);
+
+ return nice_candidate_ice_priority_full (type_preference, local_preference,
+ candidate->component_id);
+}
+
+/*
+ * Calculates the pair priority as specified in ICE
+ * sect 5.7.2. "Computing Pair Priority and Ordering Pairs" (ID-19).
+ */
+guint64
+nice_candidate_pair_priority (guint32 o_prio, guint32 a_prio)
+{
+ guint32 max = o_prio > a_prio ? o_prio : a_prio;
+ guint32 min = o_prio < a_prio ? o_prio : a_prio;
+ /* These two constants are here explictly to make some version of GCC happy */
+ const guint64 one = 1;
+ const guint64 thirtytwo = 32;
+
+ return (one << thirtytwo) * min + 2 * max + (o_prio > a_prio ? 1 : 0);
+}
+
+/*
+ * Copies a candidate
+ */
+NICEAPI_EXPORT NiceCandidate *
+nice_candidate_copy (const NiceCandidate *candidate)
+{
+ NiceCandidate *copy;
+
+ g_return_val_if_fail (candidate != NULL, NULL);
+
+ copy = nice_candidate_new (candidate->type);
+ memcpy (copy, candidate, sizeof(NiceCandidate));
+
+ copy->turn = NULL;
+ copy->username = g_strdup (copy->username);
+ copy->password = g_strdup (copy->password);
+
+ return copy;
+}
+
+NICEAPI_EXPORT gboolean
+nice_candidate_equal_target (const NiceCandidate *candidate1,
+ const NiceCandidate *candidate2)
+{
+ g_return_val_if_fail (candidate1 != NULL, FALSE);
+ g_return_val_if_fail (candidate2 != NULL, FALSE);
+
+ return (candidate1->transport == candidate2->transport &&
+ nice_address_equal (&candidate1->addr, &candidate2->addr));
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2006-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2006-2009 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Dafydd Harries, Collabora Ltd.
+ * Youness Alaoui, Collabora Ltd.
+ * Kai Vehmanen, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef __LIBNICE_CANDIDATE_H__
+#define __LIBNICE_CANDIDATE_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+
+/**
+ * SECTION:candidate
+ * @short_description: ICE candidate representation
+ * @see_also: #NiceAddress
+ * @stability: Stable
+ *
+ * A representation of an ICE candidate. Make sure you read the ICE drafts[1] to
+ * understand correctly the concept of ICE candidates.
+ *
+ * [1] http://tools.ietf.org/wg/mmusic/draft-ietf-mmusic-ice/
+ */
+
+
+G_BEGIN_DECLS
+
+/* Constants for determining candidate priorities */
+#define NICE_CANDIDATE_TYPE_PREF_HOST 120
+#define NICE_CANDIDATE_TYPE_PREF_PEER_REFLEXIVE 110
+#define NICE_CANDIDATE_TYPE_PREF_NAT_ASSISTED 105
+#define NICE_CANDIDATE_TYPE_PREF_SERVER_REFLEXIVE 100
+#define NICE_CANDIDATE_TYPE_PREF_RELAYED_UDP 30
+#define NICE_CANDIDATE_TYPE_PREF_RELAYED 20
+
+/* Priority preference constants for MS-ICE compatibility */
+#define NICE_CANDIDATE_TRANSPORT_MS_PREF_UDP 15
+#define NICE_CANDIDATE_TRANSPORT_MS_PREF_TCP 6
+#define NICE_CANDIDATE_DIRECTION_MS_PREF_PASSIVE 2
+#define NICE_CANDIDATE_DIRECTION_MS_PREF_ACTIVE 5
+
+/* Max foundation size '1*32ice-char' plus terminating NULL, ICE ID-19 */
+/**
+ * NICE_CANDIDATE_MAX_FOUNDATION:
+ *
+ * The maximum size a candidate foundation can have.
+ */
+#define NICE_CANDIDATE_MAX_FOUNDATION (32+1)
+
+
+/**
+ * NiceCandidateType:
+ * @NICE_CANDIDATE_TYPE_HOST: A host candidate
+ * @NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE: A server reflexive candidate
+ * @NICE_CANDIDATE_TYPE_PEER_REFLEXIVE: A peer reflexive candidate
+ * @NICE_CANDIDATE_TYPE_RELAYED: A relay candidate
+ *
+ * An enum represneting the type of a candidate
+ */
+typedef enum
+{
+ NICE_CANDIDATE_TYPE_HOST,
+ NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE,
+ NICE_CANDIDATE_TYPE_PEER_REFLEXIVE,
+ NICE_CANDIDATE_TYPE_RELAYED,
+} NiceCandidateType;
+
+/**
+ * NiceCandidateTransport:
+ * @NICE_CANDIDATE_TRANSPORT_UDP: UDP transport
+ * @NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE: TCP Active transport
+ * @NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE: TCP Passive transport
+ * @NICE_CANDIDATE_TRANSPORT_TCP_SO: TCP Simultaneous-Open transport
+ *
+ * An enum representing the type of transport to use
+ */
+typedef enum
+{
+ NICE_CANDIDATE_TRANSPORT_UDP,
+ NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE,
+ NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE,
+ NICE_CANDIDATE_TRANSPORT_TCP_SO,
+} NiceCandidateTransport;
+
+/**
+ * NiceRelayType:
+ * @NICE_RELAY_TYPE_TURN_UDP: A TURN relay using UDP
+ * @NICE_RELAY_TYPE_TURN_TCP: A TURN relay using TCP
+ * @NICE_RELAY_TYPE_TURN_TLS: A TURN relay using TLS over TCP
+ *
+ * An enum representing the type of relay to use
+ */
+typedef enum {
+ NICE_RELAY_TYPE_TURN_UDP,
+ NICE_RELAY_TYPE_TURN_TCP,
+ NICE_RELAY_TYPE_TURN_TLS
+} NiceRelayType;
+
+
+typedef struct _NiceCandidate NiceCandidate;
+
+typedef struct _TurnServer TurnServer;
+
+/**
+ * TurnServer:
+ * @ref_count: Reference count for the structure.
+ * @server: The #NiceAddress of the TURN server
+ * @username: The TURN username
+ * @password: The TURN password
+ * @type: The #NiceRelayType of the server
+ *
+ * A structure to store the TURN relay settings
+ */
+struct _TurnServer
+{
+ gint ref_count;
+
+ NiceAddress server;
+ gchar *username;
+ gchar *password;
+ NiceRelayType type;
+};
+
+/**
+ * NiceCandidate:
+ * @type: The type of candidate
+ * @transport: The transport being used for the candidate
+ * @addr: The #NiceAddress of the candidate
+ * @base_addr: The #NiceAddress of the base address used by the candidate
+ * @priority: The priority of the candidate <emphasis> see note </emphasis>
+ * @stream_id: The ID of the stream to which belongs the candidate
+ * @component_id: The ID of the component to which belongs the candidate
+ * @foundation: The foundation of the candidate
+ * @username: The candidate-specific username to use (overrides the one set
+ * by nice_agent_set_local_credentials() or nice_agent_set_remote_credentials())
+ * @password: The candidate-specific password to use (overrides the one set
+ * by nice_agent_set_local_credentials() or nice_agent_set_remote_credentials())
+ * @turn: The #TurnServer settings if the candidate is
+ * of type %NICE_CANDIDATE_TYPE_RELAYED
+ * @sockptr: The underlying socket
+ *
+ * A structure to represent an ICE candidate
+ <note>
+ <para>
+ The @priority is an integer as specified in the ICE draft 19. If you are
+ using the MSN or the GOOGLE compatibility mode (which are based on ICE
+ draft 6, which uses a floating point qvalue as priority), then the @priority
+ value will represent the qvalue multiplied by 1000.
+ </para>
+ </note>
+ */
+struct _NiceCandidate
+{
+ NiceCandidateType type;
+ NiceCandidateTransport transport;
+ NiceAddress addr;
+ NiceAddress base_addr;
+ guint32 priority;
+ guint stream_id;
+ guint component_id;
+ gchar foundation[NICE_CANDIDATE_MAX_FOUNDATION];
+ gchar *username; /* pointer to a nul-terminated username string */
+ gchar *password; /* pointer to a nul-terminated password string */
+ TurnServer *turn;
+ gpointer sockptr;
+};
+
+/**
+ * nice_candidate_new:
+ * @type: The #NiceCandidateType of the candidate to create
+ *
+ * Creates a new candidate. Must be freed with nice_candidate_free()
+ *
+ * Returns: A new #NiceCandidate
+ */
+NiceCandidate *
+nice_candidate_new (NiceCandidateType type);
+
+/**
+ * nice_candidate_free:
+ * @candidate: The candidate to free
+ *
+ * Frees a #NiceCandidate
+ */
+void
+nice_candidate_free (NiceCandidate *candidate);
+
+/**
+ * nice_candidate_copy:
+ * @candidate: The candidate to copy
+ *
+ * Makes a copy of a #NiceCandidate
+ *
+ * Returns: A new #NiceCandidate, a copy of @candidate
+ */
+NiceCandidate *
+nice_candidate_copy (const NiceCandidate *candidate);
+
+/**
+ * nice_candidate_equal_target:
+ * @candidate1: A candidate
+ * @candidate2: A candidate
+ *
+ * Verifies that the candidates point to the same place, meaning they have
+ * the same transport and the same address. It ignores all other aspects.
+ *
+ * Returns: %TRUE if the candidates point to the same place
+ *
+ * Since: 0.1.15
+ */
+gboolean
+nice_candidate_equal_target (const NiceCandidate *candidate1,
+ const NiceCandidate *candidate2);
+
+ GType nice_candidate_get_type (void);
+
+/**
+ * NICE_TYPE_CANDIDATE:
+ *
+ * A boxed type for a #NiceCandidate.
+ */
+#define NICE_TYPE_CANDIDATE nice_candidate_get_type ()
+
+G_END_DECLS
+
+#endif /* __LIBNICE_CANDIDATE_H__ */
+
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2006-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2006-2009 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Dafydd Harries, Collabora Ltd.
+ * Youness Alaoui, Collabora Ltd.
+ * Kai Vehmanen, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+/*
+ * @file component.c
+ * @brief ICE component functions
+ */
+
+/* Simple tracking for the number of alive components. These must be accessed
+ * atomically. */
+static volatile unsigned int n_components_created = 0;
+static volatile unsigned int n_components_destroyed = 0;
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#include "debug.h"
+
+#include "component.h"
+#include "discovery.h"
+#include "agent-priv.h"
+
+G_DEFINE_TYPE (NiceComponent, nice_component, G_TYPE_OBJECT);
+
+typedef enum {
+ PROP_ID = 1,
+ PROP_AGENT,
+ PROP_STREAM,
+} NiceComponentProperty;
+
+static void
+nice_component_constructed (GObject *obj);
+static void
+nice_component_get_property (GObject *obj,
+ guint property_id, GValue *value, GParamSpec *pspec);
+static void
+nice_component_set_property (GObject *obj,
+ guint property_id, const GValue *value, GParamSpec *pspec);
+static void
+nice_component_finalize (GObject *obj);
+
+static void
+nice_component_schedule_io_callback (NiceComponent *component);
+static void
+nice_component_deschedule_io_callback (NiceComponent *component);
+static void
+nice_component_detach_socket (NiceComponent *component, NiceSocket *nicesock);
+static void
+nice_component_clear_selected_pair (NiceComponent *component);
+
+
+void
+incoming_check_free (IncomingCheck *icheck)
+{
+ g_free (icheck->username);
+ g_slice_free (IncomingCheck, icheck);
+}
+
+/* Must *not* take the agent lock, since it’s called from within
+ * nice_component_set_io_context(), which holds the Component’s I/O lock. */
+static void
+socket_source_attach (SocketSource *socket_source, GMainContext *context)
+{
+ GSource *source;
+
+ if (socket_source->socket->fileno == NULL)
+ return;
+
+ /* Do not create a GSource for UDP turn socket, because it
+ * would duplicate the packets already received on the base
+ * UDP socket.
+ */
+ if (socket_source->socket->type == NICE_SOCKET_TYPE_UDP_TURN)
+ return;
+
+ /* Create a source. */
+ source = g_socket_create_source (socket_source->socket->fileno,
+ G_IO_IN, NULL);
+ g_source_set_callback (source, (GSourceFunc) G_CALLBACK (component_io_cb),
+ socket_source, NULL);
+
+ /* Add the source. */
+ nice_debug ("Attaching source %p (socket %p, FD %d) to context %p", source,
+ socket_source->socket, g_socket_get_fd (socket_source->socket->fileno),
+ context);
+
+ g_assert (socket_source->source == NULL);
+ socket_source->source = source;
+ g_source_attach (source, context);
+}
+
+static void
+socket_source_detach (SocketSource *source)
+{
+ nice_debug ("Detaching source %p (socket %p, FD %d) from context %p",
+ source->source, source->socket,
+ (source->socket->fileno != NULL) ?
+ g_socket_get_fd (source->socket->fileno) : 0,
+ (source->source != NULL) ? g_source_get_context (source->source) : 0);
+
+ if (source->source != NULL) {
+ g_source_destroy (source->source);
+ g_source_unref (source->source);
+ }
+ source->source = NULL;
+}
+
+static void
+socket_source_free (SocketSource *source)
+{
+ socket_source_detach (source);
+ nice_socket_free (source->socket);
+
+ g_slice_free (SocketSource, source);
+}
+
+NiceComponent *
+nice_component_new (guint id, NiceAgent *agent, NiceStream *stream)
+{
+ return g_object_new (NICE_TYPE_COMPONENT,
+ "id", id,
+ "agent", agent,
+ "stream", stream,
+ NULL);
+}
+
+void
+nice_component_remove_socket (NiceAgent *agent, NiceComponent *cmp,
+ NiceSocket *nsocket)
+{
+ GSList *i;
+ NiceStream *stream;
+
+ stream = agent_find_stream (agent, cmp->stream_id);
+
+ for (i = cmp->local_candidates; i;) {
+ NiceCandidate *candidate = i->data;
+ GSList *next = i->next;
+
+ if (!nice_socket_is_based_on (candidate->sockptr, nsocket)) {
+ i = next;
+ continue;
+ }
+
+ if (candidate == cmp->selected_pair.local) {
+ nice_component_clear_selected_pair (cmp);
+ agent_signal_component_state_change (agent, cmp->stream_id,
+ cmp->id, NICE_COMPONENT_STATE_FAILED);
+ }
+
+ refresh_prune_candidate (agent, candidate);
+ discovery_prune_socket (agent, candidate->sockptr);
+ if (stream) {
+ conn_check_prune_socket (agent, stream, cmp,
+ candidate->sockptr);
+ }
+
+ /* Keep nsocket alive since it's used in the loop. */
+ if (candidate->sockptr != nsocket) {
+ nice_component_detach_socket (cmp, candidate->sockptr);
+ }
+ agent_remove_local_candidate (agent, candidate);
+ nice_candidate_free (candidate);
+
+ cmp->local_candidates = g_slist_delete_link (cmp->local_candidates, i);
+ i = next;
+ }
+
+ nice_component_detach_socket (cmp, nsocket);
+}
+
+static gboolean
+on_candidate_refreshes_pruned (NiceAgent *agent, NiceCandidate *candidate)
+{
+ NiceComponent *component;
+
+ if (agent_find_component (agent, candidate->stream_id,
+ candidate->component_id, NULL, &component)) {
+ nice_component_detach_socket (component, candidate->sockptr);
+ }
+
+ nice_candidate_free (candidate);
+
+ return G_SOURCE_REMOVE;
+}
+
+void
+nice_component_clean_turn_servers (NiceAgent *agent, NiceComponent *cmp)
+{
+ GSList *i;
+ GSList *relay_candidates = NULL;
+ NiceStream *stream;
+
+ stream = agent_find_stream (agent, cmp->stream_id);
+
+ g_list_free_full (cmp->turn_servers, (GDestroyNotify) turn_server_unref);
+ cmp->turn_servers = NULL;
+
+ for (i = cmp->local_candidates; i;) {
+ NiceCandidate *candidate = i->data;
+ GSList *next = i->next;
+
+ if (candidate->type != NICE_CANDIDATE_TYPE_RELAYED) {
+ i = next;
+ continue;
+ }
+
+ /* note: do not remove the remote candidate that is
+ * currently part of the 'selected pair', see ICE
+ * 9.1.1.1. "ICE Restarts" (ID-19)
+ *
+ * So what we do instead is that we put the selected candidate
+ * in a special location and keep it "alive" that way. This is
+ * especially important for TURN, because refresh requests to the
+ * server need to keep happening.
+ */
+ if (candidate == cmp->selected_pair.local) {
+ if (cmp->turn_candidate) {
+ relay_candidates = g_slist_append(relay_candidates, cmp->turn_candidate);
+ }
+ /* Bring the priority down to 0, so that it will be replaced
+ * on the new run.
+ */
+ cmp->selected_pair.priority = 0;
+ cmp->turn_candidate = candidate;
+ } else {
+ agent_remove_local_candidate (agent, candidate);
+ relay_candidates = g_slist_append(relay_candidates, candidate);
+ }
+ cmp->local_candidates = g_slist_delete_link (cmp->local_candidates, i);
+ i = next;
+ }
+
+ for (i = relay_candidates; i; i = i->next) {
+ NiceCandidate * candidate = i->data;
+
+ discovery_prune_socket (agent, candidate->sockptr);
+ if (stream) {
+ conn_check_prune_socket (agent, stream, cmp, candidate->sockptr);
+ }
+
+ refresh_prune_candidate_async (agent, candidate,
+ (NiceTimeoutLockedCallback) on_candidate_refreshes_pruned);
+ }
+}
+
+static void
+nice_component_clear_selected_pair (NiceComponent *component)
+{
+ if (component->selected_pair.keepalive.tick_source != NULL) {
+ g_source_destroy (component->selected_pair.keepalive.tick_source);
+ g_source_unref (component->selected_pair.keepalive.tick_source);
+ component->selected_pair.keepalive.tick_source = NULL;
+ }
+
+ memset (&component->selected_pair, 0, sizeof(CandidatePair));
+}
+
+/* Must be called with the agent lock held as it touches internal Component
+ * state. */
+void
+nice_component_close (NiceAgent *agent, NiceComponent *cmp)
+{
+ IOCallbackData *data;
+ GOutputVector *vec;
+ IncomingCheck *c;
+
+ /* Start closing the pseudo-TCP socket first. FIXME: There is a very big and
+ * reliably triggerable race here. pseudo_tcp_socket_close() does not block
+ * on the socket closing — it only sends the first packet of the FIN
+ * handshake. nice_component_close() will immediately afterwards close the
+ * underlying component sockets, aborting the handshake.
+ *
+ * On the principle that starting the FIN handshake is better than not
+ * starting it, even if it’s later truncated, call pseudo_tcp_socket_close().
+ * A long-term fix is needed in the form of making nice_component_close() (and
+ * all its callers) async, so we can properly block on closure. */
+ if (cmp->tcp) {
+ pseudo_tcp_socket_close (cmp->tcp, TRUE);
+ }
+
+ if (cmp->restart_candidate)
+ nice_candidate_free (cmp->restart_candidate),
+ cmp->restart_candidate = NULL;
+
+ if (cmp->turn_candidate)
+ nice_candidate_free (cmp->turn_candidate),
+ cmp->turn_candidate = NULL;
+
+ while (cmp->local_candidates) {
+ agent_remove_local_candidate (agent, cmp->local_candidates->data);
+ nice_candidate_free (cmp->local_candidates->data);
+ cmp->local_candidates = g_slist_delete_link (cmp->local_candidates,
+ cmp->local_candidates);
+ }
+
+ g_slist_free_full (cmp->remote_candidates,
+ (GDestroyNotify) nice_candidate_free);
+ cmp->remote_candidates = NULL;
+ nice_component_free_socket_sources (cmp);
+
+ while ((c = g_queue_pop_head (&cmp->incoming_checks)))
+ incoming_check_free (c);
+
+ nice_component_clean_turn_servers (agent, cmp);
+
+ if (cmp->tcp_clock) {
+ g_source_destroy (cmp->tcp_clock);
+ g_source_unref (cmp->tcp_clock);
+ cmp->tcp_clock = NULL;
+ }
+ if (cmp->tcp_writable_cancellable) {
+ g_cancellable_cancel (cmp->tcp_writable_cancellable);
+ g_clear_object (&cmp->tcp_writable_cancellable);
+ }
+
+ while ((data = g_queue_pop_head (&cmp->pending_io_messages)) != NULL)
+ io_callback_data_free (data);
+
+ nice_component_deschedule_io_callback (cmp);
+
+ g_cancellable_cancel (cmp->stop_cancellable);
+
+ while ((vec = g_queue_pop_head (&cmp->queued_tcp_packets)) != NULL) {
+ g_free ((gpointer) vec->buffer);
+ g_slice_free (GOutputVector, vec);
+ }
+}
+
+/*
+ * Finds a candidate pair that has matching foundation ids.
+ *
+ * @return TRUE if pair found, pointer to pair stored at 'pair'
+ */
+gboolean
+nice_component_find_pair (NiceComponent *cmp, NiceAgent *agent, const gchar *lfoundation, const gchar *rfoundation, CandidatePair *pair)
+{
+ GSList *i;
+ CandidatePair result = { 0, };
+
+ for (i = cmp->local_candidates; i; i = i->next) {
+ NiceCandidate *candidate = i->data;
+ if (strncmp (candidate->foundation, lfoundation, NICE_CANDIDATE_MAX_FOUNDATION) == 0) {
+ result.local = candidate;
+ break;
+ }
+ }
+
+ for (i = cmp->remote_candidates; i; i = i->next) {
+ NiceCandidate *candidate = i->data;
+ if (strncmp (candidate->foundation, rfoundation, NICE_CANDIDATE_MAX_FOUNDATION) == 0) {
+ result.remote = candidate;
+ break;
+ }
+ }
+
+ if (result.local && result.remote) {
+ result.priority = agent_candidate_pair_priority (agent, result.local, result.remote);
+ if (pair)
+ *pair = result;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*
+ * Resets the component state to that of a ICE restarted
+ * session.
+ */
+void
+nice_component_restart (NiceComponent *cmp)
+{
+ GSList *i;
+ IncomingCheck *c;
+
+ for (i = cmp->remote_candidates; i; i = i->next) {
+ NiceCandidate *candidate = i->data;
+
+ /* note: do not remove the remote candidate that is
+ * currently part of the 'selected pair', see ICE
+ * 9.1.1.1. "ICE Restarts" (ID-19) */
+ if (candidate == cmp->selected_pair.remote) {
+ if (cmp->restart_candidate)
+ nice_candidate_free (cmp->restart_candidate);
+ cmp->restart_candidate = candidate;
+ }
+ else
+ nice_candidate_free (candidate);
+ }
+ g_slist_free (cmp->remote_candidates),
+ cmp->remote_candidates = NULL;
+
+ while ((c = g_queue_pop_head (&cmp->incoming_checks)))
+ incoming_check_free (c);
+
+ /* Reset the priority to 0 to make sure we get a new pair */
+ cmp->selected_pair.priority = 0;
+
+ /* note: component state managed by agent */
+}
+
+/*
+ * Changes the selected pair for the component to 'pair'. Does not
+ * emit the "selected-pair-changed" signal.
+ */
+void
+nice_component_update_selected_pair (NiceAgent *agent, NiceComponent *component, const CandidatePair *pair)
+{
+ NiceStream *stream;
+
+ g_assert (component);
+ g_assert (pair);
+
+ stream = agent_find_stream (agent, component->stream_id);
+
+ nice_debug ("setting SELECTED PAIR for component %u: %s:%s (prio:%"
+ G_GUINT64_FORMAT ").", component->id, pair->local->foundation,
+ pair->remote->foundation, pair->priority);
+
+ if (component->selected_pair.local &&
+ component->selected_pair.local == component->turn_candidate) {
+ discovery_prune_socket (agent,
+ component->turn_candidate->sockptr);
+ if (stream)
+ conn_check_prune_socket (agent, stream, component,
+ component->turn_candidate->sockptr);
+ refresh_prune_candidate_async (agent, component->turn_candidate,
+ (NiceTimeoutLockedCallback) on_candidate_refreshes_pruned);
+ component->turn_candidate = NULL;
+ }
+
+ nice_component_clear_selected_pair (component);
+
+ component->selected_pair.local = pair->local;
+ component->selected_pair.remote = pair->remote;
+ component->selected_pair.priority = pair->priority;
+ component->selected_pair.prflx_priority = pair->prflx_priority;
+
+ nice_component_add_valid_candidate (agent, component, pair->remote);
+}
+
+/*
+ * Finds a remote candidate with matching address and
+ * transport.
+ *
+ * @return pointer to candidate or NULL if not found
+ */
+NiceCandidate *
+nice_component_find_remote_candidate (NiceComponent *component, const NiceAddress *addr, NiceCandidateTransport transport)
+{
+ GSList *i;
+
+ for (i = component->remote_candidates; i; i = i->next) {
+ NiceCandidate *candidate = i->data;
+
+ if (nice_address_equal(&candidate->addr, addr) &&
+ candidate->transport == transport)
+ return candidate;
+
+ }
+
+ return NULL;
+}
+
+/*
+ * Sets the desired remote candidate as the selected pair
+ *
+ * It will start sending on the highest priority pair available with
+ * this candidate.
+ */
+
+NiceCandidate *
+nice_component_set_selected_remote_candidate (NiceComponent *component,
+ NiceAgent *agent, NiceCandidate *candidate)
+{
+ NiceCandidate *local = NULL;
+ NiceCandidate *remote = NULL;
+ guint64 priority = 0;
+ GSList *item = NULL;
+
+ g_assert (candidate != NULL);
+
+ for (item = component->local_candidates; item; item = g_slist_next (item)) {
+ NiceCandidate *tmp = item->data;
+ guint64 tmp_prio = 0;
+
+ if (tmp->transport != conn_check_match_transport(candidate->transport) ||
+ tmp->addr.s.addr.sa_family != candidate->addr.s.addr.sa_family ||
+ tmp->type != NICE_CANDIDATE_TYPE_HOST)
+ continue;
+
+ tmp_prio = agent_candidate_pair_priority (agent, tmp, candidate);
+
+ if (tmp_prio > priority) {
+ priority = tmp_prio;
+ local = tmp;
+ }
+ }
+
+ if (local == NULL)
+ return NULL;
+
+ remote = nice_component_find_remote_candidate (component, &candidate->addr,
+ candidate->transport);
+
+ if (!remote) {
+ remote = nice_candidate_copy (candidate);
+ component->remote_candidates = g_slist_append (component->remote_candidates,
+ remote);
+ agent_signal_new_remote_candidate (agent, remote);
+ }
+
+ nice_component_clear_selected_pair (component);
+
+ component->selected_pair.local = local;
+ component->selected_pair.remote = remote;
+ component->selected_pair.priority = priority;
+
+ /* Get into fallback mode where packets from any source is accepted once
+ * this has been called. This is the expected behavior of pre-ICE SIP.
+ */
+ component->fallback_mode = TRUE;
+
+ return local;
+}
+
+static gint
+_find_socket_source (gconstpointer a, gconstpointer b)
+{
+ const SocketSource *source_a = a;
+ const NiceSocket *socket_b = b;
+
+ return (source_a->socket == socket_b) ? 0 : 1;
+}
+
+/* This takes ownership of the socket.
+ * It creates and attaches a source to the component’s context. */
+void
+nice_component_attach_socket (NiceComponent *component, NiceSocket *nicesock)
+{
+ GSList *l;
+ SocketSource *socket_source;
+
+ g_assert (component != NULL);
+ g_assert (nicesock != NULL);
+
+ g_assert (component->ctx != NULL);
+
+ /* Find an existing SocketSource in the component which contains @socket, or
+ * create a new one.
+ *
+ * Whenever a source is added or remove to socket_sources, socket_sources_age
+ * must be incremented.
+ */
+ l = g_slist_find_custom (component->socket_sources, nicesock,
+ _find_socket_source);
+ if (l != NULL) {
+ socket_source = l->data;
+ } else {
+ socket_source = g_slice_new0 (SocketSource);
+ socket_source->socket = nicesock;
+ socket_source->component = component;
+ component->socket_sources =
+ g_slist_prepend (component->socket_sources, socket_source);
+ if (nicesock->fileno != NULL)
+ component->socket_sources_age++;
+ }
+
+ /* Create and attach a source */
+ nice_debug ("Component %p: Attach source (stream %u).",
+ component, component->stream_id);
+ socket_source_attach (socket_source, component->ctx);
+}
+
+/* Reattaches socket handles of @component to the main context.
+ *
+ * Must *not* take the agent lock, since it’s called from within
+ * nice_component_set_io_context(), which holds the Component’s I/O lock. */
+static void
+nice_component_reattach_all_sockets (NiceComponent *component)
+{
+ GSList *i;
+
+ for (i = component->socket_sources; i != NULL; i = i->next) {
+ SocketSource *socket_source = i->data;
+ nice_debug ("Reattach source %p.", socket_source->source);
+ socket_source_detach (socket_source);
+ socket_source_attach (socket_source, component->ctx);
+ }
+}
+
+/**
+ * nice_component_detach_socket:
+ * @component: a #NiceComponent
+ * @socket: the socket to detach the source for
+ *
+ * Detach the #GSource for the single specified @socket. It also closes it
+ * and frees it!
+ *
+ * If the @socket doesn’t exist in this @component, do nothing.
+ */
+static void
+nice_component_detach_socket (NiceComponent *component, NiceSocket *nicesock)
+{
+ GList *l;
+ GSList *s;
+ SocketSource *socket_source;
+
+ nice_debug ("Detach socket %p.", nicesock);
+
+ /* Remove the socket from various lists. */
+ for (l = component->incoming_checks.head; l != NULL;) {
+ IncomingCheck *icheck = l->data;
+ GList *next = l->next;
+
+ if (icheck->local_socket == nicesock) {
+ g_queue_delete_link (&component->incoming_checks, l);
+ incoming_check_free (icheck);
+ }
+
+ l = next;
+ }
+
+ /* Find the SocketSource for the socket. */
+ s = g_slist_find_custom (component->socket_sources, nicesock,
+ _find_socket_source);
+ if (s == NULL)
+ return;
+
+ /* Detach the source. */
+ socket_source = s->data;
+ component->socket_sources = g_slist_delete_link (component->socket_sources, s);
+ component->socket_sources_age++;
+
+ socket_source_detach (socket_source);
+ socket_source_free (socket_source);
+}
+
+/*
+ * Detaches socket handles of @component from the main context. Leaves the
+ * sockets themselves untouched.
+ *
+ * Must *not* take the agent lock, since it’s called from within
+ * nice_component_set_io_context(), which holds the Component’s I/O lock.
+ */
+void
+nice_component_detach_all_sockets (NiceComponent *component)
+{
+ GSList *i;
+
+ for (i = component->socket_sources; i != NULL; i = i->next) {
+ SocketSource *socket_source = i->data;
+ nice_debug ("Detach source %p, socket %p.", socket_source->source,
+ socket_source->socket);
+ socket_source_detach (socket_source);
+ }
+}
+
+void
+nice_component_free_socket_sources (NiceComponent *component)
+{
+ nice_debug ("Free socket sources for component %p.", component);
+
+ g_slist_free_full (component->socket_sources,
+ (GDestroyNotify) socket_source_free);
+ component->socket_sources = NULL;
+ component->socket_sources_age++;
+
+ nice_component_clear_selected_pair (component);
+}
+
+GMainContext *
+nice_component_dup_io_context (NiceComponent *component)
+{
+ return g_main_context_ref (component->own_ctx);
+}
+
+/* If @context is %NULL, it's own context is used, so component->ctx is always
+ * guaranteed to be non-%NULL. */
+void
+nice_component_set_io_context (NiceComponent *component, GMainContext *context)
+{
+ g_mutex_lock (&component->io_mutex);
+
+ if (component->ctx != context) {
+ if (context == NULL)
+ context = g_main_context_ref (component->own_ctx);
+ else
+ g_main_context_ref (context);
+
+ nice_component_detach_all_sockets (component);
+ g_main_context_unref (component->ctx);
+
+ component->ctx = context;
+ nice_component_reattach_all_sockets (component);
+ }
+
+ g_mutex_unlock (&component->io_mutex);
+}
+
+/* (func, user_data) and (recv_messages, n_recv_messages) are mutually
+ * exclusive. At most one of the two must be specified; if both are NULL, the
+ * Component will not receive any data (i.e. reception is paused).
+ *
+ * Apart from during setup, this must always be called with the agent lock held,
+ * and the I/O lock released (because it takes the I/O lock itself). Requiring
+ * the agent lock to be held means it can’t be called between a packet being
+ * dequeued from the kernel buffers in agent.c, and an I/O callback being
+ * emitted for it (which could cause data loss if the I/O callback function was
+ * unset in that time). */
+void
+nice_component_set_io_callback (NiceComponent *component,
+ NiceAgentRecvFunc func, gpointer user_data,
+ NiceInputMessage *recv_messages, guint n_recv_messages,
+ GError **error)
+{
+ g_assert (func == NULL || recv_messages == NULL);
+ g_assert (n_recv_messages == 0 || recv_messages != NULL);
+ g_assert (error == NULL || *error == NULL);
+
+ g_mutex_lock (&component->io_mutex);
+
+ if (func != NULL) {
+ component->io_callback = func;
+ component->io_user_data = user_data;
+ component->recv_messages = NULL;
+ component->n_recv_messages = 0;
+
+ nice_component_schedule_io_callback (component);
+ } else {
+ component->io_callback = NULL;
+ component->io_user_data = NULL;
+ component->recv_messages = recv_messages;
+ component->n_recv_messages = n_recv_messages;
+
+ nice_component_deschedule_io_callback (component);
+ }
+
+ nice_input_message_iter_reset (&component->recv_messages_iter);
+ component->recv_buf_error = error;
+
+ g_mutex_unlock (&component->io_mutex);
+}
+
+gboolean
+nice_component_has_io_callback (NiceComponent *component)
+{
+ gboolean has_io_callback;
+
+ g_mutex_lock (&component->io_mutex);
+ has_io_callback = (component->io_callback != NULL);
+ g_mutex_unlock (&component->io_mutex);
+
+ return has_io_callback;
+}
+
+IOCallbackData *
+io_callback_data_new (const guint8 *buf, gsize buf_len)
+{
+ IOCallbackData *data;
+
+ data = g_slice_new0 (IOCallbackData);
+ data->buf = g_memdup (buf, buf_len);
+ data->buf_len = buf_len;
+ data->offset = 0;
+
+ return data;
+}
+
+void
+io_callback_data_free (IOCallbackData *data)
+{
+ g_free (data->buf);
+ g_slice_free (IOCallbackData, data);
+}
+
+/* This is called with the global agent lock released. It does not take that
+ * lock, but does take the io_mutex. */
+static gboolean
+emit_io_callback_cb (gpointer user_data)
+{
+ NiceComponent *component = user_data;
+ IOCallbackData *data;
+ NiceAgentRecvFunc io_callback;
+ gpointer io_user_data;
+ guint stream_id, component_id;
+ NiceAgent *agent;
+
+ agent = g_weak_ref_get (&component->agent_ref);
+ if (agent == NULL) {
+ nice_debug ("Agent for component %p is gone", component);
+ return FALSE;
+ }
+
+ stream_id = component->stream_id;
+ component_id = component->id;
+
+ g_mutex_lock (&component->io_mutex);
+
+ /* The members of Component are guaranteed not to have changed since this
+ * GSource was attached in nice_component_emit_io_callback(). The Component’s agent
+ * and stream are immutable after construction, as are the stream and
+ * component IDs. The callback and its user data may have changed, but are
+ * guaranteed to be non-%NULL at the start as the idle source is removed when
+ * the callback is set to %NULL. They may become %NULL during the io_callback,
+ * so must be re-checked every loop iteration. The data buffer is copied into
+ * the #IOCallbackData closure.
+ *
+ * If the component is destroyed (which happens if the agent or stream are
+ * destroyed) between attaching the GSource and firing it, the GSource is
+ * detached during dispose and this callback is never invoked. If the
+ * agent is destroyed during an io_callback, its weak pointer will be
+ * nullified. Similarly, the Component needs to be re-queried for after every
+ * iteration, just in case the client has removed the stream in the
+ * callback. */
+ while (TRUE) {
+ io_callback = component->io_callback;
+ io_user_data = component->io_user_data;
+ data = g_queue_peek_head (&component->pending_io_messages);
+
+ if (data == NULL || io_callback == NULL)
+ break;
+
+ g_mutex_unlock (&component->io_mutex);
+
+ io_callback (agent, stream_id, component_id,
+ data->buf_len - data->offset, (gchar *) data->buf + data->offset,
+ io_user_data);
+
+ /* Check for the user destroying things underneath our feet. */
+ if (!agent_find_component (agent, stream_id, component_id,
+ NULL, &component)) {
+ nice_debug ("%s: Agent or component destroyed.", G_STRFUNC);
+ goto done;
+ }
+
+ g_queue_pop_head (&component->pending_io_messages);
+ io_callback_data_free (data);
+
+ g_mutex_lock (&component->io_mutex);
+ }
+
+ component->io_callback_id = 0;
+ g_mutex_unlock (&component->io_mutex);
+
+ done:
+ g_object_unref (agent);
+
+ return G_SOURCE_REMOVE;
+}
+
+/* This must be called with the agent lock *held*. */
+void
+nice_component_emit_io_callback (NiceAgent *agent, NiceComponent *component,
+ const guint8 *buf, gsize buf_len)
+{
+ guint stream_id, component_id;
+ NiceAgentRecvFunc io_callback;
+ gpointer io_user_data;
+
+ g_assert (component != NULL);
+ g_assert (buf != NULL);
+ g_assert (buf_len > 0);
+
+ stream_id = component->stream_id;
+ component_id = component->id;
+
+ g_mutex_lock (&component->io_mutex);
+ io_callback = component->io_callback;
+ io_user_data = component->io_user_data;
+ g_mutex_unlock (&component->io_mutex);
+
+ /* Allow this to be called with a NULL io_callback, since the caller can’t
+ * lock io_mutex to check beforehand. */
+ if (io_callback == NULL)
+ return;
+
+ g_assert (NICE_IS_AGENT (agent));
+ g_assert (stream_id > 0);
+ g_assert (component_id > 0);
+ g_assert (io_callback != NULL);
+
+ /* Only allocate a closure if the callback is being deferred to an idle
+ * handler. */
+ if (g_main_context_is_owner (component->ctx)) {
+ /* Thread owns the main context, so invoke the callback directly. */
+ agent_unlock_and_emit (agent);
+ io_callback (agent, stream_id,
+ component_id, buf_len, (gchar *) buf, io_user_data);
+ agent_lock (agent);
+ } else {
+ IOCallbackData *data;
+
+ g_mutex_lock (&component->io_mutex);
+
+ /* Slow path: Current thread doesn’t own the Component’s context at the
+ * moment, so schedule the callback in an idle handler. */
+ data = io_callback_data_new (buf, buf_len);
+ g_queue_push_tail (&component->pending_io_messages,
+ data); /* transfer ownership */
+
+ nice_debug ("%s: **WARNING: SLOW PATH**", G_STRFUNC);
+
+ nice_component_schedule_io_callback (component);
+
+ g_mutex_unlock (&component->io_mutex);
+ }
+}
+
+/* Note: Must be called with the io_mutex held. */
+static void
+nice_component_schedule_io_callback (NiceComponent *component)
+{
+ GSource *source;
+
+ /* Already scheduled or nothing to schedule? */
+ if (component->io_callback_id != 0 ||
+ g_queue_is_empty (&component->pending_io_messages))
+ return;
+
+ /* Add the idle callback. If nice_agent_attach_recv() is called with a
+ * NULL callback before this source is dispatched, the source will be
+ * destroyed, but any pending data will remain in
+ * component->pending_io_messages, ready to be picked up when a callback
+ * is re-attached, or if nice_agent_recv() is called. */
+ source = g_idle_source_new ();
+ g_source_set_priority (source, G_PRIORITY_DEFAULT);
+ g_source_set_callback (source, emit_io_callback_cb, component, NULL);
+ component->io_callback_id = g_source_attach (source, component->ctx);
+ g_source_unref (source);
+}
+
+/* Note: Must be called with the io_mutex held. */
+static void
+nice_component_deschedule_io_callback (NiceComponent *component)
+{
+ /* Already descheduled? */
+ if (component->io_callback_id == 0)
+ return;
+
+ g_source_remove (component->io_callback_id);
+ component->io_callback_id = 0;
+}
+
+static void
+nice_component_class_init (NiceComponentClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructed = nice_component_constructed;
+ object_class->get_property = nice_component_get_property;
+ object_class->set_property = nice_component_set_property;
+ object_class->finalize = nice_component_finalize;
+
+ /**
+ * NiceComponent:id:
+ *
+ * The unique numeric ID of the component.
+ *
+ * Since: 0.1.14
+ */
+ g_object_class_install_property (object_class, PROP_ID,
+ g_param_spec_uint (
+ "id",
+ "ID",
+ "The unique numeric ID of the component.",
+ 1, G_MAXUINT, 1,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ /**
+ * NiceComponent:agent:
+ *
+ * The #NiceAgent this component belongs to.
+ *
+ * Since: 0.1.14
+ */
+ g_object_class_install_property (object_class, PROP_AGENT,
+ g_param_spec_object (
+ "agent",
+ "Agent",
+ "The NiceAgent this component belongs to.",
+ NICE_TYPE_AGENT,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ /**
+ * NiceComponent:stream:
+ *
+ * The #NiceStream this component belongs to.
+ *
+ * Since: 0.1.14
+ */
+ g_object_class_install_property (object_class, PROP_STREAM,
+ g_param_spec_object (
+ "stream",
+ "Stream",
+ "The NiceStream this component belongs to.",
+ NICE_TYPE_STREAM,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+}
+
+static gboolean
+dummy_callback (gpointer data)
+{
+ return G_SOURCE_CONTINUE;
+}
+
+static void
+source_set_dummy_callback (GSource *source)
+{
+ g_source_set_callback (source, dummy_callback, NULL, NULL);
+}
+
+static void
+nice_component_init (NiceComponent *component)
+{
+ g_atomic_int_inc (&n_components_created);
+ nice_debug ("Created NiceComponent (%u created, %u destroyed)",
+ n_components_created, n_components_destroyed);
+
+ component->id = 0;
+ component->state = NICE_COMPONENT_STATE_DISCONNECTED;
+ component->restart_candidate = NULL;
+ component->tcp = NULL;
+ g_weak_ref_init (&component->agent_ref, NULL);
+
+ g_mutex_init (&component->io_mutex);
+ g_queue_init (&component->pending_io_messages);
+ component->io_callback_id = 0;
+
+ component->own_ctx = g_main_context_new ();
+ component->stop_cancellable = g_cancellable_new ();
+ component->stop_cancellable_source =
+ g_cancellable_source_new (component->stop_cancellable);
+ source_set_dummy_callback (component->stop_cancellable_source);
+ g_source_attach (component->stop_cancellable_source, component->own_ctx);
+ component->ctx = g_main_context_ref (component->own_ctx);
+
+ /* Start off with a fresh main context and all I/O paused. This
+ * will be updated when nice_agent_attach_recv() or nice_agent_recv_messages()
+ * are called. */
+ nice_component_set_io_context (component, NULL);
+ nice_component_set_io_callback (component, NULL, NULL, NULL, 0, NULL);
+
+ g_queue_init (&component->queued_tcp_packets);
+ g_queue_init (&component->incoming_checks);
+}
+
+static void
+nice_component_constructed (GObject *obj)
+{
+ NiceComponent *component;
+ NiceAgent *agent;
+
+ component = NICE_COMPONENT (obj);
+
+ agent = g_weak_ref_get (&component->agent_ref);
+ g_assert (agent != NULL);
+ nice_agent_init_stun_agent (agent, &component->stun_agent);
+
+ g_object_unref (agent);
+
+ G_OBJECT_CLASS (nice_component_parent_class)->constructed (obj);
+}
+
+static void
+nice_component_get_property (GObject *obj,
+ guint property_id, GValue *value, GParamSpec *pspec)
+{
+ NiceComponent *component;
+
+ component = NICE_COMPONENT (obj);
+
+ switch ((NiceComponentProperty) property_id)
+ {
+ case PROP_ID:
+ g_value_set_uint (value, component->id);
+ break;
+
+ case PROP_AGENT:
+ {
+ NiceAgent *agent;
+
+ agent = g_weak_ref_get (&component->agent_ref);
+ if (agent)
+ g_value_take_object (value, agent);
+ break;
+ }
+ case PROP_STREAM:
+ {
+ NiceAgent *agent;
+ NiceStream *stream = NULL;
+
+ agent = g_weak_ref_get (&component->agent_ref);
+ if (agent) {
+ stream = agent_find_stream (agent, component->stream_id);
+ g_value_set_object (value, stream);
+ g_object_unref (agent);
+ }
+ break;
+ }
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec);
+ }
+}
+
+static void
+nice_component_set_property (GObject *obj,
+ guint property_id, const GValue *value, GParamSpec *pspec)
+{
+ NiceComponent *component;
+
+ component = NICE_COMPONENT (obj);
+
+ switch ((NiceComponentProperty) property_id)
+ {
+ case PROP_ID:
+ component->id = g_value_get_uint (value);
+ break;
+
+ case PROP_AGENT:
+ g_weak_ref_set (&component->agent_ref, g_value_get_object (value));
+ break;
+
+ case PROP_STREAM:
+ {
+ NiceStream *stream = g_value_get_object (value);
+ component->stream_id = stream->id;
+ }
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec);
+ }
+}
+
+/* Must be called with the agent lock released as it could dispose of
+ * NiceIOStreams. */
+static void
+nice_component_finalize (GObject *obj)
+{
+ NiceComponent *cmp;
+
+ cmp = NICE_COMPONENT (obj);
+
+ /* Component should have been closed already. */
+ g_warn_if_fail (cmp->local_candidates == NULL);
+ g_warn_if_fail (cmp->remote_candidates == NULL);
+ g_warn_if_fail (g_queue_get_length (&cmp->incoming_checks) == 0);
+
+ g_list_free_full (cmp->valid_candidates,
+ (GDestroyNotify) nice_candidate_free);
+
+ g_clear_object (&cmp->tcp);
+ g_clear_object (&cmp->stop_cancellable);
+ g_clear_object (&cmp->iostream);
+ g_mutex_clear (&cmp->io_mutex);
+
+ if (cmp->stop_cancellable_source != NULL) {
+ g_source_destroy (cmp->stop_cancellable_source);
+ g_source_unref (cmp->stop_cancellable_source);
+ }
+
+ if (cmp->ctx != NULL) {
+ g_main_context_unref (cmp->ctx);
+ cmp->ctx = NULL;
+ }
+
+ g_main_context_unref (cmp->own_ctx);
+
+ g_weak_ref_clear (&cmp->agent_ref);
+
+ g_atomic_int_inc (&n_components_destroyed);
+ nice_debug ("Destroyed NiceComponent (%u created, %u destroyed)",
+ n_components_created, n_components_destroyed);
+
+ G_OBJECT_CLASS (nice_component_parent_class)->finalize (obj);
+}
+
+/**
+ * ComponentSource:
+ *
+ * This is a GSource which wraps a single Component and is dispatched whenever
+ * any of its NiceSockets are dispatched, i.e. it proxies all poll() events for
+ * every socket in the Component. It is designed for use by GPollableInputStream
+ * and GPollableOutputStream, so that a Component can be incorporated into a
+ * custom main context iteration.
+ *
+ * The callbacks dispatched by a ComponentSource have type GPollableSourceFunc.
+ *
+ * ComponentSource supports adding a GCancellable child source which will
+ * additionally dispatch if a provided GCancellable is cancelled.
+ *
+ * Internally, ComponentSource adds a new GSocketSource for each socket in the
+ * Component. Changes to the Component’s list of sockets are detected on each
+ * call to component_source_prepare(), which compares a stored age with the
+ * current age of the Component’s socket list — if the socket list has changed,
+ * the age will have increased (indicating added sockets) or will have been
+ * reset to 0 (indicating all sockets have been closed).
+ */
+typedef struct {
+ GSource parent;
+
+ GObject *pollable_stream; /* owned */
+
+ GWeakRef agent_ref;
+ guint stream_id;
+ guint component_id;
+ guint component_socket_sources_age;
+
+ /* SocketSource, free with free_child_socket_source() */
+ GSList *socket_sources;
+
+ GIOCondition condition;
+} ComponentSource;
+
+static gboolean
+component_source_prepare (GSource *source, gint *timeout_)
+{
+ ComponentSource *component_source = (ComponentSource *) source;
+ NiceAgent *agent;
+ NiceComponent *component;
+ GSList *parentl, *childl;
+
+ agent = g_weak_ref_get (&component_source->agent_ref);
+ if (!agent)
+ return FALSE;
+
+ /* Needed due to accessing the Component. */
+ agent_lock (agent);
+
+ if (!agent_find_component (agent,
+ component_source->stream_id, component_source->component_id, NULL,
+ &component))
+ goto done;
+
+
+ if (component->socket_sources_age ==
+ component_source->component_socket_sources_age)
+ goto done;
+
+ /* If the age has changed, either
+ * - one or more new socket has been prepended
+ * - old sockets have been removed
+ */
+
+ /* Add the new child sources. */
+
+ for (parentl = component->socket_sources; parentl; parentl = parentl->next) {
+ SocketSource *parent_socket_source = parentl->data;
+ SocketSource *child_socket_source;
+
+ if (parent_socket_source->socket->fileno == NULL)
+ continue;
+
+ /* Iterating the list of socket sources every time isn't a big problem
+ * because the number of pairs is limited ~100 normally, so there will
+ * rarely be more than 10.
+ */
+ childl = g_slist_find_custom (component_source->socket_sources,
+ parent_socket_source->socket, _find_socket_source);
+
+ /* If we have reached this state, then all sources new sources have been
+ * added, because they are always prepended.
+ */
+ if (childl)
+ break;
+
+ child_socket_source = g_slice_new0 (SocketSource);
+ child_socket_source->socket = parent_socket_source->socket;
+ child_socket_source->source =
+ g_socket_create_source (child_socket_source->socket->fileno, G_IO_IN,
+ NULL);
+ source_set_dummy_callback (child_socket_source->source);
+ g_source_add_child_source (source, child_socket_source->source);
+ g_source_unref (child_socket_source->source);
+ component_source->socket_sources =
+ g_slist_prepend (component_source->socket_sources, child_socket_source);
+ }
+
+
+ for (childl = component_source->socket_sources;
+ childl;) {
+ SocketSource *child_socket_source = childl->data;
+ GSList *next = childl->next;
+
+ parentl = g_slist_find_custom (component->socket_sources,
+ child_socket_source->socket, _find_socket_source);
+
+ /* If this is not a currently used socket, remove the relevant source */
+ if (!parentl) {
+ g_source_remove_child_source (source, child_socket_source->source);
+ g_slice_free (SocketSource, child_socket_source);
+ component_source->socket_sources =
+ g_slist_delete_link (component_source->socket_sources, childl);
+ }
+
+ childl = next;
+ }
+
+
+ /* Update the age. */
+ component_source->component_socket_sources_age = component->socket_sources_age;
+
+ done:
+
+ agent_unlock_and_emit (agent);
+ g_object_unref (agent);
+
+ /* We can’t be sure if the ComponentSource itself needs to be dispatched until
+ * poll() is called on all the child sources. */
+ return FALSE;
+}
+
+static gboolean
+component_source_dispatch (GSource *source, GSourceFunc callback,
+ gpointer user_data)
+{
+ ComponentSource *component_source = (ComponentSource *) source;
+ GPollableSourceFunc func = (GPollableSourceFunc) G_CALLBACK (callback);
+
+ return func (component_source->pollable_stream, user_data);
+}
+
+static void
+free_child_socket_source (gpointer data)
+{
+ g_slice_free (SocketSource, data);
+}
+
+static void
+component_source_finalize (GSource *source)
+{
+ ComponentSource *component_source = (ComponentSource *) source;
+
+ g_slist_free_full (component_source->socket_sources, free_child_socket_source);
+
+ g_weak_ref_clear (&component_source->agent_ref);
+ g_object_unref (component_source->pollable_stream);
+ component_source->pollable_stream = NULL;
+}
+
+static gboolean
+component_source_closure_callback (GObject *pollable_stream, gpointer user_data)
+{
+ GClosure *closure = user_data;
+ GValue param_value = G_VALUE_INIT;
+ GValue result_value = G_VALUE_INIT;
+ gboolean retval;
+
+ g_value_init (&result_value, G_TYPE_BOOLEAN);
+ g_value_init (¶m_value, G_TYPE_OBJECT);
+ g_value_set_object (¶m_value, pollable_stream);
+
+ g_closure_invoke (closure, &result_value, 1, ¶m_value, NULL);
+ retval = g_value_get_boolean (&result_value);
+
+ g_value_unset (¶m_value);
+ g_value_unset (&result_value);
+
+ return retval;
+}
+
+static GSourceFuncs component_source_funcs = {
+ component_source_prepare,
+ NULL, /* check */
+ component_source_dispatch,
+ component_source_finalize,
+ (GSourceFunc) G_CALLBACK (component_source_closure_callback),
+};
+
+/**
+ * nice_component_source_new:
+ * @agent: a #NiceAgent
+ * @stream_id: The stream's id
+ * @component_id: The component's number
+ * @pollable_stream: a #GPollableInputStream or #GPollableOutputStream to pass
+ * to dispatched callbacks
+ * @cancellable: (allow-none): a #GCancellable, or %NULL
+ *
+ * Create a new #ComponentSource, a type of #GSource which proxies poll events
+ * from all sockets in the given @component.
+ *
+ * A callback function of type #GPollableSourceFunc must be connected to the
+ * returned #GSource using g_source_set_callback(). @pollable_stream is passed
+ * to all callbacks dispatched from the #GSource, and a reference is held on it
+ * by the #GSource.
+ *
+ * The #GSource will automatically update to poll sockets as they’re added to
+ * the @component (e.g. during peer discovery).
+ *
+ * Returns: (transfer full): a new #ComponentSource; unref with g_source_unref()
+ */
+GSource *
+nice_component_input_source_new (NiceAgent *agent, guint stream_id,
+ guint component_id, GPollableInputStream *pollable_istream,
+ GCancellable *cancellable)
+{
+ ComponentSource *component_source;
+
+ g_assert (G_IS_POLLABLE_INPUT_STREAM (pollable_istream));
+
+ component_source =
+ (ComponentSource *)
+ g_source_new (&component_source_funcs, sizeof (ComponentSource));
+ g_source_set_name ((GSource *) component_source, "ComponentSource");
+
+ component_source->component_socket_sources_age = 0;
+ component_source->pollable_stream = g_object_ref (pollable_istream);
+ g_weak_ref_init (&component_source->agent_ref, agent);
+ component_source->stream_id = stream_id;
+ component_source->component_id = component_id;
+
+ /* Add a cancellable source. */
+ if (cancellable != NULL) {
+ GSource *cancellable_source;
+
+ cancellable_source = g_cancellable_source_new (cancellable);
+ source_set_dummy_callback (cancellable_source);
+ g_source_add_child_source ((GSource *) component_source,
+ cancellable_source);
+ g_source_unref (cancellable_source);
+ }
+
+ return (GSource *) component_source;
+}
+
+
+TurnServer *
+turn_server_new (const gchar *server_ip, guint server_port,
+ const gchar *username, const gchar *password, NiceRelayType type)
+{
+ TurnServer *turn = g_slice_new (TurnServer);
+
+ nice_address_init (&turn->server);
+
+ turn->ref_count = 1;
+ if (nice_address_set_from_string (&turn->server, server_ip)) {
+ nice_address_set_port (&turn->server, server_port);
+ } else {
+ g_slice_free (TurnServer, turn);
+ return NULL;
+ }
+ turn->username = g_strdup (username);
+ turn->password = g_strdup (password);
+ turn->type = type;
+
+ return turn;
+}
+
+TurnServer *
+turn_server_ref (TurnServer *turn)
+{
+ turn->ref_count++;
+
+ return turn;
+}
+
+void
+turn_server_unref (TurnServer *turn)
+{
+ turn->ref_count--;
+
+ if (turn->ref_count == 0) {
+ g_free (turn->username);
+ g_free (turn->password);
+ g_slice_free (TurnServer, turn);
+ }
+}
+
+void
+nice_component_add_valid_candidate (NiceAgent *agent, NiceComponent *component,
+ const NiceCandidate *candidate)
+{
+ guint count = 0;
+ GList *item, *last = NULL;
+
+ for (item = component->valid_candidates; item; item = item->next) {
+ NiceCandidate *cand = item->data;
+
+ last = item;
+ count++;
+ if (nice_candidate_equal_target (cand, candidate))
+ return;
+ }
+
+ /* New candidate */
+
+ if (nice_debug_is_enabled ()) {
+ char str[INET6_ADDRSTRLEN];
+ nice_address_to_string (&candidate->addr, str);
+ nice_debug ("Agent %p : %d:%d Adding valid source"
+ " candidate: %s:%d trans: %d", agent,
+ candidate->stream_id, candidate->component_id, str,
+ nice_address_get_port (&candidate->addr), candidate->transport);
+ }
+
+ component->valid_candidates = g_list_prepend (
+ component->valid_candidates, nice_candidate_copy (candidate));
+
+ /* Delete the last one to make sure we don't have a list that is too long,
+ * the candidates are not freed on ICE restart as this would be more complex,
+ * we just keep the list not too long.
+ */
+ if (count > NICE_COMPONENT_MAX_VALID_CANDIDATES) {
+ NiceCandidate *cand = last->data;
+
+ component->valid_candidates = g_list_delete_link (
+ component->valid_candidates, last);
+ nice_candidate_free (cand);
+ }
+}
+
+gboolean
+nice_component_verify_remote_candidate (NiceComponent *component,
+ const NiceAddress *address, NiceSocket *nicesock)
+{
+ GList *item;
+
+ if (component->fallback_mode)
+ return TRUE;
+
+ for (item = component->valid_candidates; item; item = item->next) {
+ NiceCandidate *cand = item->data;
+
+ if ((((nicesock->type == NICE_SOCKET_TYPE_TCP_BSD ||
+ nicesock->type == NICE_SOCKET_TYPE_UDP_TURN) &&
+ (cand->transport == NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE ||
+ cand->transport == NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE ||
+ cand->transport == NICE_CANDIDATE_TRANSPORT_TCP_SO)) ||
+ cand->transport == NICE_CANDIDATE_TRANSPORT_UDP) &&
+ nice_address_equal (address, &cand->addr)) {
+ /* fast return if it's already the first */
+ if (item == component->valid_candidates)
+ return TRUE;
+
+ /* Put the current candidate at the top so that in the normal use-case,
+ * this function becomes O(1).
+ */
+ component->valid_candidates = g_list_remove_link (
+ component->valid_candidates, item);
+ component->valid_candidates = g_list_concat (item,
+ component->valid_candidates);
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2006-2010 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2006-2010 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Dafydd Harries, Collabora Ltd.
+ * Youness Alaoui, Collabora Ltd.
+ * Kai Vehmanen, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef _NICE_COMPONENT_H
+#define _NICE_COMPONENT_H
+
+#include <glib.h>
+
+typedef struct _NiceComponent NiceComponent;
+
+#include "agent.h"
+#include "agent-priv.h"
+#include "candidate.h"
+#include "stun/stunagent.h"
+#include "stun/usages/timer.h"
+#include "pseudotcp.h"
+#include "stream.h"
+#include "socket.h"
+
+G_BEGIN_DECLS
+
+
+/* (ICE §4.1.1.1, ID-19)
+ * ""For RTP-based media streams, the RTP itself has a component
+ * ID of 1, and RTCP a component ID of 2. If an agent is using RTCP it MUST
+ * obtain a candidate for it. If an agent is using both RTP and RTCP, it
+ * would end up with 2*K host candidates if an agent has K interfaces.""
+ */
+
+typedef struct _CandidatePair CandidatePair;
+typedef struct _CandidatePairKeepalive CandidatePairKeepalive;
+typedef struct _IncomingCheck IncomingCheck;
+
+struct _CandidatePairKeepalive
+{
+ GSource *tick_source;
+ guint stream_id;
+ guint component_id;
+ StunTimer timer;
+ uint8_t stun_buffer[STUN_MAX_MESSAGE_SIZE_IPV6];
+ StunMessage stun_message;
+};
+
+struct _CandidatePair
+{
+ NiceCandidate *local;
+ NiceCandidate *remote;
+ guint64 priority; /* candidate pair priority */
+ guint32 prflx_priority;
+ CandidatePairKeepalive keepalive;
+};
+
+struct _IncomingCheck
+{
+ NiceAddress from;
+ NiceSocket *local_socket;
+ guint32 priority;
+ gboolean use_candidate;
+ uint8_t *username;
+ uint16_t username_len;
+};
+
+void
+incoming_check_free (IncomingCheck *icheck);
+
+/* A pair of a socket and the GSource which polls it from the main loop. All
+ * GSources in a Component must be attached to the same main context:
+ * component->ctx.
+ *
+ * Socket must be non-NULL, but source may be NULL if it has been detached.
+ *
+ * The Component is stored so this may be used as the user data for a GSource
+ * callback. */
+typedef struct {
+ NiceSocket *socket;
+ GSource *source;
+ NiceComponent *component;
+} SocketSource;
+
+
+/* A message which has been received and processed (so is guaranteed not
+ * to be a STUN packet, or to contain pseudo-TCP header bytes, for example), but
+ * which hasn’t yet been sent to the client in an I/O callback. This could be
+ * due to the main context not being run, or due to the I/O callback being
+ * detached.
+ *
+ * The @offset member gives the byte offset into @buf which has already been
+ * sent to the client. #IOCallbackData buffers remain in the
+ * #Component::pending_io_messages queue until all of their bytes have been sent
+ * to the client.
+ *
+ * @offset is guaranteed to be smaller than @buf_len. */
+typedef struct {
+ guint8 *buf; /* owned */
+ gsize buf_len;
+ gsize offset;
+} IOCallbackData;
+
+IOCallbackData *
+io_callback_data_new (const guint8 *buf, gsize buf_len);
+void
+io_callback_data_free (IOCallbackData *data);
+
+#define NICE_TYPE_COMPONENT nice_component_get_type()
+#define NICE_COMPONENT(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), NICE_TYPE_COMPONENT, NiceComponent))
+#define NICE_COMPONENT_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), NICE_TYPE_COMPONENT, NiceComponentClass))
+#define NICE_IS_COMPONENT(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NICE_TYPE_COMPONENT))
+#define NICE_IS_COMPONENT_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), NICE_TYPE_COMPONENT))
+#define NICE_COMPONENT_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), NICE_TYPE_COMPONENT, NiceComponentClass))
+
+struct _NiceComponent {
+ /*< private >*/
+ GObject parent;
+
+ NiceComponentType type;
+ guint id; /* component id */
+ NiceComponentState state;
+ GSList *local_candidates; /* list of NiceCandidate objs */
+ GSList *remote_candidates; /* list of NiceCandidate objs */
+ GList *valid_candidates; /* list of owned remote NiceCandidates that are part of valid pairs */
+ GSList *socket_sources; /* list of SocketSource objs; must only grow monotonically */
+ guint socket_sources_age; /* incremented when socket_sources changes */
+ GQueue incoming_checks; /* list of IncomingCheck objs */
+ GList *turn_servers; /* List of TurnServer objs */
+ CandidatePair selected_pair; /* independent from checklists,
+ see ICE 11.1. "Sending Media" (ID-19) */
+ gboolean fallback_mode; /* in this case, accepts packets from all, ignore candidate validation */
+ NiceCandidate *restart_candidate; /* for storing active remote candidate during a restart */
+ NiceCandidate *turn_candidate; /* for storing active turn candidate if turn servers have been cleared */
+ /* I/O handling. The main context must always be non-NULL, and is used for all
+ * socket recv() operations. All io_callback emissions are invoked in this
+ * context too.
+ *
+ * recv_messages and io_callback are mutually exclusive, but it is allowed for
+ * both to be NULL if the Component is not currently ready to receive data. */
+ GMutex io_mutex; /* protects io_callback, io_user_data,
+ pending_io_messages and io_callback_id.
+ immutable: can be accessed without
+ holding the agent lock; if the agent
+ lock is to be taken, it must always be
+ taken before this one */
+ NiceAgentRecvFunc io_callback; /* function called on io cb */
+ gpointer io_user_data; /* data passed to the io function */
+ GQueue pending_io_messages; /* queue of messages which have been
+ received but not passed to the client
+ in an I/O callback or recv() call yet.
+ each element is an owned
+ IOCallbackData */
+ guint io_callback_id; /* GSource ID of the I/O callback */
+
+ GMainContext *own_ctx; /* own context for GSources for this
+ component */
+ GMainContext *ctx; /* context for GSources for this
+ component (possibly set from the app) */
+ NiceInputMessage *recv_messages; /* unowned messages for receiving into */
+ guint n_recv_messages; /* length of recv_messages */
+ NiceInputMessageIter recv_messages_iter; /* current write position in
+ recv_messages */
+ GError **recv_buf_error; /* error information about failed reads */
+
+ GWeakRef agent_ref;
+ guint stream_id;
+
+ StunAgent stun_agent; /* This stun agent is used to validate all stun requests */
+
+
+ GCancellable *stop_cancellable;
+ GSource *stop_cancellable_source; /* owned */
+
+ PseudoTcpSocket *tcp;
+ GSource* tcp_clock;
+ guint64 last_clock_timeout;
+ gboolean tcp_readable;
+ GCancellable *tcp_writable_cancellable;
+
+ GIOStream *iostream;
+
+ guint min_port;
+ guint max_port;
+
+ /* Queue of messages received before a selected socket was available to send
+ * ACKs on. The messages are dequeued to the pseudo-TCP socket once a selected
+ * UDP socket is available. This is only used for reliable Components. */
+ GQueue queued_tcp_packets;
+};
+
+typedef struct {
+ GObjectClass parent_class;
+} NiceComponentClass;
+
+GType nice_component_get_type (void);
+
+NiceComponent *
+nice_component_new (guint component_id, NiceAgent *agent, NiceStream *stream);
+
+void
+nice_component_close (NiceAgent *agent, NiceComponent *component);
+
+gboolean
+nice_component_find_pair (NiceComponent *component, NiceAgent *agent,
+ const gchar *lfoundation, const gchar *rfoundation, CandidatePair *pair);
+
+void
+nice_component_restart (NiceComponent *component);
+
+void
+nice_component_update_selected_pair (NiceAgent *agent, NiceComponent *component,
+ const CandidatePair *pair);
+
+NiceCandidate *
+nice_component_find_remote_candidate (NiceComponent *component,
+ const NiceAddress *addr, NiceCandidateTransport transport);
+
+NiceCandidate *
+nice_component_set_selected_remote_candidate (NiceComponent *component,
+ NiceAgent *agent, NiceCandidate *candidate);
+
+void
+nice_component_attach_socket (NiceComponent *component, NiceSocket *nsocket);
+
+void
+nice_component_remove_socket (NiceAgent *agent, NiceComponent *component,
+ NiceSocket *nsocket);
+void
+nice_component_detach_all_sockets (NiceComponent *component);
+
+void
+nice_component_free_socket_sources (NiceComponent *component);
+
+GSource *
+nice_component_input_source_new (NiceAgent *agent, guint stream_id,
+ guint component_id, GPollableInputStream *pollable_istream,
+ GCancellable *cancellable);
+
+GMainContext *
+nice_component_dup_io_context (NiceComponent *component);
+void
+nice_component_set_io_context (NiceComponent *component, GMainContext *context);
+void
+nice_component_set_io_callback (NiceComponent *component,
+ NiceAgentRecvFunc func, gpointer user_data,
+ NiceInputMessage *recv_messages, guint n_recv_messages,
+ GError **error);
+void
+nice_component_emit_io_callback (NiceAgent *agent, NiceComponent *component,
+ const guint8 *buf, gsize buf_len);
+gboolean
+nice_component_has_io_callback (NiceComponent *component);
+void
+nice_component_clean_turn_servers (NiceAgent *agent, NiceComponent *component);
+
+
+TurnServer *
+turn_server_new (const gchar *server_ip, guint server_port,
+ const gchar *username, const gchar *password, NiceRelayType type);
+
+TurnServer *
+turn_server_ref (TurnServer *turn);
+
+void
+turn_server_unref (TurnServer *turn);
+
+void
+nice_component_add_valid_candidate (NiceAgent *agent, NiceComponent *component,
+ const NiceCandidate *candidate);
+
+gboolean
+nice_component_verify_remote_candidate (NiceComponent *component,
+ const NiceAddress *address, NiceSocket *nicesock);
+
+
+G_END_DECLS
+
+#endif /* _NICE_COMPONENT_H */
+
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2006-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2006-2009 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Kai Vehmanen, Nokia
+ * Youness Alaoui, Collabora Ltd.
+ * Dafydd Harries, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+/*
+ * @file conncheck.c
+ * @brief ICE connectivity checks
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include "debug.h"
+
+#include "agent.h"
+#include "agent-priv.h"
+#include "conncheck.h"
+#include "discovery.h"
+#include "stun/stun5389.h"
+#include "stun/usages/ice.h"
+#include "stun/usages/bind.h"
+#include "stun/usages/turn.h"
+
+static void priv_update_check_list_failed_components (NiceAgent *agent, NiceStream *stream);
+static void priv_update_check_list_state_for_ready (NiceAgent *agent, NiceStream *stream, NiceComponent *component);
+static guint priv_prune_pending_checks (NiceAgent *agent, NiceStream *stream, guint component_id);
+static gboolean priv_schedule_triggered_check (NiceAgent *agent, NiceStream *stream, NiceComponent *component, NiceSocket *local_socket, NiceCandidate *remote_cand);
+static void priv_mark_pair_nominated (NiceAgent *agent, NiceStream *stream, NiceComponent *component, NiceCandidate *localcand, NiceCandidate *remotecand);
+static size_t priv_create_username (NiceAgent *agent, NiceStream *stream,
+ guint component_id, NiceCandidate *remote, NiceCandidate *local,
+ uint8_t *dest, guint dest_len, gboolean inbound);
+static size_t priv_get_password (NiceAgent *agent, NiceStream *stream,
+ NiceCandidate *remote, uint8_t **password);
+static void candidate_check_pair_free (NiceAgent *agent,
+ CandidateCheckPair *pair);
+static CandidateCheckPair *priv_conn_check_add_for_candidate_pair_matched (
+ NiceAgent *agent, guint stream_id, NiceComponent *component,
+ NiceCandidate *local, NiceCandidate *remote, NiceCheckState initial_state);
+static gboolean priv_update_selected_pair (NiceAgent *agent,
+ NiceComponent *component, CandidateCheckPair *pair);
+
+static int priv_timer_expired (GTimeVal *timer, GTimeVal *now)
+{
+ return (now->tv_sec == timer->tv_sec) ?
+ now->tv_usec >= timer->tv_usec :
+ now->tv_sec >= timer->tv_sec;
+}
+
+static unsigned int priv_timer_remainder (GTimeVal *timer, GTimeVal *now)
+{
+ unsigned int delay;
+ if (now->tv_sec > timer->tv_sec ||
+ (now->tv_sec == timer->tv_sec && now->tv_usec > timer->tv_usec))
+ return 0;
+ delay = (timer->tv_sec - now->tv_sec) * 1000;
+ delay += ((signed long)(timer->tv_usec - now->tv_usec)) / 1000;
+ return delay;
+}
+
+static gchar
+priv_state_to_gchar (NiceCheckState state)
+{
+ switch (state) {
+ case NICE_CHECK_WAITING:
+ return 'W';
+ case NICE_CHECK_IN_PROGRESS:
+ return 'I';
+ case NICE_CHECK_SUCCEEDED:
+ return 'S';
+ case NICE_CHECK_FAILED:
+ return 'F';
+ case NICE_CHECK_FROZEN:
+ return 'Z';
+ case NICE_CHECK_DISCOVERED:
+ return 'D';
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static const gchar *
+priv_state_to_string (NiceCheckState state)
+{
+ switch (state) {
+ case NICE_CHECK_WAITING:
+ return "WAITING";
+ case NICE_CHECK_IN_PROGRESS:
+ return "IN_PROGRESS";
+ case NICE_CHECK_SUCCEEDED:
+ return "SUCCEEDED";
+ case NICE_CHECK_FAILED:
+ return "FAILED";
+ case NICE_CHECK_FROZEN:
+ return "FROZEN";
+ case NICE_CHECK_DISCOVERED:
+ return "DISCOVERED";
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+#define SET_PAIR_STATE( a, p, s ) G_STMT_START{\
+ g_assert (p); \
+ p->state = s; \
+ nice_debug ("Agent %p : pair %p state %s (%s)", \
+ a, p, priv_state_to_string (s), G_STRFUNC); \
+}G_STMT_END
+
+static const gchar *
+priv_ice_return_to_string (StunUsageIceReturn ice_return)
+{
+ switch (ice_return) {
+ case STUN_USAGE_ICE_RETURN_SUCCESS:
+ return "success";
+ case STUN_USAGE_ICE_RETURN_ERROR:
+ return "error";
+ case STUN_USAGE_ICE_RETURN_INVALID:
+ return "invalid";
+ case STUN_USAGE_ICE_RETURN_ROLE_CONFLICT:
+ return "role conflict";
+ case STUN_USAGE_ICE_RETURN_INVALID_REQUEST:
+ return "invalid request";
+ case STUN_USAGE_ICE_RETURN_INVALID_METHOD:
+ return "invalid method";
+ case STUN_USAGE_ICE_RETURN_MEMORY_ERROR:
+ return "memory error";
+ case STUN_USAGE_ICE_RETURN_INVALID_ADDRESS:
+ return "invalid address";
+ case STUN_USAGE_ICE_RETURN_NO_MAPPED_ADDRESS:
+ return "no mapped address";
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static const gchar *
+priv_candidate_type_to_string (NiceCandidateType type)
+{
+ switch (type) {
+ case NICE_CANDIDATE_TYPE_HOST:
+ return "host";
+ case NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE:
+ return "srflx";
+ case NICE_CANDIDATE_TYPE_PEER_REFLEXIVE:
+ return "prflx";
+ case NICE_CANDIDATE_TYPE_RELAYED:
+ return "relay";
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+/*
+ * Dump the conncheck lists of the agent
+ */
+static void
+priv_print_conn_check_lists (NiceAgent *agent, const gchar *where, const gchar *detail)
+{
+ GSList *i, *k, *l;
+ guint j, m;
+ GTimeVal now;
+
+ if (!nice_debug_is_verbose ())
+ return;
+
+ g_get_current_time (&now);
+
+#define PRIORITY_LEN 32
+
+ nice_debug ("Agent %p : *** conncheck list DUMP (called from %s%s)",
+ agent, where, detail ? detail : "");
+ for (i = agent->streams; i ; i = i->next) {
+ NiceStream *stream = i->data;
+ for (j = 1; j <= stream->n_components; j++) {
+ for (k = stream->conncheck_list; k ; k = k->next) {
+ CandidateCheckPair *pair = k->data;
+ if (pair->component_id == j) {
+ gchar local_addr[INET6_ADDRSTRLEN];
+ gchar remote_addr[INET6_ADDRSTRLEN];
+
+ nice_address_to_string (&pair->local->addr, local_addr);
+ nice_address_to_string (&pair->remote->addr, remote_addr);
+
+ nice_debug ("Agent %p : *** sc=%d/%d : pair %p : "
+ "f=%s t=%s:%s [%s]:%u > [%s]:%u state=%c%s%s%s",
+ agent, pair->stream_id, pair->component_id, pair,
+ pair->foundation,
+ priv_candidate_type_to_string (pair->local->type),
+ priv_candidate_type_to_string (pair->remote->type),
+ local_addr, nice_address_get_port (&pair->local->addr),
+ remote_addr, nice_address_get_port (&pair->remote->addr),
+ priv_state_to_gchar (pair->state),
+ pair->valid ? "V" : "",
+ pair->nominated ? "N" : "",
+ g_slist_find (agent->triggered_check_queue, pair) ? "T" : "");
+
+ for (l = pair->stun_transactions, m = 0; l; l = l->next, m++) {
+ StunTransaction *stun = l->data;
+ nice_debug ("Agent %p : *** sc=%d/%d : pair %p : "
+ "stun#=%d timer=%d/%d %d/%dms buf=%p %s",
+ agent, pair->stream_id, pair->component_id, pair, m,
+ stun->timer.retransmissions, stun->timer.max_retransmissions,
+ stun->timer.delay - priv_timer_remainder (&stun->next_tick, &now),
+ stun->timer.delay,
+ stun->message.buffer,
+ (m == 0 && pair->retransmit) ? "(R)" : "");
+ }
+ }
+ }
+ }
+ }
+}
+
+/* Add the pair to the triggered checks list, if not already present
+ */
+static void
+priv_add_pair_to_triggered_check_queue (NiceAgent *agent, CandidateCheckPair *pair)
+{
+ g_assert (pair);
+
+ SET_PAIR_STATE (agent, pair, NICE_CHECK_IN_PROGRESS);
+ if (agent->triggered_check_queue == NULL ||
+ g_slist_find (agent->triggered_check_queue, pair) == NULL)
+ agent->triggered_check_queue = g_slist_append (agent->triggered_check_queue, pair);
+}
+
+/* Remove the pair from the triggered checks list
+ */
+static void
+priv_remove_pair_from_triggered_check_queue (NiceAgent *agent, CandidateCheckPair *pair)
+{
+ g_assert (pair);
+ agent->triggered_check_queue = g_slist_remove (agent->triggered_check_queue, pair);
+}
+
+/* Get the pair from the triggered checks list
+ */
+static CandidateCheckPair *
+priv_get_pair_from_triggered_check_queue (NiceAgent *agent)
+{
+ CandidateCheckPair *pair = NULL;
+
+ if (agent->triggered_check_queue) {
+ pair = (CandidateCheckPair *)agent->triggered_check_queue->data;
+ priv_remove_pair_from_triggered_check_queue (agent, pair);
+ }
+ return pair;
+}
+
+/*
+ * Check if the conncheck list if Active according to
+ * ICE spec, 5.7.4 (Computing States)
+ *
+ * note: the ICE spec in unclear about that, but the check list should
+ * be considered active when there is at least a pair in Waiting state
+ * OR a pair in In-Progress state.
+ */
+static gboolean
+priv_is_checklist_active (NiceStream *stream)
+{
+ GSList *i;
+
+ for (i = stream->conncheck_list; i ; i = i->next) {
+ CandidateCheckPair *p = i->data;
+ if (p->state == NICE_CHECK_WAITING || p->state == NICE_CHECK_IN_PROGRESS)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+ * Check if the conncheck list if Frozen according to
+ * ICE spec, 5.7.4 (Computing States)
+ */
+static gboolean
+priv_is_checklist_frozen (NiceStream *stream)
+{
+ GSList *i;
+
+ if (stream->conncheck_list == NULL)
+ return FALSE;
+
+ for (i = stream->conncheck_list; i ; i = i->next) {
+ CandidateCheckPair *p = i->data;
+ if (p->state != NICE_CHECK_FROZEN)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/*
+ * Check if all components of the stream have
+ * a valid pair (used for ICE spec, 7.1.3.2.3, point 2.)
+ */
+static gboolean
+priv_all_components_have_valid_pair (NiceStream *stream)
+{
+ guint i;
+ GSList *j;
+
+ for (i = 1; i <= stream->n_components; i++) {
+ for (j = stream->conncheck_list; j ; j = j->next) {
+ CandidateCheckPair *p = j->data;
+ if (p->component_id == i && p->valid)
+ break;
+ }
+ if (j == NULL)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/*
+ * Check if the foundation in parameter matches the foundation
+ * of a valid pair in the conncheck list [of stream] (used for ICE spec,
+ * 7.1.3.2.3, point 2.)
+ */
+static gboolean
+priv_foundation_matches_a_valid_pair (const gchar *foundation, NiceStream *stream)
+{
+ GSList *i;
+
+ for (i = stream->conncheck_list; i ; i = i->next) {
+ CandidateCheckPair *p = i->data;
+ if (p->valid &&
+ strncmp (p->foundation, foundation,
+ NICE_CANDIDATE_PAIR_MAX_FOUNDATION) == 0)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+ * Finds the next connectivity check in WAITING state.
+ */
+static CandidateCheckPair *priv_conn_check_find_next_waiting (GSList *conn_check_list)
+{
+ GSList *i;
+
+ /* note: list is sorted in priority order to first waiting check has
+ * the highest priority */
+ for (i = conn_check_list; i ; i = i->next) {
+ CandidateCheckPair *p = i->data;
+ if (p->state == NICE_CHECK_WAITING)
+ return p;
+ }
+
+ return NULL;
+}
+
+/*
+ * Finds the next connectivity check in FROZEN state.
+ */
+static CandidateCheckPair *
+priv_conn_check_find_next_frozen (GSList *conn_check_list)
+{
+ GSList *i;
+
+ /* note: list is sorted in priority order to first frozen check has
+ * the highest priority */
+ for (i = conn_check_list; i ; i = i->next) {
+ CandidateCheckPair *p = i->data;
+ if (p->state == NICE_CHECK_FROZEN)
+ return p;
+ }
+
+ return NULL;
+}
+
+/*
+ * Returns the number of active check lists of the agent
+ */
+static guint
+priv_number_of_active_check_lists (NiceAgent *agent)
+{
+ guint n = 0;
+ GSList *i;
+
+ for (i = agent->streams; i ; i = i->next)
+ if (priv_is_checklist_active (i->data))
+ n++;
+ return n;
+}
+
+/*
+ * Returns the first stream of the agent having a Frozen
+ * connection check list
+ */
+static NiceStream *
+priv_find_first_frozen_check_list (NiceAgent *agent)
+{
+ GSList *i;
+
+ for (i = agent->streams; i ; i = i->next) {
+ NiceStream *stream = i->data;
+ if (priv_is_checklist_frozen (stream))
+ return stream;
+ }
+ return NULL;
+}
+
+/*
+ * Initiates a new connectivity check for a ICE candidate pair.
+ *
+ * @return TRUE on success, FALSE on error
+ */
+static gboolean priv_conn_check_initiate (NiceAgent *agent, CandidateCheckPair *pair)
+{
+ SET_PAIR_STATE (agent, pair, NICE_CHECK_IN_PROGRESS);
+ if (conn_check_send (agent, pair)) {
+ SET_PAIR_STATE (agent, pair, NICE_CHECK_FAILED);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/*
+ * Unfreezes the next connectivity check in the list. Follows the
+ * algorithm (2.) defined in 5.7.4 (Computing States) of the ICE spec
+ * (RFC5245)
+ *
+ * See also sect 7.1.2.2.3 (Updating Pair States), and
+ * priv_conn_check_unfreeze_related().
+ *
+ * @return TRUE on success, and FALSE if no frozen candidates were found.
+ */
+static gboolean priv_conn_check_unfreeze_next (NiceAgent *agent, NiceStream *stream)
+{
+ GSList *i, *j;
+ GSList *found_list = NULL;
+ gboolean result = FALSE;
+
+ priv_print_conn_check_lists (agent, G_STRFUNC, NULL);
+
+ for (i = stream->conncheck_list; i ; i = i->next) {
+ CandidateCheckPair *p1 = i->data;
+ CandidateCheckPair *pair = NULL;
+ guint lowest_component_id = stream->n_components + 1;
+ guint64 highest_priority = 0;
+
+ if (g_slist_find_custom (found_list, p1->foundation, (GCompareFunc)strcmp))
+ continue;
+ found_list = g_slist_prepend (found_list, p1->foundation);
+
+ for (j = stream->conncheck_list; j ; j = j->next) {
+ CandidateCheckPair *p2 = i->data;
+ if (strncmp (p2->foundation, p1->foundation,
+ NICE_CANDIDATE_PAIR_MAX_FOUNDATION) == 0) {
+ if (p2->component_id < lowest_component_id ||
+ (p2->component_id == lowest_component_id &&
+ p2->priority > highest_priority)) {
+ pair = p2;
+ lowest_component_id = p2->component_id;
+ highest_priority = p2->priority;
+ }
+ }
+ }
+
+ if (pair) {
+ nice_debug ("Agent %p : Pair %p with s/c-id %u/%u (%s) unfrozen.",
+ agent, pair, pair->stream_id, pair->component_id, pair->foundation);
+ SET_PAIR_STATE (agent, pair, NICE_CHECK_WAITING);
+ result = TRUE;
+ }
+ }
+ g_slist_free (found_list);
+ return result;
+}
+
+/*
+ * Unfreezes the next next connectivity check in the list after
+ * check 'success_check' has successfully completed.
+ *
+ * See sect 7.1.2.2.3 (Updating Pair States) of ICE spec (ID-19).
+ *
+ * @param agent context
+ * @param ok_check a connectivity check that has just completed
+ *
+ * @return TRUE on success, and FALSE if no frozen candidates were found.
+ */
+static void priv_conn_check_unfreeze_related (NiceAgent *agent, NiceStream *stream, CandidateCheckPair *ok_check)
+{
+ GSList *i, *j;
+
+ g_assert (ok_check);
+ g_assert (ok_check->state == NICE_CHECK_SUCCEEDED);
+ g_assert (stream);
+ g_assert (stream->id == ok_check->stream_id);
+
+ priv_print_conn_check_lists (agent, G_STRFUNC, NULL);
+
+ /* step: perform the step (1) of 'Updating Pair States' */
+ for (i = stream->conncheck_list; i ; i = i->next) {
+ CandidateCheckPair *p = i->data;
+
+ if (p->stream_id == ok_check->stream_id) {
+ if (p->state == NICE_CHECK_FROZEN &&
+ strncmp (p->foundation, ok_check->foundation,
+ NICE_CANDIDATE_PAIR_MAX_FOUNDATION) == 0) {
+ nice_debug ("Agent %p : Unfreezing check %p (after successful check %p).", agent, p, ok_check);
+ SET_PAIR_STATE (agent, p, NICE_CHECK_WAITING);
+ }
+ }
+ }
+
+ /* step: perform the step (2) of 'Updating Pair States' */
+ stream = agent_find_stream (agent, ok_check->stream_id);
+ if (priv_all_components_have_valid_pair (stream)) {
+ for (i = agent->streams; i ; i = i->next) {
+ /* the agent examines the check list for each other
+ * media stream in turn
+ */
+ NiceStream *s = i->data;
+ if (s->id == ok_check->stream_id)
+ continue;
+ if (priv_is_checklist_active (s)) {
+ /* checklist is Active
+ */
+ for (j = s->conncheck_list; j ; j = j->next) {
+ CandidateCheckPair *p = j->data;
+ if (p->state == NICE_CHECK_FROZEN &&
+ priv_foundation_matches_a_valid_pair (p->foundation, stream)) {
+ nice_debug ("Agent %p : Unfreezing check %p from stream %u (after successful check %p).", agent, p, s->id, ok_check);
+ SET_PAIR_STATE (agent, p, NICE_CHECK_WAITING);
+ }
+ }
+ } else if (priv_is_checklist_frozen (s)) {
+ /* checklist is Frozen
+ */
+ gboolean match_found = FALSE;
+ /* check if there is one pair in the check list whose
+ * foundation matches a pair in the valid list under
+ * consideration
+ */
+ for (j = s->conncheck_list; j ; j = j->next) {
+ CandidateCheckPair *p = j->data;
+ if (priv_foundation_matches_a_valid_pair (p->foundation, stream)) {
+ match_found = TRUE;
+ nice_debug ("Agent %p : Unfreezing check %p from stream %u (after successful check %p).", agent, p, s->id, ok_check);
+ SET_PAIR_STATE (agent, p, NICE_CHECK_WAITING);
+ }
+ }
+
+ if (!match_found) {
+ /* set the pair with the lowest component ID
+ * and highest priority to Waiting
+ */
+ priv_conn_check_unfreeze_next (agent, s);
+ }
+ }
+ }
+ }
+}
+
+/*
+ * Create a new STUN transaction and add it to the list
+ * of ongoing stun transactions of a pair.
+ *
+ * @pair the pair the new stun transaction should be added to.
+ * @return the created stun transaction.
+ */
+static StunTransaction *
+priv_add_stun_transaction (CandidateCheckPair *pair)
+{
+ StunTransaction *stun = g_slice_new0 (StunTransaction);
+ pair->stun_transactions = g_slist_prepend (pair->stun_transactions, stun);
+ pair->retransmit = TRUE;
+ return stun;
+}
+
+/*
+ * Forget a STUN transaction.
+ *
+ * @data the stun transaction to be forgotten.
+ * @user_data the component contained the concerned stun agent.
+ */
+static void
+priv_forget_stun_transaction (gpointer data, gpointer user_data)
+{
+ StunTransaction *stun = data;
+ NiceComponent *component = user_data;
+ StunTransactionId id;
+
+ if (stun->message.buffer != NULL) {
+ stun_message_id (&stun->message, id);
+ stun_agent_forget_transaction (&component->stun_agent, id);
+ }
+}
+
+static void
+priv_free_stun_transaction (gpointer data)
+{
+ g_slice_free (StunTransaction, data);
+}
+
+/*
+ * Remove a STUN transaction from a pair, and forget it
+ * from the related component stun agent.
+ *
+ * @pair the pair the stun transaction should be removed from.
+ * @stun the stun transaction to be removed.
+ * @component the component containing the stun agent used to
+ * forget the stun transaction.
+ */
+static void
+priv_remove_stun_transaction (CandidateCheckPair *pair,
+ StunTransaction *stun, NiceComponent *component)
+{
+ priv_forget_stun_transaction (stun, component);
+ pair->stun_transactions = g_slist_remove (pair->stun_transactions, stun);
+ priv_free_stun_transaction (stun);
+}
+
+/*
+ * Remove all STUN transactions from a pair, and forget them
+ * from the related component stun agent.
+ *
+ * @pair the pair the stun list should be cleared.
+ * @component the component containing the stun agent used to
+ * forget the stun transactions.
+ */
+static void
+priv_free_all_stun_transactions (CandidateCheckPair *pair,
+ NiceComponent *component)
+{
+ if (component)
+ g_slist_foreach (pair->stun_transactions, priv_forget_stun_transaction, component);
+ g_slist_free_full (pair->stun_transactions, priv_free_stun_transaction);
+ pair->stun_transactions = NULL;
+}
+
+static void
+candidate_check_pair_fail (NiceStream *stream, NiceAgent *agent, CandidateCheckPair *p)
+{
+ NiceComponent *component;
+
+ component = nice_stream_find_component_by_id (stream, p->component_id);
+ SET_PAIR_STATE (agent, p, NICE_CHECK_FAILED);
+ priv_free_all_stun_transactions (p, component);
+}
+
+/*
+ * Helper function for connectivity check timer callback that
+ * runs through the stream specific part of the state machine.
+ *
+ * @param schedule if TRUE, schedule a new check
+ *
+ * @return will return FALSE when no more pending timers.
+ */
+static gboolean priv_conn_check_tick_stream (NiceStream *stream, NiceAgent *agent)
+{
+ gboolean keep_timer_going = FALSE;
+ GSList *i, *j;
+ CandidateCheckPair *pair;
+ unsigned int timeout;
+ GTimeVal now;
+
+ g_get_current_time (&now);
+
+ /* step: process ongoing STUN transactions */
+ for (i = stream->conncheck_list; i ; i = i->next) {
+ CandidateCheckPair *p = i->data;
+ gchar tmpbuf1[INET6_ADDRSTRLEN], tmpbuf2[INET6_ADDRSTRLEN];
+ NiceComponent *component;
+ StunTransaction *stun;
+
+ if (p->stun_transactions == NULL)
+ continue;
+
+ if (!agent_find_component (agent, p->stream_id, p->component_id,
+ NULL, &component))
+ continue;
+
+ /* The first stun transaction of the list may eventually be
+ * retransmitted, other stun transactions just have their
+ * timer updated.
+ */
+
+ j = p->stun_transactions->next;
+
+ /* process all stun transactions except the first one */
+ while (j) {
+ StunTransaction *s = j->data;
+ GSList *next = j->next;
+
+ if (priv_timer_expired (&s->next_tick, &now))
+ switch (stun_timer_refresh (&s->timer)) {
+ case STUN_USAGE_TIMER_RETURN_TIMEOUT:
+ priv_remove_stun_transaction (p, s, component);
+ break;
+ case STUN_USAGE_TIMER_RETURN_RETRANSMIT:
+ timeout = stun_timer_remainder (&s->timer);
+ s->next_tick = now;
+ g_time_val_add (&s->next_tick, timeout * 1000);
+ break;
+ default:
+ break;
+ }
+ j = next;
+ }
+
+ if (p->state != NICE_CHECK_IN_PROGRESS)
+ continue;
+
+ /* process the first stun transaction of the list */
+ stun = p->stun_transactions->data;
+ if (!priv_timer_expired (&stun->next_tick, &now))
+ continue;
+
+ switch (stun_timer_refresh (&stun->timer)) {
+ case STUN_USAGE_TIMER_RETURN_TIMEOUT:
+timer_return_timeout:
+ /* case: error, abort processing */
+ nice_address_to_string (&p->local->addr, tmpbuf1);
+ nice_address_to_string (&p->remote->addr, tmpbuf2);
+ nice_debug ("Agent %p : Retransmissions failed, giving up on pair %p",
+ agent, p);
+ nice_debug ("Agent %p : Failed pair is [%s]:%u --> [%s]:%u", agent,
+ tmpbuf1, nice_address_get_port (&p->local->addr),
+ tmpbuf2, nice_address_get_port (&p->remote->addr));
+ candidate_check_pair_fail (stream, agent, p);
+ priv_print_conn_check_lists (agent, G_STRFUNC,
+ ", retransmission failed");
+
+ /* perform a check if a transition state from connected to
+ * ready can be performed. This may happen here, when the last
+ * in-progress pair has expired its retransmission count
+ * in priv_conn_check_tick_stream(), which is a condition to
+ * make the transition connected to ready.
+ */
+ priv_update_check_list_state_for_ready (agent, stream, component);
+ break;
+ case STUN_USAGE_TIMER_RETURN_RETRANSMIT:
+ /* case: retransmission stopped, due to the nomination of
+ * a pair with a higher priority than this in-progress pair,
+ * ICE spec, sect 8.1.2 "Updating States", item 2.2
+ */
+ if (!p->retransmit)
+ goto timer_return_timeout;
+
+ /* case: not ready, so schedule a new timeout */
+ timeout = stun_timer_remainder (&stun->timer);
+
+ nice_debug ("Agent %p :STUN transaction retransmitted on pair %p "
+ "(timer=%d/%d %d/%dms).",
+ agent, p,
+ stun->timer.retransmissions, stun->timer.max_retransmissions,
+ stun->timer.delay - timeout, stun->timer.delay);
+
+ agent_socket_send (p->sockptr, &p->remote->addr,
+ stun_message_length (&stun->message),
+ (gchar *)stun->buffer);
+
+ /* note: convert from milli to microseconds for g_time_val_add() */
+ stun->next_tick = now;
+ g_time_val_add (&stun->next_tick, timeout * 1000);
+
+ return TRUE;
+ case STUN_USAGE_TIMER_RETURN_SUCCESS:
+ timeout = stun_timer_remainder (&stun->timer);
+
+ /* note: convert from milli to microseconds for g_time_val_add() */
+ stun->next_tick = now;
+ g_time_val_add (&stun->next_tick, timeout * 1000);
+
+ keep_timer_going = TRUE;
+ break;
+ default:
+ /* Nothing to do. */
+ break;
+ }
+ }
+
+ /* step: perform an ordinary check, ICE spec, 5.8 "Scheduling Checks"
+ * note: This code is executed when the triggered checks list is
+ * empty, and when no STUN message has been sent (pacing constraint)
+ */
+ pair = priv_conn_check_find_next_waiting (stream->conncheck_list);
+ if (pair) {
+ priv_print_conn_check_lists (agent, G_STRFUNC,
+ ", got a pair in Waiting state");
+ priv_conn_check_initiate (agent, pair);
+ return TRUE;
+ }
+
+ /* note: this is unclear in the ICE spec, but a check list in Frozen
+ * state (where all pairs are in Frozen state) is not supposed to
+ * change its state by an ordinary check, but only by the success of
+ * checks in other check lists, in priv_conn_check_unfreeze_related().
+ * The underlying idea is to concentrate the checks on a single check
+ * list initially.
+ */
+ if (priv_is_checklist_frozen (stream))
+ return keep_timer_going;
+
+ /* step: ordinary check continued, if there's no pair in the waiting
+ * state, pick a pair in the frozen state
+ */
+ pair = priv_conn_check_find_next_frozen (stream->conncheck_list);
+ if (pair) {
+ priv_print_conn_check_lists (agent, G_STRFUNC,
+ ", got a pair in Frozen state");
+ SET_PAIR_STATE (agent, pair, NICE_CHECK_WAITING);
+ priv_conn_check_initiate (agent, pair);
+ return TRUE;
+ }
+ return keep_timer_going;
+}
+
+static gboolean
+priv_conn_check_tick_stream_nominate (NiceStream *stream, NiceAgent *agent)
+{
+ gboolean keep_timer_going = FALSE;
+ guint s_inprogress = 0;
+ guint s_succeeded = 0;
+ guint s_discovered = 0;
+ guint s_nominated = 0;
+ guint s_waiting_for_nomination = 0;
+ guint s_valid = 0;
+ guint frozen = 0;
+ guint waiting = 0;
+ GSList *i, *k;
+
+ for (i = stream->conncheck_list; i ; i = i->next) {
+ CandidateCheckPair *p = i->data;
+ if (p->state == NICE_CHECK_FROZEN)
+ ++frozen;
+ else if (p->state == NICE_CHECK_IN_PROGRESS)
+ ++s_inprogress;
+ else if (p->state == NICE_CHECK_WAITING)
+ ++waiting;
+ else if (p->state == NICE_CHECK_SUCCEEDED)
+ ++s_succeeded;
+ else if (p->state == NICE_CHECK_DISCOVERED)
+ ++s_discovered;
+ if (p->valid)
+ ++s_valid;
+
+ if ((p->state == NICE_CHECK_SUCCEEDED || p->state == NICE_CHECK_DISCOVERED)
+ && p->nominated)
+ ++s_nominated;
+ else if ((p->state == NICE_CHECK_SUCCEEDED ||
+ p->state == NICE_CHECK_DISCOVERED) && !p->nominated)
+ ++s_waiting_for_nomination;
+ }
+
+ /* note: keep the timer going as long as there is work to be done */
+ if (s_inprogress)
+ keep_timer_going = TRUE;
+
+ if (s_nominated < stream->n_components &&
+ s_waiting_for_nomination) {
+ if (NICE_AGENT_IS_COMPATIBLE_WITH_RFC5245_OR_OC2007R2 (agent)) {
+ if (agent->nomination_mode == NICE_NOMINATION_MODE_REGULAR &&
+ agent->controlling_mode) {
+#define NICE_MIN_NUMBER_OF_VALID_PAIRS 2
+ /* ICE 8.1.1.1 Regular nomination
+ * we choose to nominate the valid pair of a component if
+ * - there is no pair left frozen, waiting or in-progress, or
+ * - if there are at least two valid pairs, or
+ * - if there is at least one valid pair of type HOST-HOST
+ *
+ * This is the "stopping criterion" described in 8.1.1.1, and is
+ * a "local optimization" between accumulating more valid pairs,
+ * and limiting the time spent waiting for in-progress connections
+ * checks until they finally fail.
+ */
+ GSList *component_item;
+
+ for (component_item = stream->components; component_item;
+ component_item = component_item->next) {
+ NiceComponent *component = component_item->data;
+ gboolean already_done = FALSE;
+ gboolean stopping_criterion = FALSE;
+ guint p_valid = 0;
+ guint p_frozen = 0;
+ guint p_waiting = 0;
+ guint p_inprogress = 0;
+ guint p_host_host_valid = 0;
+
+ /* verify that the choice of the pair to be nominated
+ * has not already been done
+ */
+ for (k = stream->conncheck_list; k ; k = k->next) {
+ CandidateCheckPair *p = k->data;
+ if (p->component_id == component->id) {
+ if (p->use_candidate_on_next_check)
+ already_done = TRUE;
+ if (p->state == NICE_CHECK_FROZEN)
+ p_frozen++;
+ else if (p->state == NICE_CHECK_WAITING)
+ p_waiting++;
+ else if (p->state == NICE_CHECK_IN_PROGRESS)
+ p_inprogress++;
+ if (p->valid)
+ p_valid++;
+ if (p->valid &&
+ p->local->type == NICE_CANDIDATE_TYPE_HOST &&
+ p->remote->type == NICE_CANDIDATE_TYPE_HOST)
+ p_host_host_valid++;
+ }
+ }
+
+ if (already_done)
+ continue;
+
+ stopping_criterion =
+ (p_host_host_valid > 0 ||
+ p_valid >= NICE_MIN_NUMBER_OF_VALID_PAIRS ||
+ (p_waiting == 0 && p_inprogress == 0 && p_frozen == 0));
+
+ if (!stopping_criterion)
+ continue;
+
+ /* when the stopping criterion is satisfied, we choose
+ * a pair to be nominated in the list of valid pairs,
+ * and add it to the triggered checks list
+ */
+ for (k = stream->conncheck_list; k ; k = k->next) {
+ CandidateCheckPair *p = k->data;
+ /* note: highest priority item selected (list always sorted) */
+ if (p->component_id == component->id &&
+ !p->nominated &&
+ !p->use_candidate_on_next_check &&
+ p->valid) {
+ /* According a ICE spec, sect 8.1.1.1. "Regular
+ * Nomination", we enqueue the check that produced this
+ * valid pair. When this pair has been discovered, we want
+ * to test its parent pair instead.
+ */
+ if (p->succeeded_pair != NULL) {
+ g_assert (p->state == NICE_CHECK_DISCOVERED);
+ p = p->succeeded_pair;
+ }
+ g_assert (p->state == NICE_CHECK_SUCCEEDED);
+ nice_debug ("Agent %p : restarting check of pair %p with "
+ "USE-CANDIDATE attrib (regular nomination)", agent, p);
+ p->use_candidate_on_next_check = TRUE;
+ priv_add_pair_to_triggered_check_queue (agent, p);
+ keep_timer_going = TRUE;
+ break; /* move to the next component */
+ }
+ }
+ }
+ }
+ } else if (agent->controlling_mode) {
+ GSList *component_item;
+
+ for (component_item = stream->components; component_item;
+ component_item = component_item->next) {
+ NiceComponent *component = component_item->data;
+
+ for (k = stream->conncheck_list; k ; k = k->next) {
+ CandidateCheckPair *p = k->data;
+ /* note: highest priority item selected (list always sorted) */
+ if (p->component_id == component->id &&
+ (p->state == NICE_CHECK_SUCCEEDED ||
+ p->state == NICE_CHECK_DISCOVERED)) {
+ nice_debug ("Agent %p : restarting check of pair %p as the "
+ "nominated pair.", agent, p);
+ p->nominated = TRUE;
+ priv_update_selected_pair (agent, component, p);
+ priv_add_pair_to_triggered_check_queue (agent, p);
+ keep_timer_going = TRUE;
+ break; /* move to the next component */
+ }
+ }
+ }
+ }
+ }
+ if (stream->tick_counter++ % 50 == 0)
+ nice_debug ("Agent %p : stream %u: timer tick #%u: %u frozen, %u in-progress, "
+ "%u waiting, %u succeeded, %u discovered, %u nominated, "
+ "%u waiting-for-nom, %u valid.", agent, stream->id,
+ stream->tick_counter, frozen, s_inprogress, waiting, s_succeeded,
+ s_discovered, s_nominated, s_waiting_for_nomination, s_valid);
+
+ return keep_timer_going;
+
+}
+
+static void
+conn_check_stop (NiceAgent *agent)
+{
+ if (agent->conncheck_timer_source == NULL)
+ return;
+
+ g_source_destroy (agent->conncheck_timer_source);
+ g_source_unref (agent->conncheck_timer_source);
+ agent->conncheck_timer_source = NULL;
+ agent->conncheck_timer_grace_period = 0;
+}
+
+
+/*
+ * Timer callback that handles initiating and managing connectivity
+ * checks (paced by the Ta timer).
+ *
+ * This function is designed for the g_timeout_add() interface.
+ *
+ * @return will return FALSE when no more pending timers.
+ */
+static gboolean priv_conn_check_tick_agent_locked (NiceAgent *agent,
+ gpointer user_data)
+{
+ CandidateCheckPair *pair = NULL;
+ gboolean keep_timer_going = FALSE;
+ GSList *i, *j;
+
+ /* configure the initial state of the check lists of the agent
+ * as described in ICE spec, 5.7.4
+ *
+ * if all pairs in all check lists are in frozen state, then
+ * we are in the initial state (5.7.4, point 1.)
+ */
+ if (priv_number_of_active_check_lists (agent) == 0) {
+ /* set some pairs of the first stream in the waiting state
+ * ICE spec, 5.7.4, point 2.
+ *
+ * note: we adapt the ICE spec here, by selecting the first
+ * frozen check list, which is not necessarily the check
+ * list of the first stream (the first stream may be completed)
+ */
+ NiceStream *stream = priv_find_first_frozen_check_list (agent);
+ if (stream)
+ priv_conn_check_unfreeze_next (agent, stream);
+ }
+
+ /* step: perform a test from the triggered checks list,
+ * ICE spec, 5.8 "Scheduling Checks"
+ */
+ pair = priv_get_pair_from_triggered_check_queue (agent);
+
+ if (pair) {
+ priv_print_conn_check_lists (agent, G_STRFUNC,
+ ", got a pair from triggered check list");
+ if (conn_check_send (agent, pair)) {
+ SET_PAIR_STATE (agent, pair, NICE_CHECK_FAILED);
+ return FALSE;
+ }
+ return TRUE;
+ }
+
+ /* step: process ongoing STUN transactions and
+ * perform an ordinary check, ICE spec, 5.8, "Scheduling Checks"
+ */
+ for (i = agent->streams; i ; i = i->next) {
+ NiceStream *stream = i->data;
+ if (priv_conn_check_tick_stream (stream, agent))
+ keep_timer_going = TRUE;
+ if (priv_conn_check_tick_stream_nominate (stream, agent))
+ keep_timer_going = TRUE;
+ }
+
+ /* step: if no work left and a conncheck list of a stream is still
+ * frozen, set the pairs to waiting, according to ICE SPEC, sect
+ * 7.1.3.3. "Check List and Timer State Updates"
+ */
+ if (!keep_timer_going) {
+ for (i = agent->streams; i ; i = i->next) {
+ NiceStream *stream = i->data;
+ if (priv_is_checklist_frozen (stream)) {
+ nice_debug ("Agent %p : stream %d conncheck list is still "
+ "frozen, while other lists are completed. Unfreeze it.",
+ agent, stream->id);
+ keep_timer_going = priv_conn_check_unfreeze_next (agent, stream);
+ }
+ if (!keep_timer_going && !stream->peer_gathering_done) {
+ keep_timer_going = TRUE;
+ }
+ }
+ }
+
+ /* note: we provide a grace period before declaring a component as
+ * failed. Components marked connected, and then ready follow another
+ * code path, and are not concerned by this grace period.
+ */
+ if (!keep_timer_going && agent->conncheck_timer_grace_period == 0)
+ nice_debug ("Agent %p : waiting %d msecs before checking "
+ "for failed components.", agent, NICE_AGENT_MAX_TIMER_GRACE_PERIOD);
+
+ if (keep_timer_going)
+ agent->conncheck_timer_grace_period = 0;
+ else
+ agent->conncheck_timer_grace_period += agent->timer_ta;
+
+ /* step: stop timer if no work left */
+ if (!keep_timer_going &&
+ agent->conncheck_timer_grace_period >= NICE_AGENT_MAX_TIMER_GRACE_PERIOD) {
+ nice_debug ("Agent %p : checking for failed components now.", agent);
+ for (i = agent->streams; i; i = i->next) {
+ NiceStream *stream = i->data;
+ priv_update_check_list_failed_components (agent, stream);
+ for (j = stream->components; j; j = j->next) {
+ NiceComponent *component = j->data;
+ priv_update_check_list_state_for_ready (agent, stream, component);
+ }
+ }
+
+ nice_debug ("Agent %p : %s: stopping conncheck timer", agent, G_STRFUNC);
+ priv_print_conn_check_lists (agent, G_STRFUNC,
+ ", conncheck timer stopped");
+
+ /* Stopping the timer so destroy the source.. this will allow
+ the timer to be reset if we get a set_remote_candidates after this
+ point */
+ conn_check_stop (agent);
+
+ /* XXX: what to signal, is all processing now really done? */
+ nice_debug ("Agent %p : changing conncheck state to COMPLETED.", agent);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean priv_conn_keepalive_retransmissions_tick_agent_locked (
+ NiceAgent *agent, gpointer pointer)
+{
+ CandidatePair *pair = (CandidatePair *) pointer;
+
+ g_source_destroy (pair->keepalive.tick_source);
+ g_source_unref (pair->keepalive.tick_source);
+ pair->keepalive.tick_source = NULL;
+
+ switch (stun_timer_refresh (&pair->keepalive.timer)) {
+ case STUN_USAGE_TIMER_RETURN_TIMEOUT:
+ {
+ /* Time out */
+ StunTransactionId id;
+ NiceComponent *component;
+
+ if (!agent_find_component (agent,
+ pair->keepalive.stream_id, pair->keepalive.component_id,
+ NULL, &component)) {
+ nice_debug ("Could not find stream or component in"
+ " priv_conn_keepalive_retransmissions_tick");
+ return FALSE;
+ }
+
+ stun_message_id (&pair->keepalive.stun_message, id);
+ stun_agent_forget_transaction (&component->stun_agent, id);
+ pair->keepalive.stun_message.buffer = NULL;
+
+ if (agent->media_after_tick) {
+ nice_debug ("Agent %p : Keepalive conncheck timed out!! "
+ "but media was received. Suspecting keepalive lost because of "
+ "network bottleneck", agent);
+ } else {
+ nice_debug ("Agent %p : Keepalive conncheck timed out!! "
+ "peer probably lost connection", agent);
+ agent_signal_component_state_change (agent,
+ pair->keepalive.stream_id, pair->keepalive.component_id,
+ NICE_COMPONENT_STATE_FAILED);
+ }
+ break;
+ }
+ case STUN_USAGE_TIMER_RETURN_RETRANSMIT:
+ /* Retransmit */
+ agent_socket_send (pair->local->sockptr, &pair->remote->addr,
+ stun_message_length (&pair->keepalive.stun_message),
+ (gchar *)pair->keepalive.stun_buffer);
+
+ nice_debug ("Agent %p : Retransmitting keepalive conncheck",
+ agent);
+ agent_timeout_add_with_context (agent,
+ &pair->keepalive.tick_source,
+ "Pair keepalive", stun_timer_remainder (&pair->keepalive.timer),
+ priv_conn_keepalive_retransmissions_tick_agent_locked, pair);
+ break;
+ case STUN_USAGE_TIMER_RETURN_SUCCESS:
+ agent_timeout_add_with_context (agent,
+ &pair->keepalive.tick_source,
+ "Pair keepalive", stun_timer_remainder (&pair->keepalive.timer),
+ priv_conn_keepalive_retransmissions_tick_agent_locked, pair);
+ break;
+ default:
+ g_assert_not_reached();
+ break;
+ }
+
+ return FALSE;
+}
+
+static guint32 peer_reflexive_candidate_priority (NiceAgent *agent,
+ NiceCandidate *local_candidate)
+{
+ NiceCandidate *candidate_priority =
+ nice_candidate_new (NICE_CANDIDATE_TYPE_PEER_REFLEXIVE);
+ guint32 priority;
+
+ candidate_priority->transport = local_candidate->transport;
+ candidate_priority->component_id = local_candidate->component_id;
+ candidate_priority->base_addr = local_candidate->addr;
+ if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE) {
+ priority = nice_candidate_jingle_priority (candidate_priority);
+ } else if (agent->compatibility == NICE_COMPATIBILITY_MSN ||
+ agent->compatibility == NICE_COMPATIBILITY_OC2007) {
+ priority = nice_candidate_msn_priority (candidate_priority);
+ } else if (agent->compatibility == NICE_COMPATIBILITY_OC2007R2) {
+ priority = nice_candidate_ms_ice_priority (candidate_priority,
+ agent->reliable, FALSE);
+ } else {
+ priority = nice_candidate_ice_priority (candidate_priority,
+ agent->reliable, FALSE);
+ }
+ nice_candidate_free (candidate_priority);
+
+ return priority;
+}
+
+static void ms_ice2_legacy_conncheck_send(StunMessage *msg, NiceSocket *sock,
+ const NiceAddress *remote_addr)
+{
+ uint32_t *fingerprint_attr;
+ uint32_t fingerprint_orig;
+ uint16_t fingerprint_len;
+ size_t buffer_len;
+
+ if (msg->agent->ms_ice2_send_legacy_connchecks == FALSE) {
+ return;
+ }
+
+ fingerprint_attr = (uint32_t *)stun_message_find (msg,
+ STUN_ATTRIBUTE_FINGERPRINT, &fingerprint_len);
+
+ if (fingerprint_attr == NULL) {
+ nice_debug ("FINGERPRINT not found.");
+ return;
+ }
+
+ if (fingerprint_len != sizeof (fingerprint_orig)) {
+ nice_debug ("Unexpected FINGERPRINT length %u.", fingerprint_len);
+ return;
+ }
+
+ memcpy (&fingerprint_orig, fingerprint_attr, sizeof (fingerprint_orig));
+
+ buffer_len = stun_message_length (msg);
+
+ *fingerprint_attr = stun_fingerprint (msg->buffer, buffer_len, TRUE);
+
+ agent_socket_send (sock, remote_addr, buffer_len, (gchar *)msg->buffer);
+
+ memcpy (fingerprint_attr, &fingerprint_orig, sizeof (fingerprint_orig));
+}
+
+/*
+ * Timer callback that handles initiating and managing connectivity
+ * checks (paced by the Ta timer).
+ *
+ * This function is designed for the g_timeout_add() interface.
+ *
+ * @return will return FALSE when no more pending timers.
+ */
+static gboolean priv_conn_keepalive_tick_unlocked (NiceAgent *agent)
+{
+ GSList *i, *j, *k;
+ int errors = 0;
+ gboolean ret = FALSE;
+ size_t buf_len = 0;
+
+ /* case 1: session established and media flowing
+ * (ref ICE sect 10 "Keepalives" ID-19) */
+ for (i = agent->streams; i; i = i->next) {
+
+ NiceStream *stream = i->data;
+ for (j = stream->components; j; j = j->next) {
+ NiceComponent *component = j->data;
+ if (component->selected_pair.local != NULL) {
+ CandidatePair *p = &component->selected_pair;
+
+ /* Disable keepalive checks on TCP candidates unless explicitly enabled */
+ if (p->local->transport != NICE_CANDIDATE_TRANSPORT_UDP &&
+ !agent->keepalive_conncheck)
+ continue;
+
+ if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE ||
+ agent->keepalive_conncheck) {
+ uint8_t uname[NICE_STREAM_MAX_UNAME];
+ size_t uname_len =
+ priv_create_username (agent, agent_find_stream (agent, stream->id),
+ component->id, p->remote, p->local, uname, sizeof (uname),
+ FALSE);
+ uint8_t *password = NULL;
+ size_t password_len = priv_get_password (agent,
+ agent_find_stream (agent, stream->id), p->remote, &password);
+
+ if (p->keepalive.stun_message.buffer != NULL) {
+ nice_debug ("Agent %p: Keepalive for s%u:c%u still"
+ " retransmitting, not restarting", agent, stream->id,
+ component->id);
+ continue;
+ }
+
+ if (nice_debug_is_enabled ()) {
+ gchar tmpbuf[INET6_ADDRSTRLEN];
+ nice_address_to_string (&p->remote->addr, tmpbuf);
+ nice_debug ("Agent %p : Keepalive STUN-CC REQ to '%s:%u', "
+ "(c-id:%u), username='%.*s' (%" G_GSIZE_FORMAT "), "
+ "password='%.*s' (%" G_GSIZE_FORMAT "), priority=%u.", agent,
+ tmpbuf, nice_address_get_port (&p->remote->addr),
+ component->id, (int) uname_len, uname, uname_len,
+ (int) password_len, password, password_len,
+ p->prflx_priority);
+ }
+ if (uname_len > 0) {
+ buf_len = stun_usage_ice_conncheck_create (&component->stun_agent,
+ &p->keepalive.stun_message, p->keepalive.stun_buffer,
+ sizeof(p->keepalive.stun_buffer),
+ uname, uname_len, password, password_len,
+ agent->controlling_mode, agent->controlling_mode,
+ p->prflx_priority,
+ agent->tie_breaker,
+ NULL,
+ agent_to_ice_compatibility (agent));
+
+ nice_debug ("Agent %p: conncheck created %zd - %p",
+ agent, buf_len, p->keepalive.stun_message.buffer);
+
+ if (buf_len > 0) {
+ stun_timer_start (&p->keepalive.timer,
+ agent->stun_initial_timeout,
+ agent->stun_max_retransmissions);
+
+ agent->media_after_tick = FALSE;
+
+ /* send the conncheck */
+ agent_socket_send (p->local->sockptr, &p->remote->addr,
+ buf_len, (gchar *)p->keepalive.stun_buffer);
+
+ p->keepalive.stream_id = stream->id;
+ p->keepalive.component_id = component->id;
+
+ agent_timeout_add_with_context (agent,
+ &p->keepalive.tick_source, "Pair keepalive",
+ stun_timer_remainder (&p->keepalive.timer),
+ priv_conn_keepalive_retransmissions_tick_agent_locked, p);
+ } else {
+ ++errors;
+ }
+ }
+ } else {
+ buf_len = stun_usage_bind_keepalive (&component->stun_agent,
+ &p->keepalive.stun_message, p->keepalive.stun_buffer,
+ sizeof(p->keepalive.stun_buffer));
+
+ if (buf_len > 0) {
+ agent_socket_send (p->local->sockptr, &p->remote->addr, buf_len,
+ (gchar *)p->keepalive.stun_buffer);
+
+ if (agent->compatibility == NICE_COMPATIBILITY_OC2007R2) {
+ ms_ice2_legacy_conncheck_send (&p->keepalive.stun_message,
+ p->local->sockptr, &p->remote->addr);
+ }
+
+ nice_debug ("Agent %p : stun_bind_keepalive for pair %p res %d.",
+ agent, p, (int) buf_len);
+ } else {
+ ++errors;
+ }
+ }
+ }
+ }
+ }
+
+ /* case 2: connectivity establishment ongoing
+ * (ref ICE sect 4.1.1.4 "Keeping Candidates Alive" ID-19) */
+ for (i = agent->streams; i; i = i->next) {
+ NiceStream *stream = i->data;
+ for (j = stream->components; j; j = j->next) {
+ NiceComponent *component = j->data;
+ if (component->state < NICE_COMPONENT_STATE_READY &&
+ agent->stun_server_ip) {
+ NiceAddress stun_server;
+ if (nice_address_set_from_string (&stun_server, agent->stun_server_ip)) {
+ StunAgent stun_agent;
+ uint8_t stun_buffer[STUN_MAX_MESSAGE_SIZE_IPV6];
+ StunMessage stun_message;
+ size_t buffer_len = 0;
+
+ nice_address_set_port (&stun_server, agent->stun_server_port);
+
+ nice_agent_init_stun_agent (agent, &stun_agent);
+
+ buffer_len = stun_usage_bind_create (&stun_agent,
+ &stun_message, stun_buffer, sizeof(stun_buffer));
+
+ for (k = component->local_candidates; k; k = k->next) {
+ NiceCandidate *candidate = (NiceCandidate *) k->data;
+ if (candidate->type == NICE_CANDIDATE_TYPE_HOST &&
+ candidate->transport == NICE_CANDIDATE_TRANSPORT_UDP &&
+ nice_address_ip_version (&candidate->addr) ==
+ nice_address_ip_version (&stun_server)) {
+ /* send the conncheck */
+ nice_debug ("Agent %p : resending STUN on %s to keep the "
+ "candidate alive.", agent, candidate->foundation);
+ agent_socket_send (candidate->sockptr, &stun_server,
+ buffer_len, (gchar *)stun_buffer);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (errors) {
+ nice_debug ("Agent %p : %s: stopping keepalive timer", agent, G_STRFUNC);
+ goto done;
+ }
+
+ ret = TRUE;
+
+ done:
+ return ret;
+}
+
+static gboolean priv_conn_keepalive_tick_agent_locked (NiceAgent *agent,
+ gpointer pointer)
+{
+ gboolean ret;
+
+ ret = priv_conn_keepalive_tick_unlocked (agent);
+ if (ret == FALSE) {
+ if (agent->keepalive_timer_source) {
+ g_source_destroy (agent->keepalive_timer_source);
+ g_source_unref (agent->keepalive_timer_source);
+ agent->keepalive_timer_source = NULL;
+ }
+ }
+
+ return ret;
+}
+
+
+static gboolean priv_turn_allocate_refresh_retransmissions_tick_agent_locked (
+ NiceAgent *agent, gpointer pointer)
+{
+ CandidateRefresh *cand = (CandidateRefresh *) pointer;
+
+ g_source_destroy (cand->tick_source);
+ g_source_unref (cand->tick_source);
+ cand->tick_source = NULL;
+
+ switch (stun_timer_refresh (&cand->timer)) {
+ case STUN_USAGE_TIMER_RETURN_TIMEOUT:
+ {
+ /* Time out */
+ StunTransactionId id;
+
+ stun_message_id (&cand->stun_message, id);
+ stun_agent_forget_transaction (&cand->stun_agent, id);
+
+ refresh_free (agent, cand);
+ break;
+ }
+ case STUN_USAGE_TIMER_RETURN_RETRANSMIT:
+ /* Retransmit */
+ agent_socket_send (cand->nicesock, &cand->server,
+ stun_message_length (&cand->stun_message), (gchar *)cand->stun_buffer);
+
+ agent_timeout_add_with_context (agent, &cand->tick_source,
+ "Candidate TURN refresh", stun_timer_remainder (&cand->timer),
+ priv_turn_allocate_refresh_retransmissions_tick_agent_locked, cand);
+ break;
+ case STUN_USAGE_TIMER_RETURN_SUCCESS:
+ agent_timeout_add_with_context (agent, &cand->tick_source,
+ "Candidate TURN refresh", stun_timer_remainder (&cand->timer),
+ priv_turn_allocate_refresh_retransmissions_tick_agent_locked, cand);
+ break;
+ default:
+ /* Nothing to do. */
+ break;
+ }
+
+ return G_SOURCE_REMOVE;
+}
+
+static void priv_turn_allocate_refresh_tick_unlocked (NiceAgent *agent,
+ CandidateRefresh *cand)
+{
+ uint8_t *username;
+ gsize username_len;
+ uint8_t *password;
+ gsize password_len;
+ size_t buffer_len = 0;
+ StunUsageTurnCompatibility turn_compat =
+ agent_to_turn_compatibility (agent);
+
+ username = (uint8_t *)cand->candidate->turn->username;
+ username_len = (size_t) strlen (cand->candidate->turn->username);
+ password = (uint8_t *)cand->candidate->turn->password;
+ password_len = (size_t) strlen (cand->candidate->turn->password);
+
+ if (turn_compat == STUN_USAGE_TURN_COMPATIBILITY_MSN ||
+ turn_compat == STUN_USAGE_TURN_COMPATIBILITY_OC2007) {
+ username = g_base64_decode ((gchar *)username, &username_len);
+ password = g_base64_decode ((gchar *)password, &password_len);
+ }
+
+ buffer_len = stun_usage_turn_create_refresh (&cand->stun_agent,
+ &cand->stun_message, cand->stun_buffer, sizeof(cand->stun_buffer),
+ cand->stun_resp_msg.buffer == NULL ? NULL : &cand->stun_resp_msg, -1,
+ username, username_len,
+ password, password_len,
+ turn_compat);
+
+ if (turn_compat == STUN_USAGE_TURN_COMPATIBILITY_MSN ||
+ turn_compat == STUN_USAGE_TURN_COMPATIBILITY_OC2007) {
+ g_free (username);
+ g_free (password);
+ }
+
+ nice_debug ("Agent %p : Sending allocate Refresh %zd", agent,
+ buffer_len);
+
+ if (cand->tick_source != NULL) {
+ g_source_destroy (cand->tick_source);
+ g_source_unref (cand->tick_source);
+ cand->tick_source = NULL;
+ }
+
+ if (buffer_len > 0) {
+ stun_timer_start (&cand->timer,
+ agent->stun_initial_timeout,
+ agent->stun_max_retransmissions);
+
+ /* send the refresh */
+ agent_socket_send (cand->nicesock, &cand->server,
+ buffer_len, (gchar *)cand->stun_buffer);
+
+ agent_timeout_add_with_context (agent, &cand->tick_source,
+ "Candidate TURN refresh", stun_timer_remainder (&cand->timer),
+ priv_turn_allocate_refresh_retransmissions_tick_agent_locked, cand);
+ }
+
+}
+
+
+/*
+ * Timer callback that handles refreshing TURN allocations
+ *
+ * This function is designed for the g_timeout_add() interface.
+ *
+ * @return will return FALSE when no more pending timers.
+ */
+static gboolean priv_turn_allocate_refresh_tick_agent_locked (NiceAgent *agent,
+ gpointer pointer)
+{
+ CandidateRefresh *cand = (CandidateRefresh *) pointer;
+
+ priv_turn_allocate_refresh_tick_unlocked (agent, cand);
+
+ return G_SOURCE_REMOVE;
+}
+
+
+/*
+ * Initiates the next pending connectivity check.
+ */
+void conn_check_schedule_next (NiceAgent *agent)
+{
+ if (agent->discovery_unsched_items > 0)
+ nice_debug ("Agent %p : WARN: starting conn checks before local candidate gathering is finished.", agent);
+
+ /* step: schedule timer if not running yet */
+ if (agent->conncheck_timer_source == NULL) {
+ agent_timeout_add_with_context (agent, &agent->conncheck_timer_source,
+ "Connectivity check schedule", agent->timer_ta,
+ priv_conn_check_tick_agent_locked, NULL);
+ }
+
+ /* step: also start the keepalive timer */
+ if (agent->keepalive_timer_source == NULL) {
+ agent_timeout_add_with_context (agent, &agent->keepalive_timer_source,
+ "Connectivity keepalive timeout", NICE_AGENT_TIMER_TR_DEFAULT,
+ priv_conn_keepalive_tick_agent_locked, NULL);
+ }
+}
+
+/*
+ * Compares two connectivity check items. Checkpairs are sorted
+ * in descending priority order, with highest priority item at
+ * the start of the list.
+ */
+gint conn_check_compare (const CandidateCheckPair *a, const CandidateCheckPair *b)
+{
+ if (a->priority > b->priority)
+ return -1;
+ else if (a->priority < b->priority)
+ return 1;
+ return 0;
+}
+
+void
+conn_check_remote_candidates_set(NiceAgent *agent, NiceStream *stream,
+ NiceComponent *component)
+{
+ GSList *l, *m;
+ GList *k;
+
+ for (k = component->incoming_checks.head; k;) {
+ IncomingCheck *icheck = k->data;
+ GList *k_next = k->next;
+
+ /* sect 7.2.1.3., "Learning Peer Reflexive Candidates", has to
+ * be handled separately */
+ for (l = component->remote_candidates; l; l = l->next) {
+ NiceCandidate *rcand = l->data;
+ NiceCandidate *lcand = NULL;
+
+ if (nice_address_equal (&rcand->addr, &icheck->from)) {
+ for (m = component->local_candidates; m; m = m->next) {
+ NiceCandidate *cand = m->data;
+
+ if (nice_address_equal (&cand->addr, &icheck->local_socket->addr)) {
+ lcand = cand;
+ break;
+ }
+ }
+
+ g_assert (lcand != NULL);
+ priv_schedule_triggered_check (agent, stream, component,
+ icheck->local_socket, rcand);
+ if (icheck->use_candidate)
+ priv_mark_pair_nominated (agent, stream, component,
+ lcand, rcand);
+
+ g_queue_delete_link (&component->incoming_checks, k);
+ break;
+ }
+ }
+ k = k_next;
+ }
+}
+
+/*
+ * Handle any processing steps for connectivity checks after
+ * remote credentials have been set. This function handles
+ * the special case where answerer has sent us connectivity
+ * checks before the answer (containing credentials information),
+ * reaches us. The special case is documented in RFC 5245 sect 7.2.
+ * ).
+ */
+void conn_check_remote_credentials_set(NiceAgent *agent, NiceStream *stream)
+{
+ GSList *j;
+
+ for (j = stream->components; j ; j = j->next) {
+ NiceComponent *component = j->data;
+
+ conn_check_remote_candidates_set(agent, stream, component);
+ }
+}
+
+/*
+ * Enforces the upper limit for connectivity checks as described
+ * in ICE spec section 5.7.3 (ID-19). See also
+ * conn_check_add_for_candidate().
+ */
+static GSList *priv_limit_conn_check_list_size (NiceAgent *agent,
+ GSList *conncheck_list, guint upper_limit)
+{
+ guint valid = 0;
+ guint cancelled = 0;
+ GSList *item = conncheck_list;
+
+ while (item) {
+ CandidateCheckPair *pair = item->data;
+ GSList *next = item->next;
+
+ valid++;
+ if (valid > upper_limit) {
+ candidate_check_pair_free (agent, pair);
+ conncheck_list = g_slist_delete_link (conncheck_list, item);
+ cancelled++;
+ }
+ item = next;
+ }
+
+ if (cancelled > 0)
+ nice_debug ("Agent : Pruned %d candidates. Conncheck list has %d elements"
+ " left. Maximum connchecks allowed : %d", cancelled, valid,
+ upper_limit);
+ return conncheck_list;
+}
+
+/*
+ * Changes the selected pair for the component if 'pair' is nominated
+ * and has higher priority than the currently selected pair. See
+ * ICE sect 11.1.1. "Procedures for Full Implementations" (ID-19).
+ */
+static gboolean priv_update_selected_pair (NiceAgent *agent, NiceComponent *component, CandidateCheckPair *pair)
+{
+ CandidatePair cpair = { 0, };
+
+ g_assert (component);
+ g_assert (pair);
+ if (pair->priority > component->selected_pair.priority) {
+ nice_debug ("Agent %p : changing SELECTED PAIR for component %u: %s:%s "
+ "(prio:%" G_GUINT64_FORMAT ").", agent, component->id,
+ pair->local->foundation, pair->remote->foundation, pair->priority);
+
+ cpair.local = pair->local;
+ cpair.remote = pair->remote;
+ cpair.priority = pair->priority;
+ /* cpair.keepalive is not used by nice_component_update_selected_pair() */
+
+ nice_component_update_selected_pair (agent, component, &cpair);
+
+ priv_conn_keepalive_tick_unlocked (agent);
+
+ agent_signal_new_selected_pair (agent, pair->stream_id, component->id,
+ pair->local, pair->remote);
+
+ }
+
+ return TRUE;
+}
+
+/*
+ * Updates the check list state.
+ *
+ * Implements parts of the algorithm described in
+ * ICE sect 8.1.2. "Updating States" (RFC 5245): if for any
+ * component, all checks have been completed and have
+ * failed to produce a nominated pair, mark that component's
+ * state to NICE_CHECK_FAILED.
+ *
+ * Sends a component state changesignal via 'agent'.
+ */
+static void priv_update_check_list_failed_components (NiceAgent *agent, NiceStream *stream)
+{
+ GSList *i;
+ gboolean completed;
+ guint nominated;
+ /* note: emitting a signal might cause the client
+ * to remove the stream, thus the component count
+ * must be fetched before entering the loop*/
+ guint c, components = stream->n_components;
+
+ if (stream->conncheck_list == NULL)
+ return;
+
+ for (i = agent->discovery_list; i; i = i->next) {
+ CandidateDiscovery *d = i->data;
+
+ /* There is still discovery ogoing for this stream,
+ * so don't fail any of it's candidates.
+ */
+ if (d->stream_id == stream->id && !d->done)
+ return;
+ }
+ if (agent->discovery_list != NULL)
+ return;
+
+ /* note: iterate the conncheck list for each component separately */
+ for (c = 0; c < components; c++) {
+ NiceComponent *component = NULL;
+ if (!agent_find_component (agent, stream->id, c+1, NULL, &component))
+ continue;
+
+ nominated = 0;
+ completed = TRUE;
+ for (i = stream->conncheck_list; i; i = i->next) {
+ CandidateCheckPair *p = i->data;
+
+ g_assert (p->stream_id == stream->id);
+
+ if (p->component_id == (c + 1)) {
+ if (p->nominated)
+ ++nominated;
+ if (p->state != NICE_CHECK_FAILED &&
+ p->state != NICE_CHECK_SUCCEEDED &&
+ p->state != NICE_CHECK_DISCOVERED)
+ completed = FALSE;
+ }
+ }
+
+ /* note: all pairs are either failed or succeeded, and the component
+ * has not produced a nominated pair.
+ * Set the component to FAILED only if it actually had remote candidates
+ * that failed.. */
+ if (completed && nominated == 0 &&
+ component != NULL && component->remote_candidates != NULL)
+ agent_signal_component_state_change (agent,
+ stream->id,
+ (c + 1), /* component-id */
+ NICE_COMPONENT_STATE_FAILED);
+ }
+}
+
+/*
+ * Updates the check list state for a stream component.
+ *
+ * Implements the algorithm described in ICE sect 8.1.2
+ * "Updating States" (ID-19) as it applies to checks of
+ * a certain component. If there are any nominated pairs,
+ * ICE processing may be concluded, and component state is
+ * changed to READY.
+ *
+ * Sends a component state changesignal via 'agent'.
+ */
+static void priv_update_check_list_state_for_ready (NiceAgent *agent, NiceStream *stream, NiceComponent *component)
+{
+ GSList *i;
+ guint valid = 0, nominated = 0;
+
+ g_assert (component);
+
+ /* step: search for at least one nominated pair */
+ for (i = stream->conncheck_list; i; i = i->next) {
+ CandidateCheckPair *p = i->data;
+ if (p->component_id == component->id) {
+ if (p->valid) {
+ ++valid;
+ if (p->nominated == TRUE) {
+ ++nominated;
+ }
+ }
+ }
+ }
+
+ if (nominated > 0) {
+ /* Only go to READY if no checks are left in progress. If there are
+ * any that are kept, then this function will be called again when the
+ * conncheck tick timer finishes them all */
+ if (priv_prune_pending_checks (agent, stream, component->id) == 0) {
+ /* Continue through the states to give client code a nice
+ * logical progression. See http://phabricator.freedesktop.org/D218 for
+ * discussion. */
+ if (component->state < NICE_COMPONENT_STATE_CONNECTING ||
+ component->state == NICE_COMPONENT_STATE_FAILED)
+ agent_signal_component_state_change (agent, stream->id, component->id,
+ NICE_COMPONENT_STATE_CONNECTING);
+ if (component->state < NICE_COMPONENT_STATE_CONNECTED)
+ agent_signal_component_state_change (agent, stream->id, component->id,
+ NICE_COMPONENT_STATE_CONNECTED);
+ agent_signal_component_state_change (agent, stream->id,
+ component->id, NICE_COMPONENT_STATE_READY);
+ }
+ }
+ nice_debug ("Agent %p : conn.check list status: %u nominated, %u valid, c-id %u.", agent, nominated, valid, component->id);
+}
+
+/*
+ * The remote party has signalled that the candidate pair
+ * described by 'component' and 'remotecand' is nominated
+ * for use.
+ */
+static void priv_mark_pair_nominated (NiceAgent *agent, NiceStream *stream, NiceComponent *component, NiceCandidate *localcand, NiceCandidate *remotecand)
+{
+ GSList *i;
+
+ g_assert (component);
+
+ if (NICE_AGENT_IS_COMPATIBLE_WITH_RFC5245_OR_OC2007R2 (agent) &&
+ agent->controlling_mode)
+ return;
+
+ /* step: search for at least one nominated pair */
+ for (i = stream->conncheck_list; i; i = i->next) {
+ CandidateCheckPair *pair = i->data;
+ if (pair->local == localcand && pair->remote == remotecand) {
+ /* ICE, 7.2.1.5. Updating the Nominated Flag */
+ /* note: TCP candidates typically produce peer reflexive
+ * candidate, generating a "discovered" pair that can be
+ * nominated.
+ */
+ if (pair->state == NICE_CHECK_SUCCEEDED &&
+ pair->discovered_pair != NULL) {
+ pair = pair->discovered_pair;
+ g_assert (pair->state == NICE_CHECK_DISCOVERED);
+ }
+
+ /* If the state of this pair is In-Progress, [...] the resulting
+ * valid pair has its nominated flag set when the response
+ * arrives.
+ */
+ if (NICE_AGENT_IS_COMPATIBLE_WITH_RFC5245_OR_OC2007R2 (agent) &&
+ pair->state == NICE_CHECK_IN_PROGRESS) {
+ pair->mark_nominated_on_response_arrival = TRUE;
+ nice_debug ("Agent %p : pair %p (%s) is in-progress, "
+ "will be nominated on response receipt.",
+ agent, pair, pair->foundation);
+ }
+
+ if (pair->valid ||
+ !NICE_AGENT_IS_COMPATIBLE_WITH_RFC5245_OR_OC2007R2 (agent)) {
+ nice_debug ("Agent %p : marking pair %p (%s) as nominated",
+ agent, pair, pair->foundation);
+ pair->nominated = TRUE;
+ }
+
+ if (pair->valid) {
+ /* Do not step down to CONNECTED if we're already at state READY*/
+ if (component->state == NICE_COMPONENT_STATE_FAILED)
+ agent_signal_component_state_change (agent,
+ stream->id, component->id, NICE_COMPONENT_STATE_CONNECTING);
+ priv_update_selected_pair (agent, component, pair);
+ if (component->state == NICE_COMPONENT_STATE_CONNECTING)
+ /* step: notify the client of a new component state (must be done
+ * before the possible check list state update step */
+ agent_signal_component_state_change (agent,
+ stream->id, component->id, NICE_COMPONENT_STATE_CONNECTED);
+ }
+
+ if (pair->nominated)
+ priv_update_check_list_state_for_ready (agent, stream, component);
+ }
+ }
+}
+
+guint32
+ensure_unique_priority (NiceStream *stream, NiceComponent *component,
+ guint32 priority)
+{
+ GSList *item;
+
+ again:
+ if (priority == 0)
+ priority--;
+
+ for (item = component->local_candidates; item; item = item->next) {
+ NiceCandidate *cand = item->data;
+
+ if (cand->priority == priority) {
+ priority--;
+ goto again;
+ }
+ }
+
+ for (item = stream->conncheck_list; item; item = item->next) {
+ CandidateCheckPair *p = item->data;
+
+ if (p->component_id == component->id &&
+ p->prflx_priority == priority) {
+ priority--;
+ goto again;
+ }
+ }
+
+ return priority;
+}
+
+
+/*
+ * Creates a new connectivity check pair and adds it to
+ * the agent's list of checks.
+ */
+static CandidateCheckPair *priv_add_new_check_pair (NiceAgent *agent,
+ guint stream_id, NiceComponent *component, NiceCandidate *local,
+ NiceCandidate *remote, NiceCheckState initial_state)
+{
+ NiceStream *stream;
+ CandidateCheckPair *pair;
+
+ g_assert (local != NULL);
+ g_assert (remote != NULL);
+
+ stream = agent_find_stream (agent, stream_id);
+ pair = g_slice_new0 (CandidateCheckPair);
+
+ pair->stream_id = stream_id;
+ pair->component_id = component->id;;
+ pair->local = local;
+ pair->remote = remote;
+ /* note: we use the remote sockptr only in the case
+ * of TCP transport
+ */
+ if (local->transport == NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE &&
+ remote->type == NICE_CANDIDATE_TYPE_PEER_REFLEXIVE)
+ pair->sockptr = (NiceSocket *) remote->sockptr;
+ else
+ pair->sockptr = (NiceSocket *) local->sockptr;
+ g_snprintf (pair->foundation, NICE_CANDIDATE_PAIR_MAX_FOUNDATION, "%s:%s", local->foundation, remote->foundation);
+
+ pair->priority = agent_candidate_pair_priority (agent, local, remote);
+ nice_debug ("Agent %p : creating a new pair", agent);
+ SET_PAIR_STATE (agent, pair, initial_state);
+ {
+ gchar tmpbuf1[INET6_ADDRSTRLEN];
+ gchar tmpbuf2[INET6_ADDRSTRLEN];
+ nice_address_to_string (&pair->local->addr, tmpbuf1);
+ nice_address_to_string (&pair->remote->addr, tmpbuf2);
+ nice_debug ("Agent %p : new pair %p : [%s]:%u --> [%s]:%u", agent, pair,
+ tmpbuf1, nice_address_get_port (&pair->local->addr),
+ tmpbuf2, nice_address_get_port (&pair->remote->addr));
+ }
+ pair->prflx_priority = ensure_unique_priority (stream, component,
+ peer_reflexive_candidate_priority (agent, local));
+
+ stream->conncheck_list = g_slist_insert_sorted (stream->conncheck_list, pair,
+ (GCompareFunc)conn_check_compare);
+
+ nice_debug ("Agent %p : added a new pair %p with foundation '%s' to "
+ "stream %u component %u.", agent, pair, pair->foundation, stream_id,
+ component->id);
+
+ /* implement the hard upper limit for number of
+ checks (see sect 5.7.3 ICE ID-19): */
+ if (agent->compatibility == NICE_COMPATIBILITY_RFC5245) {
+ stream->conncheck_list = priv_limit_conn_check_list_size (agent,
+ stream->conncheck_list, agent->max_conn_checks);
+ }
+
+ return pair;
+}
+
+NiceCandidateTransport
+conn_check_match_transport (NiceCandidateTransport transport)
+{
+ switch (transport) {
+ case NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE:
+ return NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE;
+ break;
+ case NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE:
+ return NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE;
+ break;
+ case NICE_CANDIDATE_TRANSPORT_TCP_SO:
+ case NICE_CANDIDATE_TRANSPORT_UDP:
+ default:
+ return transport;
+ break;
+ }
+}
+
+static CandidateCheckPair *priv_conn_check_add_for_candidate_pair_matched (
+ NiceAgent *agent, guint stream_id, NiceComponent *component,
+ NiceCandidate *local, NiceCandidate *remote, NiceCheckState initial_state)
+{
+ CandidateCheckPair *pair;
+
+ pair = priv_add_new_check_pair (agent, stream_id, component, local, remote,
+ initial_state);
+ if (component->state == NICE_COMPONENT_STATE_CONNECTED ||
+ component->state == NICE_COMPONENT_STATE_READY) {
+ agent_signal_component_state_change (agent,
+ stream_id,
+ component->id,
+ NICE_COMPONENT_STATE_CONNECTED);
+ } else {
+ agent_signal_component_state_change (agent,
+ stream_id,
+ component->id,
+ NICE_COMPONENT_STATE_CONNECTING);
+ }
+
+ return pair;
+}
+
+gboolean conn_check_add_for_candidate_pair (NiceAgent *agent,
+ guint stream_id, NiceComponent *component, NiceCandidate *local,
+ NiceCandidate *remote)
+{
+ gboolean ret = FALSE;
+
+ g_assert (local != NULL);
+ g_assert (remote != NULL);
+
+ /* note: do not create pairs where the local candidate is
+ * a srv-reflexive (ICE 5.7.3. "Pruning the pairs" ID-9) */
+ if ((agent->compatibility == NICE_COMPATIBILITY_RFC5245 ||
+ agent->compatibility == NICE_COMPATIBILITY_WLM2009 ||
+ agent->compatibility == NICE_COMPATIBILITY_OC2007R2) &&
+ local->type == NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE) {
+ return FALSE;
+ }
+
+ /* note: do not create pairs where local candidate has TCP passive transport
+ * (ice-tcp-13 6.2. "Forming the Check Lists") */
+ if (local->transport == NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE) {
+ return FALSE;
+ }
+
+ /* note: match pairs only if transport and address family are the same */
+ if (local->transport == conn_check_match_transport (remote->transport) &&
+ local->addr.s.addr.sa_family == remote->addr.s.addr.sa_family) {
+ priv_conn_check_add_for_candidate_pair_matched (agent, stream_id, component,
+ local, remote, NICE_CHECK_FROZEN);
+ ret = TRUE;
+ }
+
+ return ret;
+}
+
+/*
+ * Forms new candidate pairs by matching the new remote candidate
+ * 'remote_cand' with all existing local candidates of 'component'.
+ * Implements the logic described in ICE sect 5.7.1. "Forming Candidate
+ * Pairs" (ID-19).
+ *
+ * @param agent context
+ * @param component pointer to the component
+ * @param remote remote candidate to match with
+ *
+ * @return number of checks added, negative on fatal errors
+ */
+int conn_check_add_for_candidate (NiceAgent *agent, guint stream_id, NiceComponent *component, NiceCandidate *remote)
+{
+ GSList *i;
+ int added = 0;
+ int ret = 0;
+
+ g_assert (remote != NULL);
+
+ /* note: according to 7.2.1.3, "Learning Peer Reflexive Candidates",
+ * the agent does not pair this candidate with any local candidates.
+ */
+ if (agent->compatibility == NICE_COMPATIBILITY_RFC5245 &&
+ remote->type == NICE_CANDIDATE_TYPE_PEER_REFLEXIVE)
+ {
+ return added;
+ }
+
+ for (i = component->local_candidates; i ; i = i->next) {
+ NiceCandidate *local = i->data;
+
+ if (agent->force_relay && local->type != NICE_CANDIDATE_TYPE_RELAYED)
+ continue;
+
+ ret = conn_check_add_for_candidate_pair (agent, stream_id, component, local, remote);
+
+ if (ret) {
+ ++added;
+ }
+ }
+
+ return added;
+}
+
+/*
+ * Forms new candidate pairs by matching the new local candidate
+ * 'local_cand' with all existing remote candidates of 'component'.
+ *
+ * @param agent context
+ * @param component pointer to the component
+ * @param local local candidate to match with
+ *
+ * @return number of checks added, negative on fatal errors
+ */
+int conn_check_add_for_local_candidate (NiceAgent *agent, guint stream_id, NiceComponent *component, NiceCandidate *local)
+{
+ GSList *i;
+ int added = 0;
+ int ret = 0;
+
+ g_assert (local != NULL);
+
+ /*
+ * note: according to 7.1.3.2.1 "Discovering Peer Reflexive
+ * Candidates", the peer reflexive candidate is not paired
+ * with other remote candidates
+ */
+
+ if (agent->compatibility == NICE_COMPATIBILITY_RFC5245 &&
+ local->type == NICE_CANDIDATE_TYPE_PEER_REFLEXIVE)
+ {
+ return added;
+ }
+
+ for (i = component->remote_candidates; i ; i = i->next) {
+
+ NiceCandidate *remote = i->data;
+ ret = conn_check_add_for_candidate_pair (agent, stream_id, component, local, remote);
+
+ if (ret) {
+ ++added;
+ }
+ }
+
+ return added;
+}
+
+/*
+ * Frees the CandidateCheckPair structure pointer to
+ * by 'user data'. Compatible with GDestroyNotify.
+ */
+static void candidate_check_pair_free (NiceAgent *agent,
+ CandidateCheckPair *pair)
+{
+ priv_remove_pair_from_triggered_check_queue (agent, pair);
+ priv_free_all_stun_transactions (pair, NULL);
+ g_slice_free (CandidateCheckPair, pair);
+}
+
+/*
+ * Frees all resources of all connectivity checks.
+ */
+void conn_check_free (NiceAgent *agent)
+{
+ GSList *i;
+ for (i = agent->streams; i; i = i->next) {
+ NiceStream *stream = i->data;
+
+ if (stream->conncheck_list) {
+ GSList *item;
+
+ nice_debug ("Agent %p, freeing conncheck_list of stream %p", agent,
+ stream);
+ for (item = stream->conncheck_list; item; item = item->next)
+ candidate_check_pair_free (agent, item->data);
+ g_slist_free (stream->conncheck_list);
+ stream->conncheck_list = NULL;
+ }
+ }
+
+ conn_check_stop (agent);
+}
+
+/*
+ * Prunes the list of connectivity checks for items related
+ * to stream 'stream_id'.
+ *
+ * @return TRUE on success, FALSE on a fatal error
+ */
+void conn_check_prune_stream (NiceAgent *agent, NiceStream *stream)
+{
+ GSList *i;
+ gboolean keep_going = FALSE;
+
+ if (stream->conncheck_list) {
+ GSList *item;
+
+ nice_debug ("Agent %p, freeing conncheck_list of stream %p", agent, stream);
+
+ for (item = stream->conncheck_list; item; item = item->next)
+ candidate_check_pair_free (agent, item->data);
+ g_slist_free (stream->conncheck_list);
+ stream->conncheck_list = NULL;
+ }
+
+ for (i = agent->streams; i; i = i->next) {
+ NiceStream *s = i->data;
+ if (s->conncheck_list) {
+ keep_going = TRUE;
+ break;
+ }
+ }
+
+ if (!keep_going)
+ conn_check_stop (agent);
+}
+
+/*
+ * Fills 'dest' with a username string for use in an outbound connectivity
+ * checks. No more than 'dest_len' characters (including terminating
+ * NULL) is ever written to the 'dest'.
+ */
+static
+size_t priv_gen_username (NiceAgent *agent, guint component_id,
+ gchar *remote, gchar *local, uint8_t *dest, guint dest_len)
+{
+ guint len = 0;
+ gsize remote_len = strlen (remote);
+ gsize local_len = strlen (local);
+
+ if (remote_len > 0 && local_len > 0) {
+ if (agent->compatibility == NICE_COMPATIBILITY_RFC5245 &&
+ dest_len >= remote_len + local_len + 1) {
+ memcpy (dest, remote, remote_len);
+ len += remote_len;
+ memcpy (dest + len, ":", 1);
+ len++;
+ memcpy (dest + len, local, local_len);
+ len += local_len;
+ } else if ((agent->compatibility == NICE_COMPATIBILITY_WLM2009 ||
+ agent->compatibility == NICE_COMPATIBILITY_OC2007R2) &&
+ dest_len >= remote_len + local_len + 4 ) {
+ memcpy (dest, remote, remote_len);
+ len += remote_len;
+ memcpy (dest + len, ":", 1);
+ len++;
+ memcpy (dest + len, local, local_len);
+ len += local_len;
+ if (len % 4 != 0) {
+ memset (dest + len, 0, 4 - (len % 4));
+ len += 4 - (len % 4);
+ }
+ } else if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE &&
+ dest_len >= remote_len + local_len) {
+ memcpy (dest, remote, remote_len);
+ len += remote_len;
+ memcpy (dest + len, local, local_len);
+ len += local_len;
+ } else if (agent->compatibility == NICE_COMPATIBILITY_MSN ||
+ agent->compatibility == NICE_COMPATIBILITY_OC2007) {
+ gchar component_str[10];
+ guchar *local_decoded = NULL;
+ guchar *remote_decoded = NULL;
+ gsize local_decoded_len;
+ gsize remote_decoded_len;
+ gsize total_len;
+ int padding;
+
+ g_snprintf (component_str, sizeof(component_str), "%d", component_id);
+ local_decoded = g_base64_decode (local, &local_decoded_len);
+ remote_decoded = g_base64_decode (remote, &remote_decoded_len);
+
+ total_len = remote_decoded_len + local_decoded_len + 3 + 2*strlen (component_str);
+ padding = 4 - (total_len % 4);
+
+ if (dest_len >= total_len + padding) {
+ guchar pad_char[1] = {0};
+ int i;
+
+ memcpy (dest, remote_decoded, remote_decoded_len);
+ len += remote_decoded_len;
+ memcpy (dest + len, ":", 1);
+ len++;
+ memcpy (dest + len, component_str, strlen (component_str));
+ len += strlen (component_str);
+
+ memcpy (dest + len, ":", 1);
+ len++;
+
+ memcpy (dest + len, local_decoded, local_decoded_len);
+ len += local_decoded_len;
+ memcpy (dest + len, ":", 1);
+ len++;
+ memcpy (dest + len, component_str, strlen (component_str));;
+ len += strlen (component_str);
+
+ for (i = 0; i < padding; i++) {
+ memcpy (dest + len, pad_char, 1);
+ len++;
+ }
+
+ }
+
+ g_free (local_decoded);
+ g_free (remote_decoded);
+ }
+ }
+
+ return len;
+}
+
+/*
+ * Fills 'dest' with a username string for use in an outbound connectivity
+ * checks. No more than 'dest_len' characters (including terminating
+ * NULL) is ever written to the 'dest'.
+ */
+static
+size_t priv_create_username (NiceAgent *agent, NiceStream *stream,
+ guint component_id, NiceCandidate *remote, NiceCandidate *local,
+ uint8_t *dest, guint dest_len, gboolean inbound)
+{
+ gchar *local_username = NULL;
+ gchar *remote_username = NULL;
+
+
+ if (remote && remote->username) {
+ remote_username = remote->username;
+ }
+
+ if (local && local->username) {
+ local_username = local->username;
+ }
+
+ if (stream) {
+ if (remote_username == NULL) {
+ remote_username = stream->remote_ufrag;
+ }
+ if (local_username == NULL) {
+ local_username = stream->local_ufrag;
+ }
+ }
+
+ if (local_username && remote_username) {
+ if (inbound) {
+ return priv_gen_username (agent, component_id,
+ local_username, remote_username, dest, dest_len);
+ } else {
+ return priv_gen_username (agent, component_id,
+ remote_username, local_username, dest, dest_len);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Returns a password string for use in an outbound connectivity
+ * check.
+ */
+static
+size_t priv_get_password (NiceAgent *agent, NiceStream *stream,
+ NiceCandidate *remote, uint8_t **password)
+{
+ if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE)
+ return 0;
+
+ if (remote && remote->password) {
+ *password = (uint8_t *)remote->password;
+ return strlen (remote->password);
+ }
+
+ if (stream) {
+ *password = (uint8_t *)stream->remote_password;
+ return strlen (stream->remote_password);
+ }
+
+ return 0;
+}
+
+/* Implement the computation specific in RFC 5245 section 16 */
+
+static unsigned int priv_compute_conncheck_timer (NiceAgent *agent, NiceStream *stream)
+{
+ GSList *i;
+ guint waiting_and_in_progress = 0;
+ guint n = 0;
+ unsigned int rto = 0;
+
+ for (i = stream->conncheck_list; i ; i = i->next) {
+ CandidateCheckPair *p = i->data;
+ if (p->state == NICE_CHECK_IN_PROGRESS ||
+ p->state == NICE_CHECK_WAITING)
+ waiting_and_in_progress++;
+ }
+
+ n = priv_number_of_active_check_lists (agent);
+ rto = agent->timer_ta * n * waiting_and_in_progress;
+
+ /* We assume non-reliable streams are RTP, so we use 100 as the max */
+ nice_debug ("Agent %p : timer set to %dms, "
+ "waiting+in_progress=%d, nb_active=%d",
+ agent, agent->reliable ? MAX (rto, 500) : MAX (rto, 100),
+ waiting_and_in_progress, n);
+ if (agent->reliable)
+ return MAX (rto, 500);
+ else
+ return MAX (rto, 100);
+}
+
+/*
+ * Sends a connectivity check over candidate pair 'pair'.
+ *
+ * @return zero on success, non-zero on error
+ */
+int conn_check_send (NiceAgent *agent, CandidateCheckPair *pair)
+{
+
+ /* note: following information is supplied:
+ * - username (for USERNAME attribute)
+ * - password (for MESSAGE-INTEGRITY)
+ * - priority (for PRIORITY)
+ * - ICE-CONTROLLED/ICE-CONTROLLING (for role conflicts)
+ * - USE-CANDIDATE (if sent by the controlling agent)
+ */
+
+ uint8_t uname[NICE_STREAM_MAX_UNAME];
+ NiceStream *stream;
+ NiceComponent *component;
+ gsize uname_len;
+ uint8_t *password = NULL;
+ gsize password_len;
+ bool controlling = agent->controlling_mode;
+ /* XXX: add API to support different nomination modes: */
+ bool cand_use = controlling;
+ size_t buffer_len;
+ unsigned int timeout;
+ StunTransaction *stun;
+
+ if (!agent_find_component (agent, pair->stream_id, pair->component_id,
+ &stream, &component))
+ return -1;
+
+ uname_len = priv_create_username (agent, stream, pair->component_id,
+ pair->remote, pair->local, uname, sizeof (uname), FALSE);
+ password_len = priv_get_password (agent, stream, pair->remote, &password);
+
+ if (password != NULL &&
+ (agent->compatibility == NICE_COMPATIBILITY_MSN ||
+ agent->compatibility == NICE_COMPATIBILITY_OC2007)) {
+ password = g_base64_decode ((gchar *) password, &password_len);
+ }
+
+ if (nice_debug_is_enabled ()) {
+ gchar tmpbuf1[INET6_ADDRSTRLEN];
+ gchar tmpbuf2[INET6_ADDRSTRLEN];
+ nice_address_to_string (&pair->local->addr, tmpbuf1);
+ nice_address_to_string (&pair->remote->addr, tmpbuf2);
+ nice_debug ("Agent %p : STUN-CC REQ [%s]:%u --> [%s]:%u, socket=%u, "
+ "pair=%p (c-id:%u), tie=%llu, username='%.*s' (%" G_GSIZE_FORMAT "), "
+ "password='%.*s' (%" G_GSIZE_FORMAT "), prio=%u, %s.", agent,
+ tmpbuf1, nice_address_get_port (&pair->local->addr),
+ tmpbuf2, nice_address_get_port (&pair->remote->addr),
+ pair->sockptr->fileno ? g_socket_get_fd(pair->sockptr->fileno) : -1,
+ pair, pair->component_id,
+ (unsigned long long)agent->tie_breaker,
+ (int) uname_len, uname, uname_len,
+ (int) password_len, password, password_len,
+ pair->prflx_priority,
+ controlling ? "controlling" : "controlled");
+ }
+
+ if (NICE_AGENT_IS_COMPATIBLE_WITH_RFC5245_OR_OC2007R2 (agent)) {
+ switch (agent->nomination_mode) {
+ case NICE_NOMINATION_MODE_REGULAR:
+ /* We are doing regular nomination, so we set the use-candidate
+ * attrib, when the controlling agent decided which valid pair to
+ * resend with this flag in priv_conn_check_tick_stream()
+ */
+ cand_use = pair->use_candidate_on_next_check;
+ nice_debug ("Agent %p : %s: set cand_use=%d "
+ "(regular nomination).", agent, G_STRFUNC, cand_use);
+ break;
+ case NICE_NOMINATION_MODE_AGGRESSIVE:
+ /* We are doing aggressive nomination, we set the use-candidate
+ * attrib in every check we send, when we are the controlling
+ * agent, RFC 5245, 8.1.1.2
+ */
+ cand_use = controlling;
+ nice_debug ("Agent %p : %s: set cand_use=%d "
+ "(aggressive nomination).", agent, G_STRFUNC, cand_use);
+ break;
+ default:
+ /* Nothing to do. */
+ break;
+ }
+ } else if (cand_use)
+ pair->nominated = controlling;
+
+ if (uname_len == 0) {
+ nice_debug ("Agent %p: no credentials found, cancelling conncheck", agent);
+ return -1;
+ }
+
+ stun = priv_add_stun_transaction (pair);
+
+ buffer_len = stun_usage_ice_conncheck_create (&component->stun_agent,
+ &stun->message, stun->buffer, sizeof(stun->buffer),
+ uname, uname_len, password, password_len,
+ cand_use, controlling, pair->prflx_priority,
+ agent->tie_breaker,
+ pair->local->foundation,
+ agent_to_ice_compatibility (agent));
+
+ nice_debug ("Agent %p: conncheck created %zd - %p", agent, buffer_len,
+ stun->message.buffer);
+
+ if (agent->compatibility == NICE_COMPATIBILITY_MSN ||
+ agent->compatibility == NICE_COMPATIBILITY_OC2007) {
+ g_free (password);
+ }
+
+ if (buffer_len == 0) {
+ nice_debug ("Agent %p: buffer is empty, cancelling conncheck", agent);
+ priv_remove_stun_transaction (pair, stun, component);
+ return -1;
+ }
+
+ if (nice_socket_is_reliable(pair->sockptr)) {
+ timeout = agent->stun_reliable_timeout;
+ stun_timer_start_reliable(&stun->timer, timeout);
+ } else {
+ timeout = priv_compute_conncheck_timer (agent, stream);
+ stun_timer_start (&stun->timer, timeout, agent->stun_max_retransmissions);
+ }
+
+ g_get_current_time (&stun->next_tick);
+ g_time_val_add (&stun->next_tick, timeout * 1000);
+
+ /* TCP-ACTIVE candidate must create a new socket before sending
+ * by connecting to the peer. The new socket is stored in the candidate
+ * check pair, until we discover a new local peer reflexive */
+ if (pair->sockptr->fileno == NULL &&
+ pair->sockptr->type != NICE_SOCKET_TYPE_UDP_TURN &&
+ pair->local->transport == NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE) {
+ NiceStream *stream2 = NULL;
+ NiceComponent *component2 = NULL;
+ NiceSocket *new_socket;
+
+ if (agent_find_component (agent, pair->stream_id, pair->component_id,
+ &stream2, &component2)) {
+ new_socket = nice_tcp_active_socket_connect (pair->sockptr,
+ &pair->remote->addr);
+ if (new_socket) {
+ pair->sockptr = new_socket;
+ _priv_set_socket_tos (agent, pair->sockptr, stream2->tos);
+
+ nice_socket_set_writable_callback (pair->sockptr, _tcp_sock_is_writable,
+ component2);
+
+ nice_component_attach_socket (component2, new_socket);
+ }
+ }
+ }
+ /* send the conncheck */
+ agent_socket_send (pair->sockptr, &pair->remote->addr,
+ buffer_len, (gchar *)stun->buffer);
+
+ if (agent->compatibility == NICE_COMPATIBILITY_OC2007R2)
+ ms_ice2_legacy_conncheck_send (&stun->message, pair->sockptr,
+ &pair->remote->addr);
+
+ return 0;
+}
+
+/*
+ * Implemented the pruning steps described in ICE sect 8.1.2
+ * "Updating States" (ID-19) after a pair has been nominated.
+ *
+ * @see priv_update_check_list_state_failed_components()
+ */
+static guint priv_prune_pending_checks (NiceAgent *agent, NiceStream *stream, guint component_id)
+{
+ GSList *i;
+ guint64 highest_nominated_priority = 0;
+ guint in_progress = 0;
+
+ nice_debug ("Agent %p: Finding highest priority for component %d",
+ agent, component_id);
+
+ for (i = stream->conncheck_list; i; i = i->next) {
+ CandidateCheckPair *p = i->data;
+ if (p->component_id == component_id && p->valid == TRUE &&
+ p->nominated == TRUE) {
+ if (p->priority > highest_nominated_priority) {
+ highest_nominated_priority = p->priority;
+ }
+ }
+ }
+
+ nice_debug ("Agent %p: Pruning pending checks. Highest nominated priority "
+ "is %" G_GUINT64_FORMAT, agent, highest_nominated_priority);
+
+ /* step: cancel all FROZEN and WAITING pairs for the component */
+ i = stream->conncheck_list;
+ while (i) {
+ CandidateCheckPair *p = i->data;
+ GSList *next = i->next;
+
+ if (p->component_id == component_id) {
+ if (p->state == NICE_CHECK_FROZEN || p->state == NICE_CHECK_WAITING) {
+ nice_debug ("Agent %p : pair %p removed.", agent, p);
+ candidate_check_pair_free (agent, p);
+ stream->conncheck_list = g_slist_delete_link(stream->conncheck_list, i);
+ }
+
+ /* note: a SHOULD level req. in ICE 8.1.2. "Updating States" (ID-19) */
+ else if (p->state == NICE_CHECK_IN_PROGRESS) {
+ if (p->priority < highest_nominated_priority) {
+ p->retransmit = FALSE;
+ nice_debug ("Agent %p : pair %p will not be retransmitted.",
+ agent, p);
+ } else {
+ /* We must keep the higher priority pairs running because if a udp
+ * packet was lost, we might end up using a bad candidate */
+ nice_debug ("Agent %p : pair %p kept IN_PROGRESS because priority %"
+ G_GUINT64_FORMAT " is higher than currently nominated pair %"
+ G_GUINT64_FORMAT, agent,
+ p, p->priority, highest_nominated_priority);
+ in_progress++;
+ }
+ }
+ }
+ i = next;
+ }
+
+ return in_progress;
+}
+
+/*
+ * Schedules a triggered check after a successfully inbound
+ * connectivity check. Implements ICE sect 7.2.1.4 "Triggered Checks" (ID-19).
+ *
+ * @param agent self pointer
+ * @param component the check is related to
+ * @param local_socket socket from which the inbound check was received
+ * @param remote_cand remote candidate from which the inbound check was sent
+ */
+static gboolean priv_schedule_triggered_check (NiceAgent *agent, NiceStream *stream, NiceComponent *component, NiceSocket *local_socket, NiceCandidate *remote_cand)
+{
+ GSList *i;
+ NiceCandidate *local = NULL;
+ CandidateCheckPair *p;
+
+ g_assert (remote_cand != NULL);
+
+ for (i = stream->conncheck_list; i ; i = i->next) {
+ p = i->data;
+ if (p->component_id == component->id &&
+ p->remote == remote_cand &&
+ ((p->local->transport == NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE &&
+ p->sockptr == local_socket) ||
+ (p->local->transport != NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE &&
+ p->local->sockptr == local_socket))) {
+ /* We don't check for p->sockptr because in the case of
+ * tcp-active we don't want to retrigger a check on a pair that
+ * was FAILED when a peer-reflexive pair was created */
+
+ if (p->succeeded_pair != NULL) {
+ g_assert (p->state == NICE_CHECK_DISCOVERED);
+ p = p->succeeded_pair;
+ }
+
+ nice_debug ("Agent %p : Found a matching pair %p (%s) (%s) ...",
+ agent, p, p->foundation, priv_state_to_string (p->state));
+
+ switch (p->state) {
+ case NICE_CHECK_WAITING:
+ case NICE_CHECK_FROZEN:
+ nice_debug ("Agent %p : pair %p added for a triggered check.",
+ agent, p);
+ priv_add_pair_to_triggered_check_queue (agent, p);
+ break;
+ case NICE_CHECK_IN_PROGRESS:
+ /* note: according to ICE SPEC sect 7.2.1.4 "Triggered Checks"
+ * we cancel the in-progress transaction, and after the
+ * retransmission timeout, we create a new connectivity check
+ * for that pair. The controlling role of this new check may
+ * be different from the role of this cancelled check.
+ *
+ * note: the flag retransmit unset means that
+ * another pair, with a higher priority is already nominated,
+ * so there's no reason to recheck this pair, since it can in
+ * no way replace the nominated one.
+ */
+ if (!nice_socket_is_reliable (p->sockptr) && p->retransmit) {
+ nice_debug ("Agent %p : pair %p added for a triggered check.",
+ agent, p);
+ priv_add_pair_to_triggered_check_queue (agent, p);
+ }
+ break;
+ case NICE_CHECK_FAILED:
+ if (p->retransmit) {
+ nice_debug ("Agent %p : pair %p added for a triggered check.",
+ agent, p);
+ priv_add_pair_to_triggered_check_queue (agent, p);
+ /* If the component for this pair is in failed state, move it
+ * back to connecting, and reinitiate the timers
+ */
+ if (component->state == NICE_COMPONENT_STATE_FAILED) {
+ agent_signal_component_state_change (agent, stream->id,
+ component->id, NICE_COMPONENT_STATE_CONNECTING);
+ conn_check_schedule_next (agent);
+ }
+ }
+ break;
+ case NICE_CHECK_SUCCEEDED:
+ nice_debug ("Agent %p : nothing to do for pair %p.", agent, p);
+ /* note: this is a bit unsure corner-case -- let's do the
+ same state update as for processing responses to our own checks */
+ /* note: this update is required by the trickle test, to
+ * ensure the transition ready -> connected -> ready, because
+ * an incoming stun request generates a discovered peer reflexive,
+ * that causes the ready -> connected transition.
+ */
+ priv_update_check_list_state_for_ready (agent, stream, component);
+ break;
+ default:
+ break;
+ }
+
+ /* note: the spec says the we SHOULD retransmit in-progress
+ * checks immediately, but we won't do that now */
+
+ return TRUE;
+ }
+ }
+
+ for (i = component->local_candidates; i ; i = i->next) {
+ local = i->data;
+ if (local->sockptr == local_socket)
+ break;
+ }
+
+ if (i) {
+ nice_debug ("Agent %p : Adding a triggered check to conn.check list (local=%p).", agent, local);
+ p = priv_conn_check_add_for_candidate_pair_matched (agent, stream->id,
+ component, local, remote_cand, NICE_CHECK_WAITING);
+ priv_add_pair_to_triggered_check_queue (agent, p);
+ return TRUE;
+ }
+ else {
+ nice_debug ("Agent %p : Didn't find a matching pair for triggered check (remote-cand=%p).", agent, remote_cand);
+ return FALSE;
+ }
+}
+
+
+/*
+ * Sends a reply to an successfully received STUN connectivity
+ * check request. Implements parts of the ICE spec section 7.2 (STUN
+ * Server Procedures).
+ *
+ * @param agent context pointer
+ * @param stream which stream (of the agent)
+ * @param component which component (of the stream)
+ * @param rcand remote candidate from which the request came, if NULL,
+ * the response is sent immediately but no other processing is done
+ * @param toaddr address to which reply is sent
+ * @param socket the socket over which the request came
+ * @param rbuf_len length of STUN message to send
+ * @param msg the STUN message to send
+ * @param use_candidate whether the request had USE_CANDIDATE attribute
+ *
+ * @pre (rcand == NULL || nice_address_equal(rcand->addr, toaddr) == TRUE)
+ */
+static void priv_reply_to_conn_check (NiceAgent *agent, NiceStream *stream,
+ NiceComponent *component, NiceCandidate *lcand, NiceCandidate *rcand,
+ const NiceAddress *toaddr, NiceSocket *sockptr, size_t rbuf_len,
+ StunMessage *msg, gboolean use_candidate)
+{
+ g_assert (rcand == NULL || nice_address_equal(&rcand->addr, toaddr) == TRUE);
+
+ if (nice_debug_is_enabled ()) {
+ gchar tmpbuf[INET6_ADDRSTRLEN];
+ nice_address_to_string (toaddr, tmpbuf);
+ nice_debug ("Agent %p : STUN-CC RESP to '%s:%u', socket=%u, len=%u, cand=%p (c-id:%u), use-cand=%d.", agent,
+ tmpbuf,
+ nice_address_get_port (toaddr),
+ sockptr->fileno ? g_socket_get_fd(sockptr->fileno) : -1,
+ (unsigned)rbuf_len,
+ rcand, component->id,
+ (int)use_candidate);
+ }
+
+ agent_socket_send (sockptr, toaddr, rbuf_len, (const gchar*)msg->buffer);
+ if (agent->compatibility == NICE_COMPATIBILITY_OC2007R2) {
+ ms_ice2_legacy_conncheck_send(msg, sockptr, toaddr);
+ }
+
+ /* We react to this stun request when we have the remote credentials.
+ * When credentials are not yet known, this request is stored
+ * in incoming_checks for later processing when returning from this
+ * function.
+ */
+ if (rcand && stream->remote_ufrag[0]) {
+ priv_schedule_triggered_check (agent, stream, component, sockptr, rcand);
+ if (use_candidate)
+ priv_mark_pair_nominated (agent, stream, component, lcand, rcand);
+ }
+}
+
+/*
+ * Stores information of an incoming STUN connectivity check
+ * for later use. This is only needed when a check is received
+ * before we get information about the remote candidates (via
+ * SDP or other signaling means).
+ *
+ * @return non-zero on error, zero on success
+ */
+static int priv_store_pending_check (NiceAgent *agent, NiceComponent *component,
+ const NiceAddress *from, NiceSocket *sockptr, uint8_t *username,
+ uint16_t username_len, uint32_t priority, gboolean use_candidate)
+{
+ IncomingCheck *icheck;
+ nice_debug ("Agent %p : Storing pending check.", agent);
+
+ if (g_queue_get_length (&component->incoming_checks) >=
+ NICE_AGENT_MAX_REMOTE_CANDIDATES) {
+ nice_debug ("Agent %p : WARN: unable to store information for early incoming check.", agent);
+ return -1;
+ }
+
+ icheck = g_slice_new0 (IncomingCheck);
+ g_queue_push_tail (&component->incoming_checks, icheck);
+ icheck->from = *from;
+ icheck->local_socket = sockptr;
+ icheck->priority = priority;
+ icheck->use_candidate = use_candidate;
+ icheck->username_len = username_len;
+ icheck->username = NULL;
+ if (username_len > 0)
+ icheck->username = g_memdup (username, username_len);
+
+ return 0;
+}
+
+/*
+ * Adds a new pair, discovered from an incoming STUN response, to
+ * the connectivity check list.
+ *
+ * @return created pair, or NULL on fatal (memory allocation) errors
+ */
+static CandidateCheckPair *priv_add_peer_reflexive_pair (NiceAgent *agent, guint stream_id, NiceComponent *component, NiceCandidate *local_cand, CandidateCheckPair *parent_pair)
+{
+ CandidateCheckPair *pair = g_slice_new0 (CandidateCheckPair);
+ NiceStream *stream = agent_find_stream (agent, stream_id);
+
+ pair->stream_id = stream_id;
+ pair->component_id = component->id;;
+ pair->local = local_cand;
+ pair->remote = parent_pair->remote;
+ pair->sockptr = local_cand->sockptr;
+ parent_pair->discovered_pair = pair;
+ pair->succeeded_pair = parent_pair;
+ nice_debug ("Agent %p : creating a new pair", agent);
+ SET_PAIR_STATE (agent, pair, NICE_CHECK_DISCOVERED);
+ {
+ gchar tmpbuf1[INET6_ADDRSTRLEN];
+ gchar tmpbuf2[INET6_ADDRSTRLEN];
+ nice_address_to_string (&pair->local->addr, tmpbuf1);
+ nice_address_to_string (&pair->remote->addr, tmpbuf2);
+ nice_debug ("Agent %p : new pair %p : [%s]:%u --> [%s]:%u", agent, pair,
+ tmpbuf1, nice_address_get_port (&pair->local->addr),
+ tmpbuf2, nice_address_get_port (&pair->remote->addr));
+ }
+ g_snprintf (pair->foundation, NICE_CANDIDATE_PAIR_MAX_FOUNDATION, "%s:%s",
+ local_cand->foundation, parent_pair->remote->foundation);
+ if (agent->controlling_mode == TRUE)
+ pair->priority = nice_candidate_pair_priority (pair->local->priority,
+ pair->remote->priority);
+ else
+ pair->priority = nice_candidate_pair_priority (pair->remote->priority,
+ pair->local->priority);
+ pair->nominated = parent_pair->nominated;
+ pair->prflx_priority = ensure_unique_priority (stream, component,
+ peer_reflexive_candidate_priority (agent, local_cand));
+ nice_debug ("Agent %p : added a new peer-discovered pair with "
+ "foundation '%s'.", agent, pair->foundation);
+
+ stream->conncheck_list = g_slist_insert_sorted (stream->conncheck_list, pair,
+ (GCompareFunc)conn_check_compare);
+
+ return pair;
+}
+
+/*
+ * Recalculates priorities of all candidate pairs. This
+ * is required after a conflict in ICE roles.
+ */
+void recalculate_pair_priorities (NiceAgent *agent)
+{
+ GSList *i, *j;
+
+ for (i = agent->streams; i; i = i->next) {
+ NiceStream *stream = i->data;
+ for (j = stream->conncheck_list; j; j = j->next) {
+ CandidateCheckPair *p = j->data;
+ p->priority = agent_candidate_pair_priority (agent, p->local, p->remote);
+ }
+ stream->conncheck_list = g_slist_sort (stream->conncheck_list,
+ (GCompareFunc)conn_check_compare);
+ }
+}
+
+/*
+ * Change the agent role if different from 'control'. Can be
+ * initiated both by handling of incoming connectivity checks,
+ * and by processing the responses to checks sent by us.
+ */
+static void priv_check_for_role_conflict (NiceAgent *agent, gboolean control)
+{
+ /* role conflict, change mode; wait for a new conn. check */
+ if (control != agent->controlling_mode) {
+ nice_debug ("Agent %p : Role conflict, changing agent role to \"%s\".",
+ agent, control ? "controlling" : "controlled");
+ agent->controlling_mode = control;
+ /* the pair priorities depend on the roles, so recalculation
+ * is needed */
+ recalculate_pair_priorities (agent);
+ }
+ else
+ nice_debug ("Agent %p : Role conflict, staying with role \"%s\".",
+ agent, control ? "controlling" : "controlled");
+}
+
+/*
+ * Checks whether the mapped address in connectivity check response
+ * matches any of the known local candidates. If not, apply the
+ * mechanism for "Discovering Peer Reflexive Candidates" ICE ID-19)
+ *
+ * @param agent context pointer
+ * @param stream which stream (of the agent)
+ * @param component which component (of the stream)
+ * @param p the connectivity check pair for which we got a response
+ * @param socketptr socket used to send the reply
+ * @param mapped_sockaddr mapped address in the response
+ *
+ * @return pointer to a candidate pair, found in conncheck list or newly created
+ */
+static CandidateCheckPair *priv_process_response_check_for_reflexive(NiceAgent *agent, NiceStream *stream, NiceComponent *component, CandidateCheckPair *p, NiceSocket *sockptr, struct sockaddr *mapped_sockaddr, NiceCandidate *local_candidate, NiceCandidate *remote_candidate)
+{
+ CandidateCheckPair *new_pair = NULL;
+ NiceAddress mapped;
+ GSList *i, *j;
+ NiceCandidate *local_cand = NULL;
+
+ nice_address_set_from_sockaddr (&mapped, mapped_sockaddr);
+
+ for (j = component->local_candidates; j; j = j->next) {
+ NiceCandidate *cand = j->data;
+ if (nice_address_equal (&mapped, &cand->addr)) {
+ local_cand = cand;
+
+ /* We always need to select the peer-reflexive Candidate Pair in the case
+ * of a TCP-ACTIVE local candidate, so we find it even if an incoming
+ * check matched an existing pair because it could be the original
+ * ACTIVE-PASSIVE candidate pair which was retriggered */
+ for (i = stream->conncheck_list; i; i = i->next) {
+ CandidateCheckPair *pair = i->data;
+ if (pair->local == cand && remote_candidate == pair->remote) {
+ new_pair = pair;
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ if (new_pair) {
+ /* note: when new_pair is distinct from p, it means new_pair is a
+ * previously discovered peer-reflexive candidate pair, so we don't
+ * set the valid flag on p in this case, because the valid flag is
+ * already set on the discovered pair.
+ */
+ if (new_pair == p)
+ p->valid = TRUE;
+ SET_PAIR_STATE (agent, p, NICE_CHECK_SUCCEEDED);
+ priv_remove_pair_from_triggered_check_queue (agent, p);
+ priv_free_all_stun_transactions (p, component);
+ nice_component_add_valid_candidate (agent, component, remote_candidate);
+ }
+ else {
+ if (!local_cand) {
+ if (!agent->force_relay) {
+ /* step: find a new local candidate, see RFC 5245 7.1.3.2.1.
+ * "Discovering Peer Reflexive Candidates"
+ */
+ local_cand = discovery_add_peer_reflexive_candidate (agent,
+ stream->id,
+ component->id,
+ &mapped,
+ sockptr,
+ local_candidate,
+ remote_candidate);
+ nice_debug ("Agent %p : added a new peer-reflexive local candidate %p",
+ agent, local_cand);
+ }
+ }
+
+ /* step: add a new discovered pair (see RFC 5245 7.1.3.2.2
+ "Constructing a Valid Pair") */
+ if (local_cand)
+ new_pair = priv_add_peer_reflexive_pair (agent, stream->id, component,
+ local_cand, p);
+ /* note: this is same as "adding to VALID LIST" in the spec
+ text */
+ if (new_pair)
+ new_pair->valid = TRUE;
+ /* step: The agent sets the state of the pair that *generated* the check to
+ * Succeeded, RFC 5245, 7.1.3.2.3, "Updating Pair States"
+ */
+ SET_PAIR_STATE (agent, p, NICE_CHECK_SUCCEEDED);
+ priv_remove_pair_from_triggered_check_queue (agent, p);
+ priv_free_all_stun_transactions (p, component);
+ }
+
+ if (new_pair && new_pair->valid)
+ nice_component_add_valid_candidate (agent, component, remote_candidate);
+
+
+ return new_pair;
+}
+
+/*
+ * Tries to match STUN reply in 'buf' to an existing STUN connectivity
+ * check transaction. If found, the reply is processed. Implements
+ * section 7.1.2 "Processing the Response" of ICE spec (ID-19).
+ *
+ * @return TRUE if a matching transaction is found
+ */
+static gboolean priv_map_reply_to_conn_check_request (NiceAgent *agent, NiceStream *stream, NiceComponent *component, NiceSocket *sockptr, const NiceAddress *from, NiceCandidate *local_candidate, NiceCandidate *remote_candidate, StunMessage *resp)
+{
+ union {
+ struct sockaddr_storage storage;
+ struct sockaddr addr;
+ } sockaddr;
+ socklen_t socklen = sizeof (sockaddr);
+ GSList *i, *j;
+ guint k;
+ StunUsageIceReturn res;
+ StunTransactionId discovery_id;
+ StunTransactionId response_id;
+ stun_message_id (resp, response_id);
+
+ for (i = stream->conncheck_list; i; i = i->next) {
+ CandidateCheckPair *p = i->data;
+
+ for (j = p->stun_transactions, k = 0; j; j = j->next, k++) {
+ StunTransaction *stun = j->data;
+
+ stun_message_id (&stun->message, discovery_id);
+
+ if (memcmp (discovery_id, response_id, sizeof(StunTransactionId)))
+ continue;
+
+ res = stun_usage_ice_conncheck_process (resp,
+ &sockaddr.storage, &socklen,
+ agent_to_ice_compatibility (agent));
+ nice_debug ("Agent %p : stun_bind_process/conncheck for %p: "
+ "%s,res=%s,stun#=%d.",
+ agent, p,
+ agent->controlling_mode ? "controlling" : "controlled",
+ priv_ice_return_to_string (res), k);
+
+ if (res == STUN_USAGE_ICE_RETURN_SUCCESS ||
+ res == STUN_USAGE_ICE_RETURN_NO_MAPPED_ADDRESS) {
+ /* case: found a matching connectivity check request */
+
+ CandidateCheckPair *ok_pair = NULL;
+
+ nice_debug ("Agent %p : pair %p MATCHED.", agent, p);
+ priv_remove_stun_transaction (p, stun, component);
+
+ /* step: verify that response came from the same IP address we
+ * sent the original request to (see 7.1.2.1. "Failure
+ * Cases") */
+ if (nice_address_equal (from, &p->remote->addr) == FALSE) {
+ candidate_check_pair_fail (stream, agent, p);
+ if (nice_debug_is_enabled ()) {
+ gchar tmpbuf[INET6_ADDRSTRLEN];
+ gchar tmpbuf2[INET6_ADDRSTRLEN];
+ nice_debug ("Agent %p : pair %p FAILED"
+ " (mismatch of source address).", agent, p);
+ nice_address_to_string (&p->remote->addr, tmpbuf);
+ nice_address_to_string (from, tmpbuf2);
+ nice_debug ("Agent %p : '%s:%u' != '%s:%u'", agent,
+ tmpbuf, nice_address_get_port (&p->remote->addr),
+ tmpbuf2, nice_address_get_port (from));
+ }
+ return TRUE;
+ }
+
+ /* note: CONNECTED but not yet READY, see docs */
+
+ /* step: handle the possible case of a peer-reflexive
+ * candidate where the mapped-address in response does
+ * not match any local candidate, see 7.1.2.2.1
+ * "Discovering Peer Reflexive Candidates" ICE ID-19) */
+
+ if (res == STUN_USAGE_ICE_RETURN_NO_MAPPED_ADDRESS) {
+ nice_debug ("Agent %p : Mapped address not found", agent);
+ SET_PAIR_STATE (agent, p, NICE_CHECK_SUCCEEDED);
+ p->valid = TRUE;
+ nice_component_add_valid_candidate (agent, component, p->remote);
+ } else
+ ok_pair = priv_process_response_check_for_reflexive (agent,
+ stream, component, p, sockptr, &sockaddr.addr,
+ local_candidate, remote_candidate);
+
+ /* note: The success of this check might also
+ * cause the state of other checks to change as well, ICE
+ * spec 7.1.3.2.3
+ */
+ priv_conn_check_unfreeze_related (agent, stream, p);
+
+ /* Note: this assignment helps to reduce the numbers of cases
+ * to be tested. If ok_pair and p refer to distinct pairs, it
+ * means that ok_pair is a discovered peer reflexive one,
+ * caused by the check made on pair p. In that case, the
+ * flags to be tested are on p, but the nominated flag will be
+ * set on ok_pair. When there's no discovered pair, p and
+ * ok_pair refer to the same pair.
+ * To summarize : p is a SUCCEEDED pair, ok_pair is a
+ * DISCOVERED, VALID, and eventually NOMINATED pair.
+ */
+ if (!ok_pair)
+ ok_pair = p;
+
+ /* step: updating nominated flag (ICE 7.1.2.2.4 "Updating the
+ Nominated Flag" (ID-19) */
+ if (NICE_AGENT_IS_COMPATIBLE_WITH_RFC5245_OR_OC2007R2 (agent)) {
+ nice_debug ("Agent %p : Updating nominated flag (%s): "
+ "ok_pair=%p (%d/%d) p=%p (%d/%d) (ucnc/mnora)",
+ agent, p->local->transport == NICE_CANDIDATE_TRANSPORT_UDP ?
+ "UDP" : "TCP",
+ ok_pair, ok_pair->use_candidate_on_next_check,
+ ok_pair->mark_nominated_on_response_arrival,
+ p, p->use_candidate_on_next_check,
+ p->mark_nominated_on_response_arrival);
+
+ if (agent->controlling_mode) {
+ switch (agent->nomination_mode) {
+ case NICE_NOMINATION_MODE_REGULAR:
+ if (p->use_candidate_on_next_check) {
+ nice_debug ("Agent %p : marking pair %p (%s) as nominated "
+ "(regular nomination, controlling, "
+ "use_cand_on_next_check=1).",
+ agent, ok_pair, ok_pair->foundation);
+ ok_pair->nominated = TRUE;
+ }
+ break;
+ case NICE_NOMINATION_MODE_AGGRESSIVE:
+ if (!p->nominated) {
+ nice_debug ("Agent %p : marking pair %p (%s) as nominated "
+ "(aggressive nomination, controlling).",
+ agent, ok_pair, ok_pair->foundation);
+ ok_pair->nominated = TRUE;
+ }
+ break;
+ default:
+ /* Nothing to do */
+ break;
+ }
+ } else {
+ if (p->mark_nominated_on_response_arrival) {
+ nice_debug ("Agent %p : marking pair %p (%s) as nominated "
+ "(%s nomination, controlled, mark_on_response=1).",
+ agent, ok_pair, ok_pair->foundation,
+ agent->nomination_mode == NICE_NOMINATION_MODE_AGGRESSIVE ?
+ "aggressive" : "regular");
+ ok_pair->nominated = TRUE;
+ }
+ }
+ }
+
+ if (ok_pair->nominated == TRUE) {
+ priv_update_selected_pair (agent, component, ok_pair);
+ priv_print_conn_check_lists (agent, G_STRFUNC,
+ ", got a nominated pair");
+
+ /* Do not step down to CONNECTED if we're already at state READY*/
+ if (component->state != NICE_COMPONENT_STATE_READY)
+ /* step: notify the client of a new component state (must be done
+ * before the possible check list state update step */
+ agent_signal_component_state_change (agent,
+ stream->id, component->id, NICE_COMPONENT_STATE_CONNECTED);
+ }
+
+ /* step: update pair states (ICE 7.1.2.2.3 "Updating pair
+ states" and 8.1.2 "Updating States", ID-19) */
+ priv_update_check_list_state_for_ready (agent, stream, component);
+ } else if (res == STUN_USAGE_ICE_RETURN_ROLE_CONFLICT) {
+ uint64_t tie;
+ gboolean controlled_mode;
+
+ /* case: role conflict error, need to restart with new role */
+ nice_debug ("Agent %p : Role conflict with pair %p, restarting",
+ agent, p);
+
+ /* note: this res value indicates that the role of the peer
+ * agent has not changed after the tie-breaker comparison, so
+ * this is our role that must change. see ICE sect. 7.1.3.1
+ * "Failure Cases". Our role might already have changed due to
+ * an earlier incoming request, but if not, change role now.
+ *
+ * Sect. 7.1.3.1 is not clear on this point, but we choose to
+ * put the candidate pair in the triggered check list even
+ * when the agent did not switch its role. The reason for this
+ * interpretation is that the reception of the stun reply, even
+ * an error reply, is a good sign that this pair will be
+ * valid, if we retry the check after the role of both peers
+ * has been fixed.
+ */
+ controlled_mode = (stun_message_find64 (&stun->message,
+ STUN_ATTRIBUTE_ICE_CONTROLLED, &tie) ==
+ STUN_MESSAGE_RETURN_SUCCESS);
+
+ priv_check_for_role_conflict (agent, controlled_mode);
+ priv_remove_stun_transaction (p, stun, component);
+ priv_add_pair_to_triggered_check_queue (agent, p);
+ } else {
+ /* case: STUN error, the check STUN context was freed */
+ candidate_check_pair_fail (stream, agent, p);
+ }
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/*
+ * Tries to match STUN reply in 'buf' to an existing STUN discovery
+ * transaction. If found, a reply is sent.
+ *
+ * @return TRUE if a matching transaction is found
+ */
+static gboolean priv_map_reply_to_discovery_request (NiceAgent *agent, StunMessage *resp)
+{
+ union {
+ struct sockaddr_storage storage;
+ struct sockaddr addr;
+ } sockaddr;
+ socklen_t socklen = sizeof (sockaddr);
+
+ union {
+ struct sockaddr_storage storage;
+ struct sockaddr addr;
+ } alternate;
+ socklen_t alternatelen = sizeof (sockaddr);
+
+ GSList *i;
+ StunUsageBindReturn res;
+ gboolean trans_found = FALSE;
+ StunTransactionId discovery_id;
+ StunTransactionId response_id;
+ stun_message_id (resp, response_id);
+
+ for (i = agent->discovery_list; i && trans_found != TRUE; i = i->next) {
+ CandidateDiscovery *d = i->data;
+
+ if (d->type == NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE &&
+ d->stun_message.buffer) {
+ stun_message_id (&d->stun_message, discovery_id);
+
+ if (memcmp (discovery_id, response_id, sizeof(StunTransactionId)) == 0) {
+ res = stun_usage_bind_process (resp, &sockaddr.addr,
+ &socklen, &alternate.addr, &alternatelen);
+ nice_debug ("Agent %p : stun_bind_process/disc for %p res %d.",
+ agent, d, (int)res);
+
+ if (res == STUN_USAGE_BIND_RETURN_ALTERNATE_SERVER) {
+ /* handle alternate server */
+ NiceAddress niceaddr;
+ nice_address_set_from_sockaddr (&niceaddr, &alternate.addr);
+ d->server = niceaddr;
+
+ d->pending = FALSE;
+ agent->discovery_unsched_items++;
+ } else if (res == STUN_USAGE_BIND_RETURN_SUCCESS) {
+ /* case: successful binding discovery, create a new local candidate */
+
+ if (!agent->force_relay) {
+ NiceAddress niceaddr;
+
+ nice_address_set_from_sockaddr (&niceaddr, &sockaddr.addr);
+ discovery_add_server_reflexive_candidate (
+ agent,
+ d->stream_id,
+ d->component_id,
+ &niceaddr,
+ NICE_CANDIDATE_TRANSPORT_UDP,
+ d->nicesock,
+ FALSE);
+ if (agent->use_ice_tcp)
+ discovery_discover_tcp_server_reflexive_candidates (
+ agent,
+ d->stream_id,
+ d->component_id,
+ &niceaddr,
+ d->nicesock);
+ }
+ d->stun_message.buffer = NULL;
+ d->stun_message.buffer_len = 0;
+ d->done = TRUE;
+ trans_found = TRUE;
+ } else if (res == STUN_USAGE_BIND_RETURN_ERROR) {
+ /* case: STUN error, the check STUN context was freed */
+ d->stun_message.buffer = NULL;
+ d->stun_message.buffer_len = 0;
+ d->done = TRUE;
+ trans_found = TRUE;
+ }
+ }
+ }
+ }
+
+ return trans_found;
+}
+
+static guint
+priv_calc_turn_timeout (guint lifetime)
+{
+ if (lifetime > 120)
+ return lifetime - 60;
+ else
+ return lifetime / 2;
+}
+
+static CandidateRefresh *
+priv_add_new_turn_refresh (NiceAgent *agent, CandidateDiscovery *cdisco,
+ NiceCandidate *relay_cand, guint lifetime)
+{
+ CandidateRefresh *cand;
+
+ cand = g_slice_new0 (CandidateRefresh);
+ agent->refresh_list = g_slist_append (agent->refresh_list, cand);
+
+ cand->candidate = relay_cand;
+ cand->nicesock = cdisco->nicesock;
+ cand->server = cdisco->server;
+ cand->stream_id = cdisco->stream_id;
+ cand->component_id = cdisco->component_id;
+ memcpy (&cand->stun_agent, &cdisco->stun_agent, sizeof(StunAgent));
+
+ /* Use previous stun response for authentication credentials */
+ if (cdisco->stun_resp_msg.buffer != NULL) {
+ memcpy(cand->stun_resp_buffer, cdisco->stun_resp_buffer,
+ sizeof(cand->stun_resp_buffer));
+ memcpy(&cand->stun_resp_msg, &cdisco->stun_resp_msg, sizeof(StunMessage));
+ cand->stun_resp_msg.buffer = cand->stun_resp_buffer;
+ cand->stun_resp_msg.agent = NULL;
+ cand->stun_resp_msg.key = NULL;
+ }
+
+ nice_debug ("Agent %p : Adding new refresh candidate %p with timeout %d",
+ agent, cand, priv_calc_turn_timeout (lifetime));
+ /* step: also start the refresh timer */
+ /* refresh should be sent 1 minute before it expires */
+ agent_timeout_add_seconds_with_context (agent, &cand->timer_source,
+ "Candidate TURN refresh",
+ priv_calc_turn_timeout (lifetime),
+ priv_turn_allocate_refresh_tick_agent_locked, cand);
+
+ nice_debug ("timer source is : %p", cand->timer_source);
+
+ return cand;
+}
+
+static void priv_handle_turn_alternate_server (NiceAgent *agent,
+ CandidateDiscovery *disco, NiceAddress server, NiceAddress alternate)
+{
+ /* We need to cancel and reset all candidate discovery turn for the same
+ stream and type if there is an alternate server. Otherwise, we might end up
+ with two relay components on different servers, creating candidates with
+ unique foundations that only contain one component.
+ */
+ GSList *i;
+
+ for (i = agent->discovery_list; i; i = i->next) {
+ CandidateDiscovery *d = i->data;
+
+ if (!d->done &&
+ d->type == disco->type &&
+ d->stream_id == disco->stream_id &&
+ d->turn->type == disco->turn->type &&
+ nice_address_equal (&d->server, &server)) {
+ gchar ip[INET6_ADDRSTRLEN];
+ // Cancel the pending request to avoid a race condition with another
+ // component responding with another altenrate-server
+ d->stun_message.buffer = NULL;
+ d->stun_message.buffer_len = 0;
+
+ nice_address_to_string (&server, ip);
+ nice_debug ("Agent %p : Cancelling and setting alternate server %s for "
+ "CandidateDiscovery %p", agent, ip, d);
+ d->server = alternate;
+ d->turn->server = alternate;
+ d->pending = FALSE;
+ agent->discovery_unsched_items++;
+ }
+ }
+}
+
+/*
+ * Tries to match STUN reply in 'buf' to an existing STUN discovery
+ * transaction. If found, a reply is sent.
+ *
+ * @return TRUE if a matching transaction is found
+ */
+static gboolean priv_map_reply_to_relay_request (NiceAgent *agent, StunMessage *resp)
+{
+ union {
+ struct sockaddr_storage storage;
+ struct sockaddr addr;
+ } sockaddr;
+ socklen_t socklen = sizeof (sockaddr);
+
+ union {
+ struct sockaddr_storage storage;
+ struct sockaddr addr;
+ } alternate;
+ socklen_t alternatelen = sizeof (alternate);
+
+ union {
+ struct sockaddr_storage storage;
+ struct sockaddr addr;
+ } relayaddr;
+ socklen_t relayaddrlen = sizeof (relayaddr);
+
+ uint32_t lifetime;
+ uint32_t bandwidth;
+ GSList *i;
+ StunUsageTurnReturn res;
+ gboolean trans_found = FALSE;
+ StunTransactionId discovery_id;
+ StunTransactionId response_id;
+ stun_message_id (resp, response_id);
+
+ for (i = agent->discovery_list; i && trans_found != TRUE; i = i->next) {
+ CandidateDiscovery *d = i->data;
+
+ if (d->type == NICE_CANDIDATE_TYPE_RELAYED &&
+ d->stun_message.buffer) {
+ stun_message_id (&d->stun_message, discovery_id);
+
+ if (memcmp (discovery_id, response_id, sizeof(StunTransactionId)) == 0) {
+ res = stun_usage_turn_process (resp,
+ &relayaddr.storage, &relayaddrlen,
+ &sockaddr.storage, &socklen,
+ &alternate.storage, &alternatelen,
+ &bandwidth, &lifetime, agent_to_turn_compatibility (agent));
+ nice_debug ("Agent %p : stun_turn_process/disc for %p res %d.",
+ agent, d, (int)res);
+
+ if (res == STUN_USAGE_TURN_RETURN_ALTERNATE_SERVER) {
+ NiceAddress addr;
+
+ /* handle alternate server */
+ nice_address_set_from_sockaddr (&addr, &alternate.addr);
+ priv_handle_turn_alternate_server (agent, d, d->server, addr);
+ } else if (res == STUN_USAGE_TURN_RETURN_RELAY_SUCCESS ||
+ res == STUN_USAGE_TURN_RETURN_MAPPED_SUCCESS) {
+ /* case: successful allocate, create a new local candidate */
+ NiceAddress niceaddr;
+ NiceCandidate *relay_cand;
+
+ nice_address_set_from_sockaddr (&niceaddr, &relayaddr.addr);
+
+ if (res == STUN_USAGE_TURN_RETURN_MAPPED_SUCCESS) {
+ NiceAddress mappedniceaddr;
+
+ /* We also received our mapped address */
+ nice_address_set_from_sockaddr (&mappedniceaddr, &sockaddr.addr);
+
+ /* TCP or TLS TURNS means the server-reflexive address was
+ * on a TCP connection, which cannot be used for server-reflexive
+ * discovery of candidates.
+ */
+ if (d->turn->type == NICE_RELAY_TYPE_TURN_UDP &&
+ !agent->force_relay) {
+ discovery_add_server_reflexive_candidate (
+ agent,
+ d->stream_id,
+ d->component_id,
+ &mappedniceaddr,
+ NICE_CANDIDATE_TRANSPORT_UDP,
+ d->nicesock,
+ FALSE);
+ }
+ if (agent->use_ice_tcp) {
+ if ((agent->compatibility == NICE_COMPATIBILITY_OC2007 ||
+ agent->compatibility == NICE_COMPATIBILITY_OC2007R2) &&
+ !nice_address_equal_no_port (&niceaddr, &d->turn->server)) {
+ nice_debug("TURN port got allocated on an alternate server, "
+ "ignoring bogus srflx address");
+ } else {
+ discovery_discover_tcp_server_reflexive_candidates (
+ agent,
+ d->stream_id,
+ d->component_id,
+ &mappedniceaddr,
+ d->nicesock);
+ }
+ }
+ }
+
+ if (nice_socket_is_reliable (d->nicesock)) {
+ relay_cand = discovery_add_relay_candidate (
+ agent,
+ d->stream_id,
+ d->component_id,
+ &niceaddr,
+ NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE,
+ d->nicesock,
+ d->turn);
+
+ if (relay_cand) {
+ if (agent->compatibility == NICE_COMPATIBILITY_OC2007 ||
+ agent->compatibility == NICE_COMPATIBILITY_OC2007R2) {
+ nice_udp_turn_socket_set_ms_realm(relay_cand->sockptr,
+ &d->stun_message);
+ nice_udp_turn_socket_set_ms_connection_id(relay_cand->sockptr,
+ resp);
+ } else {
+ priv_add_new_turn_refresh (agent, d, relay_cand, lifetime);
+ }
+ }
+
+ relay_cand = discovery_add_relay_candidate (
+ agent,
+ d->stream_id,
+ d->component_id,
+ &niceaddr,
+ NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE,
+ d->nicesock,
+ d->turn);
+ } else {
+ relay_cand = discovery_add_relay_candidate (
+ agent,
+ d->stream_id,
+ d->component_id,
+ &niceaddr,
+ NICE_CANDIDATE_TRANSPORT_UDP,
+ d->nicesock,
+ d->turn);
+ }
+
+ if (relay_cand) {
+ if (d->stun_resp_msg.buffer)
+ nice_udp_turn_socket_cache_realm_nonce (relay_cand->sockptr,
+ &d->stun_resp_msg);
+ if (agent->compatibility == NICE_COMPATIBILITY_OC2007 ||
+ agent->compatibility == NICE_COMPATIBILITY_OC2007R2) {
+ /* These data are needed on TURN socket when sending requests,
+ * but never reach nice_turn_socket_parse_recv() where it could
+ * be read directly, as the socket does not exist when allocate
+ * response arrives to _nice_agent_recv(). We must set them right
+ * after socket gets created in discovery_add_relay_candidate(),
+ * so we are doing it here. */
+ nice_udp_turn_socket_set_ms_realm(relay_cand->sockptr,
+ &d->stun_message);
+ nice_udp_turn_socket_set_ms_connection_id(relay_cand->sockptr,
+ resp);
+ } else {
+ priv_add_new_turn_refresh (agent, d, relay_cand, lifetime);
+ }
+
+ /* In case a new candidate has been added */
+ conn_check_schedule_next (agent);
+ }
+
+ d->stun_message.buffer = NULL;
+ d->stun_message.buffer_len = 0;
+ d->done = TRUE;
+ trans_found = TRUE;
+ } else if (res == STUN_USAGE_TURN_RETURN_ERROR) {
+ int code = -1;
+ uint8_t *sent_realm = NULL;
+ uint8_t *recv_realm = NULL;
+ uint16_t sent_realm_len = 0;
+ uint16_t recv_realm_len = 0;
+
+ sent_realm = (uint8_t *) stun_message_find (&d->stun_message,
+ STUN_ATTRIBUTE_REALM, &sent_realm_len);
+ recv_realm = (uint8_t *) stun_message_find (resp,
+ STUN_ATTRIBUTE_REALM, &recv_realm_len);
+
+ if ((agent->compatibility == NICE_COMPATIBILITY_OC2007 ||
+ agent->compatibility == NICE_COMPATIBILITY_OC2007R2) &&
+ alternatelen != sizeof(alternate)) {
+ NiceAddress addr;
+
+ nice_address_set_from_sockaddr (&addr, &alternate.addr);
+
+ if (!nice_address_equal (&addr, &d->server)) {
+ priv_handle_turn_alternate_server (agent, d, d->server, addr);
+ }
+ }
+ /* check for unauthorized error response */
+ if ((agent->compatibility == NICE_COMPATIBILITY_RFC5245 ||
+ agent->compatibility == NICE_COMPATIBILITY_OC2007 ||
+ agent->compatibility == NICE_COMPATIBILITY_OC2007R2) &&
+ stun_message_get_class (resp) == STUN_ERROR &&
+ stun_message_find_error (resp, &code) ==
+ STUN_MESSAGE_RETURN_SUCCESS &&
+ recv_realm != NULL && recv_realm_len > 0) {
+
+ if (code == STUN_ERROR_STALE_NONCE ||
+ (code == STUN_ERROR_UNAUTHORIZED &&
+ !(recv_realm_len == sent_realm_len &&
+ sent_realm != NULL &&
+ memcmp (sent_realm, recv_realm, sent_realm_len) == 0))) {
+ d->stun_resp_msg = *resp;
+ memcpy (d->stun_resp_buffer, resp->buffer,
+ stun_message_length (resp));
+ d->stun_resp_msg.buffer = d->stun_resp_buffer;
+ d->stun_resp_msg.buffer_len = sizeof(d->stun_resp_buffer);
+ d->pending = FALSE;
+ agent->discovery_unsched_items++;
+ } else {
+ /* case: a real unauthorized error */
+ d->stun_message.buffer = NULL;
+ d->stun_message.buffer_len = 0;
+ d->done = TRUE;
+ }
+ } else {
+ /* case: STUN error, the check STUN context was freed */
+ d->stun_message.buffer = NULL;
+ d->stun_message.buffer_len = 0;
+ d->done = TRUE;
+ }
+ trans_found = TRUE;
+ }
+ }
+ }
+ }
+
+ return trans_found;
+}
+
+
+/*
+ * Tries to match STUN reply in 'buf' to an existing STUN discovery
+ * transaction. If found, a reply is sent.
+ *
+ * @return TRUE if a matching transaction is found
+ */
+static gboolean priv_map_reply_to_relay_refresh (NiceAgent *agent, StunMessage *resp)
+{
+ uint32_t lifetime;
+ GSList *i;
+ StunUsageTurnReturn res;
+ gboolean trans_found = FALSE;
+ StunTransactionId refresh_id;
+ StunTransactionId response_id;
+ stun_message_id (resp, response_id);
+
+ for (i = agent->refresh_list; i && trans_found != TRUE; i = i->next) {
+ CandidateRefresh *cand = i->data;
+
+ if (!cand->disposing && cand->stun_message.buffer) {
+ stun_message_id (&cand->stun_message, refresh_id);
+
+ if (memcmp (refresh_id, response_id, sizeof(StunTransactionId)) == 0) {
+ res = stun_usage_turn_refresh_process (resp,
+ &lifetime, agent_to_turn_compatibility (agent));
+ nice_debug ("Agent %p : stun_turn_refresh_process for %p res %d with lifetime %u.",
+ agent, cand, (int)res, lifetime);
+ if (res == STUN_USAGE_TURN_RETURN_RELAY_SUCCESS) {
+ /* refresh should be sent 1 minute before it expires */
+ agent_timeout_add_seconds_with_context (agent,
+ &cand->timer_source,
+ "Candidate TURN refresh", priv_calc_turn_timeout (lifetime),
+ priv_turn_allocate_refresh_tick_agent_locked, cand);
+
+ g_source_destroy (cand->tick_source);
+ g_source_unref (cand->tick_source);
+ cand->tick_source = NULL;
+ } else if (res == STUN_USAGE_TURN_RETURN_ERROR) {
+ int code = -1;
+ uint8_t *sent_realm = NULL;
+ uint8_t *recv_realm = NULL;
+ uint16_t sent_realm_len = 0;
+ uint16_t recv_realm_len = 0;
+
+ sent_realm = (uint8_t *) stun_message_find (&cand->stun_message,
+ STUN_ATTRIBUTE_REALM, &sent_realm_len);
+ recv_realm = (uint8_t *) stun_message_find (resp,
+ STUN_ATTRIBUTE_REALM, &recv_realm_len);
+
+ /* check for unauthorized error response */
+ if (agent->compatibility == NICE_COMPATIBILITY_RFC5245 &&
+ stun_message_get_class (resp) == STUN_ERROR &&
+ stun_message_find_error (resp, &code) ==
+ STUN_MESSAGE_RETURN_SUCCESS &&
+ recv_realm != NULL && recv_realm_len > 0) {
+
+ if (code == STUN_ERROR_STALE_NONCE ||
+ (code == STUN_ERROR_UNAUTHORIZED &&
+ !(recv_realm_len == sent_realm_len &&
+ sent_realm != NULL &&
+ memcmp (sent_realm, recv_realm, sent_realm_len) == 0))) {
+ cand->stun_resp_msg = *resp;
+ memcpy (cand->stun_resp_buffer, resp->buffer,
+ stun_message_length (resp));
+ cand->stun_resp_msg.buffer = cand->stun_resp_buffer;
+ cand->stun_resp_msg.buffer_len = sizeof(cand->stun_resp_buffer);
+ priv_turn_allocate_refresh_tick_unlocked (agent, cand);
+ } else {
+ /* case: a real unauthorized error */
+ refresh_free (agent, cand);
+ }
+ } else {
+ /* case: STUN error, the check STUN context was freed */
+ refresh_free (agent, cand);
+ }
+ trans_found = TRUE;
+ }
+ }
+ }
+ }
+
+ return trans_found;
+}
+
+static gboolean priv_map_reply_to_relay_remove (NiceAgent *agent,
+ StunMessage *resp)
+{
+ StunTransactionId response_id;
+ GSList *i;
+
+ stun_message_id (resp, response_id);
+
+ for (i = agent->refresh_list; i; i = i->next) {
+ CandidateRefresh *cand = i->data;
+ StunTransactionId request_id;
+ StunUsageTurnReturn res;
+ uint32_t lifetime;
+
+ if (!cand->disposing || !cand->stun_message.buffer) {
+ continue;
+ }
+
+ stun_message_id (&cand->stun_message, request_id);
+
+ if (memcmp (request_id, response_id, sizeof(StunTransactionId)) == 0) {
+ res = stun_usage_turn_refresh_process (resp, &lifetime,
+ agent_to_turn_compatibility (agent));
+
+ nice_debug ("Agent %p : priv_map_reply_to_relay_remove for %p res %d "
+ "with lifetime %u.", agent, cand, res, lifetime);
+
+ if (res != STUN_USAGE_TURN_RETURN_INVALID) {
+ refresh_free (agent, cand);
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+static gboolean priv_map_reply_to_keepalive_conncheck (NiceAgent *agent,
+ NiceComponent *component, StunMessage *resp)
+{
+ StunTransactionId conncheck_id;
+ StunTransactionId response_id;
+ stun_message_id (resp, response_id);
+
+ if (component->selected_pair.keepalive.stun_message.buffer) {
+ stun_message_id (&component->selected_pair.keepalive.stun_message,
+ conncheck_id);
+ if (memcmp (conncheck_id, response_id, sizeof(StunTransactionId)) == 0) {
+ nice_debug ("Agent %p : Keepalive for selected pair received.",
+ agent);
+ if (component->selected_pair.keepalive.tick_source) {
+ g_source_destroy (component->selected_pair.keepalive.tick_source);
+ g_source_unref (component->selected_pair.keepalive.tick_source);
+ component->selected_pair.keepalive.tick_source = NULL;
+ }
+ component->selected_pair.keepalive.stun_message.buffer = NULL;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+typedef struct {
+ NiceAgent *agent;
+ NiceStream *stream;
+ NiceComponent *component;
+ uint8_t *password;
+} conncheck_validater_data;
+
+static bool conncheck_stun_validater (StunAgent *agent,
+ StunMessage *message, uint8_t *username, uint16_t username_len,
+ uint8_t **password, size_t *password_len, void *user_data)
+{
+ conncheck_validater_data *data = (conncheck_validater_data*) user_data;
+ GSList *i;
+ gchar *ufrag = NULL;
+ gsize ufrag_len;
+
+ gboolean msn_msoc_nice_compatibility =
+ data->agent->compatibility == NICE_COMPATIBILITY_MSN ||
+ data->agent->compatibility == NICE_COMPATIBILITY_OC2007;
+
+ if (data->agent->compatibility == NICE_COMPATIBILITY_OC2007 &&
+ stun_message_get_class (message) == STUN_RESPONSE)
+ i = data->component->remote_candidates;
+ else
+ i = data->component->local_candidates;
+
+ for (; i; i = i->next) {
+ NiceCandidate *cand = i->data;
+
+ ufrag = NULL;
+ if (cand->username)
+ ufrag = cand->username;
+ else
+ ufrag = data->stream->local_ufrag;
+ ufrag_len = ufrag? strlen (ufrag) : 0;
+
+ if (ufrag && msn_msoc_nice_compatibility)
+ ufrag = (gchar *)g_base64_decode (ufrag, &ufrag_len);
+
+ if (ufrag == NULL)
+ continue;
+
+ stun_debug ("Comparing username/ufrag of len %d and %" G_GSIZE_FORMAT ", equal=%d",
+ username_len, ufrag_len, username_len >= ufrag_len ?
+ memcmp (username, ufrag, ufrag_len) : 0);
+ stun_debug_bytes (" username: ", username, username_len);
+ stun_debug_bytes (" ufrag: ", ufrag, ufrag_len);
+ if (ufrag_len > 0 && username_len >= ufrag_len &&
+ memcmp (username, ufrag, ufrag_len) == 0) {
+ gchar *pass = NULL;
+
+ if (cand->password)
+ pass = cand->password;
+ else if (data->stream && data->stream->local_password[0])
+ pass = data->stream->local_password;
+
+ if (pass) {
+ *password = (uint8_t *) pass;
+ *password_len = strlen (pass);
+
+ if (msn_msoc_nice_compatibility) {
+ gsize pass_len;
+
+ data->password = g_base64_decode (pass, &pass_len);
+ *password = data->password;
+ *password_len = pass_len;
+ }
+ }
+
+ if (msn_msoc_nice_compatibility)
+ g_free (ufrag);
+
+ stun_debug ("Found valid username, returning password: '%s'", *password);
+ return TRUE;
+ }
+
+ if (msn_msoc_nice_compatibility)
+ g_free (ufrag);
+ }
+
+ return FALSE;
+}
+
+/*
+ * handle RENOMINATION stun attribute
+ * @return TRUE if nomination changed. FALSE otherwise
+ */
+static gboolean conn_check_handle_renomination (NiceAgent *agent, NiceStream *stream,
+ NiceComponent *component, StunMessage *req,
+ NiceCandidate *remote_candidate, NiceCandidate *local_candidate)
+{
+ GSList *lst;
+ if (!agent->controlling_mode && NICE_AGENT_IS_COMPATIBLE_WITH_RFC5245_OR_OC2007R2 (agent) &&
+ agent->support_renomination && remote_candidate && local_candidate)
+ {
+ uint32_t nom_value = 0;
+ uint16_t nom_len = 0;
+ const void *value = stun_message_find (req, STUN_ATTRIBUTE_NOMINATION, &nom_len);
+ if (nom_len == 0) {
+ return FALSE;
+ }
+ if (nom_len == 4) {
+ memcpy (&nom_value, value, 4);
+ nom_value = ntohl (nom_value);
+ } else {
+ nice_debug ("Agent %p : received NOMINATION attr with incorrect octet length %u, expected 4 bytes",
+ agent, nom_len);
+ return FALSE;
+ }
+
+ if (nice_debug_is_enabled ()) {
+ gchar remote_str[INET6_ADDRSTRLEN];
+ nice_address_to_string(&remote_candidate->addr, remote_str);
+ nice_debug ("Agent %p : received NOMINATION attr for remote candidate [%s]:%u, value is %u",
+ agent, remote_str, nice_address_get_port (&remote_candidate->addr), nom_value);
+ }
+
+ /*
+ * If another pair is SELECTED, change this pair's priority to be greater than
+ * selected pair's priority so this pair gets SELECTED!
+ */
+ if (component->selected_pair.priority &&
+ component->selected_pair.remote && component->selected_pair.remote != remote_candidate &&
+ component->selected_pair.local && component->selected_pair.local != local_candidate) {
+ for (lst = stream->conncheck_list; lst; lst = lst->next) {
+ CandidateCheckPair *pair = lst->data;
+ if (pair->local == local_candidate && pair->remote == remote_candidate) {
+ if (pair->valid) {
+ pair->priority = component->selected_pair.priority + 1;
+ }
+ break;
+ }
+ }
+ }
+ priv_mark_pair_nominated (agent, stream, component, local_candidate, remote_candidate);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+ * Processing an incoming STUN message.
+ *
+ * @param agent self pointer
+ * @param stream stream the packet is related to
+ * @param component component the packet is related to
+ * @param nicesock socket from which the packet was received
+ * @param from address of the sender
+ * @param buf message contents
+ * @param buf message length
+ *
+ * @pre contents of 'buf' is a STUN message
+ *
+ * @return XXX (what FALSE means exactly?)
+ */
+gboolean conn_check_handle_inbound_stun (NiceAgent *agent, NiceStream *stream,
+ NiceComponent *component, NiceSocket *nicesock, const NiceAddress *from,
+ gchar *buf, guint len)
+{
+ union {
+ struct sockaddr_storage storage;
+ struct sockaddr addr;
+ } sockaddr;
+ uint8_t rbuf[MAX_STUN_DATAGRAM_PAYLOAD];
+ ssize_t res;
+ size_t rbuf_len = sizeof (rbuf);
+ bool control = agent->controlling_mode;
+ uint8_t uname[NICE_STREAM_MAX_UNAME];
+ guint uname_len;
+ uint8_t *username;
+ uint16_t username_len;
+ StunMessage req;
+ StunMessage msg;
+ StunValidationStatus valid;
+ conncheck_validater_data validater_data = {agent, stream, component, NULL};
+ GSList *i, *j;
+ NiceCandidate *remote_candidate = NULL;
+ NiceCandidate *remote_candidate2 = NULL;
+ NiceCandidate *local_candidate = NULL;
+ gboolean discovery_msg = FALSE;
+
+ nice_address_copy_to_sockaddr (from, &sockaddr.addr);
+
+ /* note: contents of 'buf' already validated, so it is
+ * a valid and fully received STUN message */
+
+ if (nice_debug_is_enabled ()) {
+ gchar tmpbuf[INET6_ADDRSTRLEN];
+ nice_address_to_string (from, tmpbuf);
+ nice_debug ("Agent %p: inbound STUN packet for %u/%u (stream/component) from [%s]:%u (%u octets) :",
+ agent, stream->id, component->id, tmpbuf, nice_address_get_port (from), len);
+ }
+
+ /* note: ICE 7.2. "STUN Server Procedures" (ID-19) */
+
+ valid = stun_agent_validate (&component->stun_agent, &req,
+ (uint8_t *) buf, len, conncheck_stun_validater, &validater_data);
+
+ /* Check for discovery candidates stun agents */
+ if (valid == STUN_VALIDATION_BAD_REQUEST ||
+ valid == STUN_VALIDATION_UNMATCHED_RESPONSE) {
+ for (i = agent->discovery_list; i; i = i->next) {
+ CandidateDiscovery *d = i->data;
+ if (d->stream_id == stream->id && d->component_id == component->id &&
+ d->nicesock == nicesock) {
+ valid = stun_agent_validate (&d->stun_agent, &req,
+ (uint8_t *) buf, len, conncheck_stun_validater, &validater_data);
+
+ if (valid == STUN_VALIDATION_UNMATCHED_RESPONSE)
+ continue;
+
+ discovery_msg = TRUE;
+ break;
+ }
+ }
+ }
+ /* Check for relay refresh stun agents */
+ if (valid == STUN_VALIDATION_BAD_REQUEST ||
+ valid == STUN_VALIDATION_UNMATCHED_RESPONSE) {
+ for (i = agent->refresh_list; i; i = i->next) {
+ CandidateRefresh *r = i->data;
+
+ nice_debug_verbose ("Comparing r.sid=%u to sid=%u, r.cid=%u to cid=%u and %p and %p to %p",
+ r->stream_id, stream->id, r->component_id, component->id, r->nicesock,
+ r->candidate->sockptr, nicesock);
+
+ if (r->stream_id == stream->id && r->component_id == component->id &&
+ (r->nicesock == nicesock || r->candidate->sockptr == nicesock)) {
+ valid = stun_agent_validate (&r->stun_agent, &req,
+ (uint8_t *) buf, len, conncheck_stun_validater, &validater_data);
+ nice_debug ("Validating gave %d", valid);
+ if (valid == STUN_VALIDATION_UNMATCHED_RESPONSE)
+ continue;
+ discovery_msg = TRUE;
+ break;
+ }
+ }
+ }
+
+ g_free (validater_data.password);
+
+ if (valid == STUN_VALIDATION_NOT_STUN ||
+ valid == STUN_VALIDATION_INCOMPLETE_STUN ||
+ valid == STUN_VALIDATION_BAD_REQUEST)
+ {
+ nice_debug ("Agent %p : Incorrectly multiplexed STUN message ignored.",
+ agent);
+ return FALSE;
+ }
+
+ if (valid == STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE) {
+ nice_debug ("Agent %p : Unknown mandatory attributes in message.", agent);
+
+ if (agent->compatibility != NICE_COMPATIBILITY_MSN &&
+ agent->compatibility != NICE_COMPATIBILITY_OC2007) {
+ rbuf_len = stun_agent_build_unknown_attributes_error (&component->stun_agent,
+ &msg, rbuf, rbuf_len, &req);
+ if (rbuf_len != 0)
+ agent_socket_send (nicesock, from, rbuf_len, (const gchar*)rbuf);
+ }
+ return TRUE;
+ }
+
+ if (valid == STUN_VALIDATION_UNAUTHORIZED) {
+ nice_debug ("Agent %p : Integrity check failed.", agent);
+
+ if (stun_agent_init_error (&component->stun_agent, &msg, rbuf, rbuf_len,
+ &req, STUN_ERROR_UNAUTHORIZED)) {
+ rbuf_len = stun_agent_finish_message (&component->stun_agent, &msg, NULL, 0);
+ if (rbuf_len > 0 && agent->compatibility != NICE_COMPATIBILITY_MSN &&
+ agent->compatibility != NICE_COMPATIBILITY_OC2007)
+ agent_socket_send (nicesock, from, rbuf_len, (const gchar*)rbuf);
+ }
+ return TRUE;
+ }
+ if (valid == STUN_VALIDATION_UNAUTHORIZED_BAD_REQUEST) {
+ nice_debug ("Agent %p : Integrity check failed - bad request.", agent);
+ if (stun_agent_init_error (&component->stun_agent, &msg, rbuf, rbuf_len,
+ &req, STUN_ERROR_BAD_REQUEST)) {
+ rbuf_len = stun_agent_finish_message (&component->stun_agent, &msg, NULL, 0);
+ if (rbuf_len > 0 && agent->compatibility != NICE_COMPATIBILITY_MSN &&
+ agent->compatibility != NICE_COMPATIBILITY_OC2007)
+ agent_socket_send (nicesock, from, rbuf_len, (const gchar*)rbuf);
+ }
+ return TRUE;
+ }
+
+ username = (uint8_t *) stun_message_find (&req, STUN_ATTRIBUTE_USERNAME,
+ &username_len);
+
+ for (i = component->remote_candidates; i; i = i->next) {
+ NiceCandidate *cand = i->data;
+ if (nice_address_equal (from, &cand->addr)) {
+ remote_candidate = cand;
+ break;
+ }
+ }
+ for (i = component->local_candidates; i; i = i->next) {
+ NiceCandidate *cand = i->data;
+ if (nice_address_equal (&nicesock->addr, &cand->addr)) {
+ local_candidate = cand;
+ break;
+ }
+ }
+
+ if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE ||
+ agent->compatibility == NICE_COMPATIBILITY_MSN ||
+ agent->compatibility == NICE_COMPATIBILITY_OC2007) {
+ /* We need to find which local candidate was used */
+ for (i = component->remote_candidates;
+ i != NULL && remote_candidate2 == NULL; i = i->next) {
+ for (j = component->local_candidates; j; j = j->next) {
+ gboolean inbound = TRUE;
+ NiceCandidate *rcand = i->data;
+ NiceCandidate *lcand = j->data;
+
+ /* If we receive a response, then the username is local:remote */
+ if (agent->compatibility != NICE_COMPATIBILITY_MSN) {
+ if (stun_message_get_class (&req) == STUN_REQUEST ||
+ stun_message_get_class (&req) == STUN_INDICATION) {
+ inbound = TRUE;
+ } else {
+ inbound = FALSE;
+ }
+ }
+
+ uname_len = priv_create_username (agent, stream,
+ component->id, rcand, lcand,
+ uname, sizeof (uname), inbound);
+
+
+
+ stun_debug ("Comparing usernames of size %d and %d: %d",
+ username_len, uname_len, username && uname_len == username_len &&
+ memcmp (username, uname, uname_len) == 0);
+ stun_debug_bytes (" First username: ", username,
+ username ? username_len : 0);
+ stun_debug_bytes (" Second uname: ", uname, uname_len);
+
+ if (username &&
+ uname_len == username_len &&
+ memcmp (uname, username, username_len) == 0) {
+ local_candidate = lcand;
+ remote_candidate2 = rcand;
+ break;
+ }
+ }
+ }
+ }
+
+ if (component->remote_candidates &&
+ agent->compatibility == NICE_COMPATIBILITY_GOOGLE &&
+ local_candidate == NULL &&
+ discovery_msg == FALSE) {
+ /* if we couldn't match the username and the stun agent has
+ IGNORE_CREDENTIALS then we have an integrity check failing.
+ This could happen with the race condition of receiving connchecks
+ before the remote candidates are added. Just drop the message, and let
+ the retransmissions make it work. */
+ nice_debug ("Agent %p : Username check failed.", agent);
+ return TRUE;
+ }
+
+ if (valid != STUN_VALIDATION_SUCCESS) {
+ nice_debug ("Agent %p : STUN message is unsuccessful %d, ignoring", agent, valid);
+ return FALSE;
+ }
+
+
+ if (stun_message_get_class (&req) == STUN_REQUEST) {
+ if ( agent->compatibility == NICE_COMPATIBILITY_MSN
+ || agent->compatibility == NICE_COMPATIBILITY_OC2007) {
+ if (local_candidate && remote_candidate2) {
+ gsize key_len;
+
+ if (agent->compatibility == NICE_COMPATIBILITY_MSN) {
+ username = (uint8_t *) stun_message_find (&req,
+ STUN_ATTRIBUTE_USERNAME, &username_len);
+ uname_len = priv_create_username (agent, stream,
+ component->id, remote_candidate2, local_candidate,
+ uname, sizeof (uname), FALSE);
+ memcpy (username, uname, MIN (uname_len, username_len));
+
+ req.key = g_base64_decode ((gchar *) remote_candidate2->password,
+ &key_len);
+ req.key_len = key_len;
+ } else if (agent->compatibility == NICE_COMPATIBILITY_OC2007) {
+ req.key = g_base64_decode ((gchar *) local_candidate->password,
+ &key_len);
+ req.key_len = key_len;
+ }
+ } else {
+ nice_debug ("Agent %p : received MSN incoming check from unknown remote candidate. "
+ "Ignoring request", agent);
+ return TRUE;
+ }
+ }
+
+ rbuf_len = sizeof (rbuf);
+ res = stun_usage_ice_conncheck_create_reply (&component->stun_agent, &req,
+ &msg, rbuf, &rbuf_len, &sockaddr.storage, sizeof (sockaddr),
+ &control, agent->tie_breaker,
+ agent_to_ice_compatibility (agent));
+
+ if ( agent->compatibility == NICE_COMPATIBILITY_MSN
+ || agent->compatibility == NICE_COMPATIBILITY_OC2007) {
+ g_free (req.key);
+ }
+
+ if (res == STUN_USAGE_ICE_RETURN_ROLE_CONFLICT)
+ priv_check_for_role_conflict (agent, control);
+
+ if (res == STUN_USAGE_ICE_RETURN_SUCCESS ||
+ res == STUN_USAGE_ICE_RETURN_ROLE_CONFLICT) {
+ /* case 1: valid incoming request, send a reply/error */
+ bool use_candidate =
+ stun_usage_ice_conncheck_use_candidate (&req);
+ uint32_t priority = stun_usage_ice_conncheck_priority (&req);
+
+ if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE ||
+ agent->compatibility == NICE_COMPATIBILITY_MSN ||
+ agent->compatibility == NICE_COMPATIBILITY_OC2007)
+ use_candidate = TRUE;
+
+ if (stream->initial_binding_request_received != TRUE)
+ agent_signal_initial_binding_request_received (agent, stream);
+
+ if (remote_candidate == NULL) {
+ nice_debug ("Agent %p : No matching remote candidate for incoming "
+ "check -> peer-reflexive candidate.", agent);
+ remote_candidate = discovery_learn_remote_peer_reflexive_candidate (
+ agent, stream, component, priority, from, nicesock,
+ local_candidate,
+ remote_candidate2 ? remote_candidate2 : remote_candidate);
+ if(remote_candidate && stream->remote_ufrag[0]) {
+ if (local_candidate &&
+ local_candidate->transport == NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE) {
+ CandidateCheckPair *pair;
+
+ pair = priv_conn_check_add_for_candidate_pair_matched (agent,
+ stream->id, component, local_candidate, remote_candidate,
+ NICE_CHECK_SUCCEEDED);
+ if (pair) {
+ pair->valid = TRUE;
+ }
+ } else
+ conn_check_add_for_candidate (agent, stream->id, component, remote_candidate);
+ }
+ }
+
+ nice_component_add_valid_candidate (agent, component, remote_candidate);
+
+ priv_reply_to_conn_check (agent, stream, component, local_candidate,
+ remote_candidate, from, nicesock, rbuf_len, &msg, use_candidate);
+
+ if (stream->remote_ufrag[0] == 0) {
+ /* case: We've got a valid binding request to a local candidate
+ * but we do not yet know remote credentials.
+ * As per sect 7.2 of ICE (ID-19), we send a reply
+ * immediately but postpone all other processing until
+ * we get information about the remote candidates */
+
+ /* step: send a reply immediately but postpone other processing */
+ priv_store_pending_check (agent, component, from, nicesock,
+ username, username_len, priority, use_candidate);
+ }
+ } else {
+ nice_debug ("Agent %p : Invalid STUN packet, ignoring... %s",
+ agent, strerror(errno));
+ return FALSE;
+ }
+ } else {
+ /* case 2: not a new request, might be a reply... */
+ gboolean trans_found = FALSE;
+
+ /* note: ICE sect 7.1.2. "Processing the Response" (ID-19) */
+
+ /* step: let's try to match the response to an existing check context */
+ if (trans_found != TRUE)
+ trans_found = priv_map_reply_to_conn_check_request (agent, stream,
+ component, nicesock, from, local_candidate, remote_candidate, &req);
+
+ /* step: let's try to match the response to an existing discovery */
+ if (trans_found != TRUE)
+ trans_found = priv_map_reply_to_discovery_request (agent, &req);
+
+ /* step: let's try to match the response to an existing turn allocate */
+ if (trans_found != TRUE)
+ trans_found = priv_map_reply_to_relay_request (agent, &req);
+
+ /* step: let's try to match the response to an existing turn refresh */
+ if (trans_found != TRUE)
+ trans_found = priv_map_reply_to_relay_refresh (agent, &req);
+
+ if (trans_found != TRUE)
+ trans_found = priv_map_reply_to_relay_remove (agent, &req);
+
+ /* step: let's try to match the response to an existing keepalive conncheck */
+ if (trans_found != TRUE)
+ trans_found = priv_map_reply_to_keepalive_conncheck (agent, component,
+ &req);
+
+ if (trans_found != TRUE)
+ nice_debug ("Agent %p : Unable to match to an existing transaction, "
+ "probably a keepalive.", agent);
+ }
+
+ /* RENOMINATION attribute support */
+ conn_check_handle_renomination(agent, stream, component, &req, local_candidate, remote_candidate);
+
+ return TRUE;
+}
+
+/* Remove all pointers to the given @sock from the connection checking process.
+ * These are entirely NiceCandidates pointed to from various places. */
+void
+conn_check_prune_socket (NiceAgent *agent, NiceStream *stream, NiceComponent *component,
+ NiceSocket *sock)
+{
+ GSList *l;
+
+ if (component->selected_pair.local &&
+ component->selected_pair.local->sockptr == sock &&
+ component->state == NICE_COMPONENT_STATE_READY) {
+ nice_debug ("Agent %p: Selected pair socket %p has been destroyed, "
+ "declaring failed", agent, sock);
+ agent_signal_component_state_change (agent,
+ stream->id, component->id, NICE_COMPONENT_STATE_FAILED);
+ }
+
+ /* Prune from the candidate check pairs. */
+ for (l = stream->conncheck_list; l != NULL;) {
+ CandidateCheckPair *p = l->data;
+ GSList *next = l->next;
+
+ if ((p->local != NULL && p->local->sockptr == sock) ||
+ (p->remote != NULL && p->remote->sockptr == sock) ||
+ (p->sockptr == sock)) {
+ nice_debug ("Agent %p : Retransmissions failed, giving up on pair %p",
+ agent, p);
+ candidate_check_pair_fail (stream, agent, p);
+ candidate_check_pair_free (agent, p);
+ stream->conncheck_list = g_slist_delete_link (stream->conncheck_list, l);
+ }
+
+ l = next;
+ }
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2006-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2006-2009 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Dafydd Harries, Collabora Ltd.
+ * Youness Alaoui, Collabora Ltd.
+ * Kai Vehmanen, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef _NICE_CONNCHECK_H
+#define _NICE_CONNCHECK_H
+
+/* note: this is a private header to libnice */
+
+#include "agent.h"
+#include "stream.h"
+#include "stun/stunagent.h"
+#include "stun/usages/timer.h"
+
+#define NICE_CANDIDATE_PAIR_MAX_FOUNDATION NICE_CANDIDATE_MAX_FOUNDATION*2
+
+/**
+ * NiceCheckState:
+ * @NICE_CHECK_WAITING: Waiting to be scheduled.
+ * @NICE_CHECK_IN_PROGRESS: Connection checks started.
+ * @NICE_CHECK_SUCCEEDED: Connection successfully checked.
+ * @NICE_CHECK_FAILED: No connectivity; retransmissions ceased.
+ * @NICE_CHECK_FROZEN: Waiting to be scheduled to %NICE_CHECK_WAITING.
+ * @NICE_CHECK_DISCOVERED: A valid candidate pair not on the check list.
+ *
+ * States for checking a candidate pair.
+ */
+typedef enum
+{
+ NICE_CHECK_WAITING = 1,
+ NICE_CHECK_IN_PROGRESS,
+ NICE_CHECK_SUCCEEDED,
+ NICE_CHECK_FAILED,
+ NICE_CHECK_FROZEN,
+ NICE_CHECK_DISCOVERED,
+} NiceCheckState;
+
+typedef struct _CandidateCheckPair CandidateCheckPair;
+typedef struct _StunTransaction StunTransaction;
+
+struct _StunTransaction
+{
+ GTimeVal next_tick; /* next tick timestamp */
+ StunTimer timer;
+ uint8_t buffer[STUN_MAX_MESSAGE_SIZE_IPV6];
+ StunMessage message;
+};
+
+struct _CandidateCheckPair
+{
+ guint stream_id;
+ guint component_id;
+ NiceCandidate *local;
+ NiceCandidate *remote;
+ NiceSocket *sockptr;
+ gchar foundation[NICE_CANDIDATE_PAIR_MAX_FOUNDATION];
+ NiceCheckState state;
+ gboolean nominated;
+ gboolean valid;
+ gboolean use_candidate_on_next_check;
+ gboolean mark_nominated_on_response_arrival;
+ gboolean retransmit; /* if the first stun request must be retransmitted */
+ CandidateCheckPair *discovered_pair;
+ CandidateCheckPair *succeeded_pair;
+ guint64 priority;
+ guint32 prflx_priority;
+ GSList *stun_transactions; /* a list of ongoing stun requests */
+};
+
+int conn_check_add_for_candidate (NiceAgent *agent, guint stream_id, NiceComponent *component, NiceCandidate *remote);
+int conn_check_add_for_local_candidate (NiceAgent *agent, guint stream_id, NiceComponent *component, NiceCandidate *local);
+gboolean conn_check_add_for_candidate_pair (NiceAgent *agent, guint stream_id, NiceComponent *component, NiceCandidate *local, NiceCandidate *remote);
+void conn_check_free (NiceAgent *agent);
+void conn_check_schedule_next (NiceAgent *agent);
+int conn_check_send (NiceAgent *agent, CandidateCheckPair *pair);
+void conn_check_prune_stream (NiceAgent *agent, NiceStream *stream);
+gboolean conn_check_handle_inbound_stun (NiceAgent *agent, NiceStream *stream, NiceComponent *component, NiceSocket *udp_socket, const NiceAddress *from, gchar *buf, guint len);
+gint conn_check_compare (const CandidateCheckPair *a, const CandidateCheckPair *b);
+void conn_check_remote_candidates_set(NiceAgent *agent, NiceStream *stream, NiceComponent *component);
+void conn_check_remote_credentials_set(NiceAgent *agent, NiceStream *stream);
+NiceCandidateTransport conn_check_match_transport (NiceCandidateTransport transport);
+void
+conn_check_prune_socket (NiceAgent *agent, NiceStream *stream, NiceComponent *component,
+ NiceSocket *sock);
+
+guint32 ensure_unique_priority (NiceStream *stream, NiceComponent *component,
+ guint32 priority);
+void recalculate_pair_priorities (NiceAgent *agent);
+
+#endif /*_NICE_CONNCHECK_H */
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2008 Nokia Corporation. All rights reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#include "debug.h"
+
+#include "stunagent.h"
+#include "pseudotcp.h"
+
+#include "agent-priv.h"
+
+static int debug_enabled = 0;
+static int debug_verbose_enabled = 0;
+
+#define NICE_DEBUG_STUN 1
+#define NICE_DEBUG_NICE 2
+#define NICE_DEBUG_PSEUDOTCP 4
+#define NICE_DEBUG_PSEUDOTCP_VERBOSE 8
+#define NICE_DEBUG_NICE_VERBOSE 16
+
+static const GDebugKey keys[] = {
+ { (gchar *)"stun", NICE_DEBUG_STUN },
+ { (gchar *)"nice", NICE_DEBUG_NICE },
+ { (gchar *)"pseudotcp", NICE_DEBUG_PSEUDOTCP },
+ { (gchar *)"pseudotcp-verbose", NICE_DEBUG_PSEUDOTCP_VERBOSE },
+ { (gchar *)"nice-verbose", NICE_DEBUG_NICE_VERBOSE },
+ { NULL, 0},
+};
+
+static const GDebugKey gkeys[] = {
+ { (gchar *)"libnice-stun", NICE_DEBUG_STUN },
+ { (gchar *)"libnice", NICE_DEBUG_NICE },
+ { (gchar *)"libnice-pseudotcp", NICE_DEBUG_PSEUDOTCP },
+ { (gchar *)"libnice-pseudotcp-verbose", NICE_DEBUG_PSEUDOTCP_VERBOSE },
+ { (gchar *)"libnice-verbose", NICE_DEBUG_NICE_VERBOSE },
+ { NULL, 0},
+};
+
+static void
+stun_handler (const char *format, va_list ap) G_GNUC_PRINTF (1, 0);
+
+static void
+stun_handler (const char *format, va_list ap)
+{
+ g_logv ("libnice-stun", G_LOG_LEVEL_DEBUG, format, ap);
+}
+
+void nice_debug_init (void)
+{
+ static gboolean debug_initialized = FALSE;
+ const gchar *flags_string;
+ const gchar *gflags_string;
+ guint flags = 0;
+
+ if (!debug_initialized) {
+ debug_initialized = TRUE;
+
+ flags_string = g_getenv ("NICE_DEBUG");
+ gflags_string = g_getenv ("G_MESSAGES_DEBUG");
+
+ if (flags_string)
+ flags = g_parse_debug_string (flags_string, keys, 4);
+ if (gflags_string)
+ flags |= g_parse_debug_string (gflags_string, gkeys, 4);
+ if (gflags_string && strstr (gflags_string, "libnice-pseudotcp-verbose"))
+ flags |= NICE_DEBUG_PSEUDOTCP_VERBOSE;
+ if (gflags_string && strstr (gflags_string, "libnice-verbose")) {
+ flags |= NICE_DEBUG_NICE_VERBOSE;
+ }
+
+ stun_set_debug_handler (stun_handler);
+ debug_enabled = !!(flags & NICE_DEBUG_NICE);
+ if (flags & NICE_DEBUG_STUN)
+ stun_debug_enable ();
+ else
+ stun_debug_disable ();
+
+ if (flags & NICE_DEBUG_NICE_VERBOSE)
+ debug_verbose_enabled = TRUE;
+
+ /* Set verbose before normal so that if we use 'all', then only
+ normal debug is enabled, we'd need to set pseudotcp-verbose without the
+ pseudotcp flag in order to actually enable verbose pseudotcp */
+ if (flags & NICE_DEBUG_PSEUDOTCP_VERBOSE)
+ pseudo_tcp_set_debug_level (PSEUDO_TCP_DEBUG_VERBOSE);
+ else if (flags & NICE_DEBUG_PSEUDOTCP)
+ pseudo_tcp_set_debug_level (PSEUDO_TCP_DEBUG_NORMAL);
+ }
+}
+
+#ifndef NDEBUG
+gboolean nice_debug_is_enabled (void)
+{
+ return debug_enabled;
+}
+gboolean nice_debug_is_verbose (void)
+{
+ return debug_verbose_enabled;
+}
+#else
+/* Defined in agent-priv.h. */
+#endif
+
+void nice_debug_enable (gboolean with_stun)
+{
+ nice_debug_init ();
+ debug_enabled = 1;
+ if (with_stun)
+ stun_debug_enable ();
+}
+void nice_debug_disable (gboolean with_stun)
+{
+ nice_debug_init ();
+ debug_enabled = 0;
+ if (with_stun)
+ stun_debug_disable ();
+}
+
+#ifndef NDEBUG
+void nice_debug (const char *fmt, ...)
+{
+ va_list ap;
+ if (debug_enabled) {
+ va_start (ap, fmt);
+ g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, fmt, ap);
+ va_end (ap);
+ }
+}
+void nice_debug_verbose (const char *fmt, ...)
+{
+ va_list ap;
+ if (debug_verbose_enabled) {
+ va_start (ap, fmt);
+ g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, fmt, ap);
+ va_end (ap);
+ }
+}
+#else
+/* Defined in agent-priv.h. */
+#endif
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2008 Nokia Corporation. All rights reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef __LIBNICE_DEBUG_H__
+#define __LIBNICE_DEBUG_H__
+
+
+/**
+ * SECTION:debug
+ * @short_description: Debug messages utility functions
+ * @stability: Unstable
+ *
+ * <para>Libnice can output a lot of information when debug messages are enabled.
+ * This can significantly help track down problems and/or understand what
+ * it's doing.</para>
+ *
+ * <para>You can enable/disable the debug messages by calling nice_debug_enable()
+ * or nice_debug_disable() and choosing whether you want only ICE debug messages
+ * or also stun debug messages.</para>
+ *
+ * <para>By default, the debug messages are disabled, unless the environment
+ * variable NICE_DEBUG is set, in which case, it must contain a comma separated
+ * list of flags specifying which debug to enable.</para>
+ * <para> The currently available flags are "nice", "stun", "pseudotcp",
+ * "pseudotcp-verbose" or "all" to enable all debug messages.</para>
+ * <para> If the 'pseudotcp' flag is enabled, then 'pseudotcp-verbose' gets
+ * automatically disabled. This is to allow the use of the 'all' flag without
+ * having verbose messages from pseudotcp. You can enable verbose debug messages
+ * from the pseudotcp layer by specifying 'pseudotcp-verbose' without the
+ * 'pseudotcp' flag.</para>
+ *
+ *
+ * <para>This API is unstable and is subject to change at any time...
+ * More flags are to come and a better API to enable/disable each flag
+ * should be added.</para>
+ */
+
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+/**
+ * nice_debug_enable:
+ * @with_stun: Also enable STUN debugging messages
+ *
+ * Enables libnice debug output to the terminal. Note that the
+ * `G_MESSAGES_DEBUG` and `NICE_DEBUG` environment variables must be set to the
+ * set of logging domains to print, in order for any output to be printed. Set
+ * them to `all` to print all debugging messages, or any of the following
+ * domains:
+ * - `libnice-stun`
+ * - `libnice-tests`
+ * - `libnice-socket`
+ * - `libnice`
+ * - `libnice-pseudotcp`
+ * - `libnice-pseudotcp-verbose`
+ */
+void nice_debug_enable (gboolean with_stun);
+
+/**
+ * nice_debug_disable:
+ * @with_stun: Also disable stun debugging messages
+ *
+ * Disables libnice debug output to the terminal
+ */
+void nice_debug_disable (gboolean with_stun);
+
+G_END_DECLS
+
+#endif /* __LIBNICE_DEBUG_H__ */
+
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2007-2009 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ * Kai Vehmanen, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+/*
+ * @file discovery.c
+ * @brief ICE candidate discovery functions
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <glib.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "debug.h"
+
+#include "agent.h"
+#include "agent-priv.h"
+#include "component.h"
+#include "discovery.h"
+#include "stun/usages/bind.h"
+#include "stun/usages/turn.h"
+#include "socket.h"
+
+static inline int priv_timer_expired (GTimeVal *timer, GTimeVal *now)
+{
+ return (now->tv_sec == timer->tv_sec) ?
+ now->tv_usec >= timer->tv_usec :
+ now->tv_sec >= timer->tv_sec;
+}
+
+/*
+ * Frees the CandidateDiscovery structure pointed to
+ * by 'user data'. Compatible with g_slist_free_full().
+ */
+static void discovery_free_item (CandidateDiscovery *cand)
+{
+ if (cand->turn)
+ turn_server_unref (cand->turn);
+
+ g_slice_free (CandidateDiscovery, cand);
+}
+
+/*
+ * Frees all discovery related resources for the agent.
+ */
+void discovery_free (NiceAgent *agent)
+{
+ g_slist_free_full (agent->discovery_list,
+ (GDestroyNotify) discovery_free_item);
+ agent->discovery_list = NULL;
+ agent->discovery_unsched_items = 0;
+
+ if (agent->discovery_timer_source != NULL) {
+ g_source_destroy (agent->discovery_timer_source);
+ g_source_unref (agent->discovery_timer_source);
+ agent->discovery_timer_source = NULL;
+ }
+}
+
+/*
+ * Prunes the list of discovery processes for items related
+ * to stream 'stream_id'.
+ *
+ * @return TRUE on success, FALSE on a fatal error
+ */
+void discovery_prune_stream (NiceAgent *agent, guint stream_id)
+{
+ GSList *i;
+
+ for (i = agent->discovery_list; i ; ) {
+ CandidateDiscovery *cand = i->data;
+ GSList *next = i->next;
+
+ if (cand->stream_id == stream_id) {
+ agent->discovery_list = g_slist_remove (agent->discovery_list, cand);
+ discovery_free_item (cand);
+ }
+ i = next;
+ }
+
+ if (agent->discovery_list == NULL) {
+ /* noone using the timer anymore, clean it up */
+ discovery_free (agent);
+ }
+}
+
+/*
+ * Prunes the list of discovery processes for items related
+ * to socket @sock.
+ *
+ * @return TRUE on success, FALSE on a fatal error
+ */
+void discovery_prune_socket (NiceAgent *agent, NiceSocket *sock)
+{
+ GSList *i;
+
+ for (i = agent->discovery_list; i ; ) {
+ CandidateDiscovery *discovery = i->data;
+ GSList *next = i->next;
+
+ if (discovery->nicesock == sock) {
+ agent->discovery_list = g_slist_remove (agent->discovery_list, discovery);
+ discovery_free_item (discovery);
+ }
+ i = next;
+ }
+
+ if (agent->discovery_list == NULL) {
+ /* noone using the timer anymore, clean it up */
+ discovery_free (agent);
+ }
+}
+
+/*
+ * Frees a CandidateRefresh and calls destroy callback if it has been set.
+ */
+void refresh_free (NiceAgent *agent, CandidateRefresh *cand)
+{
+ nice_debug ("Freeing candidate refresh %p", cand);
+
+ agent->refresh_list = g_slist_remove (agent->refresh_list, cand);
+
+ if (cand->timer_source != NULL) {
+ g_source_destroy (cand->timer_source);
+ g_clear_pointer (&cand->timer_source, g_source_unref);
+ }
+
+ if (cand->tick_source) {
+ g_source_destroy (cand->tick_source);
+ g_clear_pointer (&cand->tick_source, g_source_unref);
+ }
+
+ if (cand->destroy_cb) {
+ cand->destroy_cb (cand->destroy_cb_data);
+ }
+
+ g_slice_free (CandidateRefresh, cand);
+}
+
+static gboolean on_refresh_remove_timeout (NiceAgent *agent,
+ CandidateRefresh *cand)
+{
+ switch (stun_timer_refresh (&cand->timer)) {
+ case STUN_USAGE_TIMER_RETURN_TIMEOUT:
+ {
+ StunTransactionId id;
+
+ nice_debug ("TURN deallocate for refresh %p timed out", cand);
+
+ stun_message_id (&cand->stun_message, id);
+ stun_agent_forget_transaction (&cand->stun_agent, id);
+
+ refresh_free (agent, cand);
+ break;
+ }
+ case STUN_USAGE_TIMER_RETURN_RETRANSMIT:
+ nice_debug ("Retransmitting TURN deallocate for refresh %p", cand);
+
+ agent_socket_send (cand->nicesock, &cand->server,
+ stun_message_length (&cand->stun_message), (gchar *)cand->stun_buffer);
+
+ G_GNUC_FALLTHROUGH;
+ case STUN_USAGE_TIMER_RETURN_SUCCESS:
+ agent_timeout_add_with_context (agent, &cand->tick_source,
+ "TURN deallocate retransmission", stun_timer_remainder (&cand->timer),
+ (NiceTimeoutLockedCallback) on_refresh_remove_timeout, cand);
+ break;
+ default:
+ break;
+ }
+
+ return G_SOURCE_REMOVE;
+}
+
+/*
+ * Closes the port associated with the candidate refresh on the TURN server by
+ * sending a refresh request that has zero lifetime. After a response is
+ * received or the request times out, 'cand' gets freed and 'cb' is called.
+ */
+static gboolean refresh_remove_async (NiceAgent *agent, CandidateRefresh *cand,
+ GDestroyNotify cb, gpointer cb_data)
+{
+ uint8_t *username;
+ gsize username_len;
+ uint8_t *password;
+ gsize password_len;
+ size_t buffer_len = 0;
+ StunUsageTurnCompatibility turn_compat = agent_to_turn_compatibility (agent);
+
+ if (cand->disposing) {
+ return FALSE;
+ }
+
+ nice_debug ("Sending request to remove TURN allocation for refresh %p", cand);
+
+ cand->disposing = TRUE;
+
+ if (cand->timer_source != NULL) {
+ g_source_destroy (cand->timer_source);
+ g_source_unref (cand->timer_source);
+ cand->timer_source = NULL;
+ }
+
+ username = (uint8_t *)cand->candidate->turn->username;
+ username_len = (size_t) strlen (cand->candidate->turn->username);
+ password = (uint8_t *)cand->candidate->turn->password;
+ password_len = (size_t) strlen (cand->candidate->turn->password);
+
+ if (turn_compat == STUN_USAGE_TURN_COMPATIBILITY_MSN ||
+ turn_compat == STUN_USAGE_TURN_COMPATIBILITY_OC2007) {
+ username = g_base64_decode ((gchar *)username, &username_len);
+ password = g_base64_decode ((gchar *)password, &password_len);
+ }
+
+ buffer_len = stun_usage_turn_create_refresh (&cand->stun_agent,
+ &cand->stun_message, cand->stun_buffer, sizeof(cand->stun_buffer),
+ cand->stun_resp_msg.buffer == NULL ? NULL : &cand->stun_resp_msg, 0,
+ username, username_len,
+ password, password_len,
+ agent_to_turn_compatibility (agent));
+
+ if (buffer_len > 0) {
+ agent_socket_send (cand->nicesock, &cand->server, buffer_len,
+ (gchar *)cand->stun_buffer);
+
+ stun_timer_start (&cand->timer, agent->stun_initial_timeout,
+ agent->stun_max_retransmissions);
+
+ agent_timeout_add_with_context (agent, &cand->tick_source,
+ "TURN deallocate retransmission", stun_timer_remainder (&cand->timer),
+ (NiceTimeoutLockedCallback) on_refresh_remove_timeout, cand);
+ }
+
+ if (turn_compat == STUN_USAGE_TURN_COMPATIBILITY_MSN ||
+ turn_compat == STUN_USAGE_TURN_COMPATIBILITY_OC2007) {
+ g_free (username);
+ g_free (password);
+ }
+
+ cand->destroy_cb = cb;
+ cand->destroy_cb_data = cb_data;
+
+ return TRUE;
+}
+
+typedef struct {
+ NiceAgent *agent;
+ gpointer user_data;
+ guint items_to_free;
+ NiceTimeoutLockedCallback cb;
+} RefreshPruneAsyncData;
+
+static void on_refresh_removed (RefreshPruneAsyncData *data)
+{
+ if (data->items_to_free == 0 || --(data->items_to_free) == 0) {
+ GSource *timeout_source = NULL;
+ agent_timeout_add_with_context (data->agent, &timeout_source,
+ "Async refresh prune", 0, data->cb, data->user_data);
+
+ g_free (data);
+ }
+}
+
+static void refresh_prune_async (NiceAgent *agent, GSList *refreshes,
+ NiceTimeoutLockedCallback function, gpointer user_data)
+{
+ RefreshPruneAsyncData *data = g_new0 (RefreshPruneAsyncData, 1);
+ GSList *it;
+
+ data->agent = agent;
+ data->user_data = user_data;
+ data->cb = function;
+
+ for (it = refreshes; it; it = it->next) {
+ if (refresh_remove_async (agent, it->data,
+ (GDestroyNotify) on_refresh_removed, data)) {
+ ++data->items_to_free;
+ }
+ }
+
+ if (data->items_to_free == 0) {
+ /* Stream doesn't have any refreshes to remove. Invoke our callback once to
+ * schedule client's callback function. */
+ on_refresh_removed (data);
+ }
+}
+
+void refresh_prune_agent_async (NiceAgent *agent,
+ NiceTimeoutLockedCallback function, gpointer user_data)
+{
+ refresh_prune_async (agent, agent->refresh_list, function, user_data);
+}
+
+/*
+ * Removes the candidate refreshes related to 'stream' and asynchronously
+ * closes the associated port allocations on TURN server. Invokes 'function'
+ * when the process finishes.
+ */
+void refresh_prune_stream_async (NiceAgent *agent, NiceStream *stream,
+ NiceTimeoutLockedCallback function)
+{
+ GSList *refreshes = NULL;
+ GSList *i;
+
+ for (i = agent->refresh_list; i ; i = i->next) {
+ CandidateRefresh *cand = i->data;
+
+ /* Don't free the candidate refresh to the currently selected local candidate
+ * unless the whole pair is being destroyed.
+ */
+ if (cand->stream_id == stream->id) {
+ refreshes = g_slist_append (refreshes, cand);
+ }
+ }
+
+ refresh_prune_async (agent, refreshes, function, stream);
+ g_slist_free (refreshes);
+}
+
+/*
+ * Removes the candidate refreshes related to 'candidate'. The function does not
+ * close any associated port allocations on TURN server. Its purpose is in
+ * situations when an error is detected in socket communication that prevents
+ * sending more requests to the server.
+ */
+void refresh_prune_candidate (NiceAgent *agent, NiceCandidate *candidate)
+{
+ GSList *i;
+
+ for (i = agent->refresh_list; i;) {
+ GSList *next = i->next;
+ CandidateRefresh *refresh = i->data;
+
+ if (refresh->candidate == candidate) {
+ refresh_free(agent, refresh);
+ }
+
+ i = next;
+ }
+}
+
+/*
+ * Removes the candidate refreshes related to 'candidate' and asynchronously
+ * closes the associated port allocations on TURN server. Invokes 'function'
+ * when the process finishes.
+ */
+void refresh_prune_candidate_async (NiceAgent *agent, NiceCandidate *candidate,
+ NiceTimeoutLockedCallback function)
+{
+ GSList *refreshes = NULL;
+ GSList *i;
+
+ for (i = agent->refresh_list; i; i = i->next) {
+ CandidateRefresh *refresh = i->data;
+
+ if (refresh->candidate == candidate) {
+ refreshes = g_slist_append (refreshes, refresh);
+ }
+ }
+
+ refresh_prune_async (agent, refreshes, function, candidate);
+ g_slist_free (refreshes);
+}
+
+/*
+ * Adds a new local candidate. Implements the candidate pruning
+ * defined in ICE spec section 4.1.3 "Eliminating Redundant
+ * Candidates" (ID-19).
+ */
+static gboolean priv_add_local_candidate_pruned (NiceAgent *agent, guint stream_id, NiceComponent *component, NiceCandidate *candidate)
+{
+ GSList *i;
+
+ g_assert (candidate != NULL);
+
+ for (i = component->local_candidates; i ; i = i->next) {
+ NiceCandidate *c = i->data;
+
+ if (nice_address_equal (&c->base_addr, &candidate->base_addr) &&
+ nice_address_equal (&c->addr, &candidate->addr) &&
+ c->transport == candidate->transport) {
+ nice_debug ("Candidate %p (component-id %u) redundant, ignoring.", candidate, component->id);
+ return FALSE;
+ }
+ }
+
+ component->local_candidates = g_slist_append (component->local_candidates,
+ candidate);
+ conn_check_add_for_local_candidate(agent, stream_id, component, candidate);
+
+ return TRUE;
+}
+
+static guint priv_highest_remote_foundation (NiceComponent *component)
+{
+ GSList *i;
+ guint highest = 1;
+ gchar foundation[NICE_CANDIDATE_MAX_FOUNDATION];
+
+ for (highest = 1;; highest++) {
+ gboolean taken = FALSE;
+
+ g_snprintf (foundation, NICE_CANDIDATE_MAX_FOUNDATION, "remote%u",
+ highest);
+ for (i = component->remote_candidates; i; i = i->next) {
+ NiceCandidate *cand = i->data;
+ if (strncmp (foundation, cand->foundation,
+ NICE_CANDIDATE_MAX_FOUNDATION) == 0) {
+ taken = TRUE;
+ break;
+ }
+ }
+ if (!taken)
+ return highest;
+ }
+
+ g_return_val_if_reached (highest);
+}
+
+/* From RFC 5245 section 4.1.3:
+ *
+ * for reflexive and relayed candidates, the STUN or TURN servers
+ * used to obtain them have the same IP address.
+ */
+static gboolean
+priv_compare_turn_servers (TurnServer *turn1, TurnServer *turn2)
+{
+ if (turn1 == turn2)
+ return TRUE;
+ if (turn1 == NULL || turn2 == NULL)
+ return FALSE;
+
+ return nice_address_equal_no_port (&turn1->server, &turn2->server);
+}
+
+/*
+ * Assings a foundation to the candidate.
+ *
+ * Implements the mechanism described in ICE sect
+ * 4.1.1.3 "Computing Foundations" (ID-19).
+ */
+static void priv_assign_foundation (NiceAgent *agent, NiceCandidate *candidate)
+{
+ GSList *i, *j, *k;
+
+ for (i = agent->streams; i; i = i->next) {
+ NiceStream *stream = i->data;
+ for (j = stream->components; j; j = j->next) {
+ NiceComponent *component = j->data;
+ for (k = component->local_candidates; k; k = k->next) {
+ NiceCandidate *n = k->data;
+
+ /* note: candidate must not on the local candidate list */
+ g_assert (candidate != n);
+
+ if (candidate->type == n->type &&
+ candidate->transport == n->transport &&
+ nice_address_equal_no_port (&candidate->base_addr, &n->base_addr) &&
+ (candidate->type != NICE_CANDIDATE_TYPE_RELAYED ||
+ priv_compare_turn_servers (candidate->turn, n->turn)) &&
+ !(agent->compatibility == NICE_COMPATIBILITY_GOOGLE &&
+ n->type == NICE_CANDIDATE_TYPE_RELAYED)) {
+ /* note: currently only one STUN server per stream at a
+ * time is supported, so there is no need to check
+ * for candidates that would otherwise share the
+ * foundation, but have different STUN servers */
+ g_strlcpy (candidate->foundation, n->foundation,
+ NICE_CANDIDATE_MAX_FOUNDATION);
+ if (n->username) {
+ g_free (candidate->username);
+ candidate->username = g_strdup (n->username);
+ }
+ if (n->password) {
+ g_free (candidate->password);
+ candidate->password = g_strdup (n->password);
+ }
+ return;
+ }
+ }
+ }
+ }
+
+ g_snprintf (candidate->foundation, NICE_CANDIDATE_MAX_FOUNDATION,
+ "%u", agent->next_candidate_id++);
+}
+
+static void priv_assign_remote_foundation (NiceAgent *agent, NiceCandidate *candidate)
+{
+ GSList *i, *j, *k;
+ guint next_remote_id;
+ NiceComponent *component = NULL;
+
+ for (i = agent->streams; i; i = i->next) {
+ NiceStream *stream = i->data;
+ for (j = stream->components; j; j = j->next) {
+ NiceComponent *c = j->data;
+
+ if (c->id == candidate->component_id)
+ component = c;
+
+ for (k = c->remote_candidates; k; k = k->next) {
+ NiceCandidate *n = k->data;
+
+ /* note: candidate must not on the remote candidate list */
+ g_assert (candidate != n);
+
+ if (candidate->type == n->type &&
+ candidate->transport == n->transport &&
+ candidate->stream_id == n->stream_id &&
+ nice_address_equal_no_port (&candidate->addr, &n->addr)) {
+ /* note: No need to check for STUN/TURN servers, as these candidate
+ * will always be peer reflexive, never relayed or serve reflexive.
+ */
+ g_strlcpy (candidate->foundation, n->foundation,
+ NICE_CANDIDATE_MAX_FOUNDATION);
+ if (n->username) {
+ g_free (candidate->username);
+ candidate->username = g_strdup (n->username);
+ }
+ if (n->password) {
+ g_free (candidate->password);
+ candidate->password = g_strdup (n->password);
+ }
+ return;
+ }
+ }
+ }
+ }
+
+ if (component) {
+ next_remote_id = priv_highest_remote_foundation (component);
+ g_snprintf (candidate->foundation, NICE_CANDIDATE_MAX_FOUNDATION,
+ "remote%u", next_remote_id);
+ }
+}
+
+
+static
+void priv_generate_candidate_credentials (NiceAgent *agent,
+ NiceCandidate *candidate)
+{
+
+ if (agent->compatibility == NICE_COMPATIBILITY_MSN ||
+ agent->compatibility == NICE_COMPATIBILITY_OC2007) {
+ guchar username[32];
+ guchar password[16];
+
+ g_free (candidate->username);
+ g_free (candidate->password);
+
+ nice_rng_generate_bytes (agent->rng, 32, (gchar *)username);
+ nice_rng_generate_bytes (agent->rng, 16, (gchar *)password);
+
+ candidate->username = g_base64_encode (username, 32);
+ candidate->password = g_base64_encode (password, 16);
+
+ } else if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE) {
+ gchar username[16];
+
+ g_free (candidate->username);
+ g_free (candidate->password);
+ candidate->password = NULL;
+
+ nice_rng_generate_bytes_print (agent->rng, 16, (gchar *)username);
+
+ candidate->username = g_strndup (username, 16);
+ }
+
+
+}
+
+/*
+ * Creates a local host candidate for 'component_id' of stream
+ * 'stream_id'.
+ *
+ * @return pointer to the created candidate, or NULL on error
+ */
+HostCandidateResult discovery_add_local_host_candidate (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ NiceAddress *address,
+ NiceCandidateTransport transport,
+ NiceCandidate **outcandidate)
+{
+ NiceCandidate *candidate;
+ NiceComponent *component;
+ NiceStream *stream;
+ NiceSocket *nicesock = NULL;
+ HostCandidateResult res = HOST_CANDIDATE_FAILED;
+
+ if (!agent_find_component (agent, stream_id, component_id, &stream, &component))
+ return res;
+
+ candidate = nice_candidate_new (NICE_CANDIDATE_TYPE_HOST);
+ candidate->transport = transport;
+ candidate->stream_id = stream_id;
+ candidate->component_id = component_id;
+ candidate->addr = *address;
+ candidate->base_addr = *address;
+ if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE) {
+ candidate->priority = nice_candidate_jingle_priority (candidate);
+ } else if (agent->compatibility == NICE_COMPATIBILITY_MSN ||
+ agent->compatibility == NICE_COMPATIBILITY_OC2007) {
+ candidate->priority = nice_candidate_msn_priority (candidate);
+ } else if (agent->compatibility == NICE_COMPATIBILITY_OC2007R2) {
+ candidate->priority = nice_candidate_ms_ice_priority (candidate,
+ agent->reliable, FALSE);
+ } else {
+ candidate->priority = nice_candidate_ice_priority (candidate,
+ agent->reliable, FALSE);
+ }
+
+ candidate->priority = ensure_unique_priority (stream, component,
+ candidate->priority);
+ priv_generate_candidate_credentials (agent, candidate);
+ priv_assign_foundation (agent, candidate);
+
+ /* note: candidate username and password are left NULL as stream
+ level ufrag/password are used */
+ if (transport == NICE_CANDIDATE_TRANSPORT_UDP) {
+ nicesock = nice_udp_bsd_socket_new (address);
+ } else if (transport == NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE) {
+ nicesock = nice_tcp_active_socket_new (agent->main_context, address);
+ } else if (transport == NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE) {
+ nicesock = nice_tcp_passive_socket_new (agent->main_context, address);
+ } else {
+ /* TODO: Add TCP-SO */
+ }
+ if (!nicesock) {
+ res = HOST_CANDIDATE_CANT_CREATE_SOCKET;
+ goto errors;
+ }
+
+ candidate->sockptr = nicesock;
+ candidate->addr = nicesock->addr;
+ candidate->base_addr = nicesock->addr;
+
+ if (!priv_add_local_candidate_pruned (agent, stream_id, component,
+ candidate)) {
+ res = HOST_CANDIDATE_REDUNDANT;
+ goto errors;
+ }
+
+ _priv_set_socket_tos (agent, nicesock, stream->tos);
+ nice_component_attach_socket (component, nicesock);
+
+ *outcandidate = candidate;
+
+ return HOST_CANDIDATE_SUCCESS;
+
+errors:
+ nice_candidate_free (candidate);
+ if (nicesock)
+ nice_socket_free (nicesock);
+ return res;
+}
+
+/*
+ * Creates a server reflexive candidate for 'component_id' of stream
+ * 'stream_id'.
+ *
+ * @return pointer to the created candidate, or NULL on error
+ */
+NiceCandidate*
+discovery_add_server_reflexive_candidate (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ NiceAddress *address,
+ NiceCandidateTransport transport,
+ NiceSocket *base_socket,
+ gboolean nat_assisted)
+{
+ NiceCandidate *candidate;
+ NiceComponent *component;
+ NiceStream *stream;
+ gboolean result = FALSE;
+
+ if (!agent_find_component (agent, stream_id, component_id, &stream, &component))
+ return NULL;
+
+ candidate = nice_candidate_new (NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE);
+ candidate->transport = transport;
+ candidate->stream_id = stream_id;
+ candidate->component_id = component_id;
+ candidate->addr = *address;
+
+ /* step: link to the base candidate+socket */
+ candidate->sockptr = base_socket;
+ candidate->base_addr = base_socket->addr;
+
+ if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE) {
+ candidate->priority = nice_candidate_jingle_priority (candidate);
+ } else if (agent->compatibility == NICE_COMPATIBILITY_MSN ||
+ agent->compatibility == NICE_COMPATIBILITY_OC2007) {
+ candidate->priority = nice_candidate_msn_priority (candidate);
+ } else if (agent->compatibility == NICE_COMPATIBILITY_OC2007R2) {
+ candidate->priority = nice_candidate_ms_ice_priority (candidate,
+ agent->reliable, nat_assisted);
+ } else {
+ candidate->priority = nice_candidate_ice_priority (candidate,
+ agent->reliable, nat_assisted);
+ }
+
+ candidate->priority = ensure_unique_priority (stream, component,
+ candidate->priority);
+ priv_generate_candidate_credentials (agent, candidate);
+ priv_assign_foundation (agent, candidate);
+
+ result = priv_add_local_candidate_pruned (agent, stream_id, component, candidate);
+ if (result) {
+ agent_signal_new_candidate (agent, candidate);
+ }
+ else {
+ /* error: duplicate candidate */
+ nice_candidate_free (candidate), candidate = NULL;
+ }
+
+ return candidate;
+}
+
+/*
+ * Creates a server reflexive candidate for 'component_id' of stream
+ * 'stream_id' for each TCP_PASSIVE and TCP_ACTIVE candidates for each
+ * base address.
+ *
+ * @return pointer to the created candidate, or NULL on error
+ */
+void
+discovery_discover_tcp_server_reflexive_candidates (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ NiceAddress *address,
+ NiceSocket *base_socket)
+{
+ NiceComponent *component;
+ NiceStream *stream;
+ NiceAddress base_addr = base_socket->addr;
+ GSList *i;
+
+ if (!agent_find_component (agent, stream_id, component_id, &stream, &component))
+ return;
+
+ nice_address_set_port (&base_addr, 0);
+ for (i = component->local_candidates; i; i = i ->next) {
+ NiceCandidate *c = i->data;
+ NiceAddress caddr;
+
+ caddr = c->addr;
+ nice_address_set_port (&caddr, 0);
+ if (agent->force_relay == FALSE &&
+ c->transport != NICE_CANDIDATE_TRANSPORT_UDP &&
+ c->type == NICE_CANDIDATE_TYPE_HOST &&
+ nice_address_equal (&base_addr, &caddr)) {
+ nice_address_set_port (address, nice_address_get_port (&c->addr));
+ discovery_add_server_reflexive_candidate (
+ agent,
+ stream_id,
+ component_id,
+ address,
+ c->transport,
+ c->sockptr,
+ FALSE);
+ }
+ }
+}
+
+/*
+ * Creates a server reflexive candidate for 'component_id' of stream
+ * 'stream_id'.
+ *
+ * @return pointer to the created candidate, or NULL on error
+ */
+NiceCandidate*
+discovery_add_relay_candidate (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ NiceAddress *address,
+ NiceCandidateTransport transport,
+ NiceSocket *base_socket,
+ TurnServer *turn)
+{
+ NiceCandidate *candidate;
+ NiceComponent *component;
+ NiceStream *stream;
+ NiceSocket *relay_socket = NULL;
+
+ if (!agent_find_component (agent, stream_id, component_id, &stream, &component))
+ return NULL;
+
+ candidate = nice_candidate_new (NICE_CANDIDATE_TYPE_RELAYED);
+ candidate->transport = transport;
+ candidate->stream_id = stream_id;
+ candidate->component_id = component_id;
+ candidate->addr = *address;
+ candidate->turn = turn_server_ref (turn);
+
+ /* step: link to the base candidate+socket */
+ relay_socket = nice_udp_turn_socket_new (agent->main_context, address,
+ base_socket, &turn->server,
+ turn->username, turn->password,
+ agent_to_turn_socket_compatibility (agent));
+ if (!relay_socket)
+ goto errors;
+
+ candidate->sockptr = relay_socket;
+ candidate->base_addr = base_socket->addr;
+
+ if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE) {
+ candidate->priority = nice_candidate_jingle_priority (candidate);
+ } else if (agent->compatibility == NICE_COMPATIBILITY_MSN ||
+ agent->compatibility == NICE_COMPATIBILITY_OC2007) {
+ candidate->priority = nice_candidate_msn_priority (candidate);
+ } else if (agent->compatibility == NICE_COMPATIBILITY_OC2007R2) {
+ candidate->priority = nice_candidate_ms_ice_priority (candidate,
+ agent->reliable, FALSE);
+ } else {
+ candidate->priority = nice_candidate_ice_priority (candidate,
+ agent->reliable, FALSE);
+ }
+
+ candidate->priority = ensure_unique_priority (stream, component,
+ candidate->priority);
+ priv_generate_candidate_credentials (agent, candidate);
+
+ /* Google uses the turn username as the candidate username */
+ if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE) {
+ g_free (candidate->username);
+ candidate->username = g_strdup (turn->username);
+ }
+
+ priv_assign_foundation (agent, candidate);
+
+ if (!priv_add_local_candidate_pruned (agent, stream_id, component, candidate))
+ goto errors;
+
+ nice_component_attach_socket (component, relay_socket);
+ agent_signal_new_candidate (agent, candidate);
+
+ return candidate;
+
+errors:
+ nice_candidate_free (candidate);
+ if (relay_socket)
+ nice_socket_free (relay_socket);
+ return NULL;
+}
+
+/*
+ * Creates a peer reflexive candidate for 'component_id' of stream
+ * 'stream_id'.
+ *
+ * @return pointer to the created candidate, or NULL on error
+ */
+NiceCandidate*
+discovery_add_peer_reflexive_candidate (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ NiceAddress *address,
+ NiceSocket *base_socket,
+ NiceCandidate *local,
+ NiceCandidate *remote)
+{
+ NiceCandidate *candidate;
+ NiceComponent *component;
+ NiceStream *stream;
+ gboolean result;
+
+ if (!agent_find_component (agent, stream_id, component_id, &stream, &component))
+ return NULL;
+
+ candidate = nice_candidate_new (NICE_CANDIDATE_TYPE_PEER_REFLEXIVE);
+ if (local)
+ candidate->transport = local->transport;
+ else if (remote)
+ candidate->transport = conn_check_match_transport (remote->transport);
+ else {
+ if (base_socket->type == NICE_SOCKET_TYPE_UDP_BSD ||
+ base_socket->type == NICE_SOCKET_TYPE_UDP_TURN)
+ candidate->transport = NICE_CANDIDATE_TRANSPORT_UDP;
+ else
+ candidate->transport = NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE;
+ }
+ candidate->stream_id = stream_id;
+ candidate->component_id = component_id;
+ candidate->addr = *address;
+ candidate->sockptr = base_socket;
+ candidate->base_addr = base_socket->addr;
+
+ if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE) {
+ candidate->priority = nice_candidate_jingle_priority (candidate);
+ } else if (agent->compatibility == NICE_COMPATIBILITY_MSN ||
+ agent->compatibility == NICE_COMPATIBILITY_OC2007) {
+ candidate->priority = nice_candidate_msn_priority (candidate);
+ } else if (agent->compatibility == NICE_COMPATIBILITY_OC2007R2) {
+ candidate->priority = nice_candidate_ms_ice_priority (candidate,
+ agent->reliable, FALSE);
+ } else {
+ candidate->priority = nice_candidate_ice_priority (candidate,
+ agent->reliable, FALSE);
+ }
+
+ candidate->priority = ensure_unique_priority (stream, component,
+ candidate->priority);
+ priv_assign_foundation (agent, candidate);
+
+ if ((agent->compatibility == NICE_COMPATIBILITY_MSN ||
+ agent->compatibility == NICE_COMPATIBILITY_OC2007) &&
+ remote && local) {
+ guchar *new_username = NULL;
+ guchar *decoded_local = NULL;
+ guchar *decoded_remote = NULL;
+ gsize local_size;
+ gsize remote_size;
+ g_free(candidate->username);
+ g_free(candidate->password);
+
+ decoded_local = g_base64_decode (local->username, &local_size);
+ decoded_remote = g_base64_decode (remote->username, &remote_size);
+
+ new_username = g_new0(guchar, local_size + remote_size);
+ memcpy(new_username, decoded_local, local_size);
+ memcpy(new_username + local_size, decoded_remote, remote_size);
+
+ candidate->username = g_base64_encode (new_username, local_size + remote_size);
+ g_free(new_username);
+ g_free(decoded_local);
+ g_free(decoded_remote);
+
+ candidate->password = g_strdup(local->password);
+ } else if (local) {
+ g_free(candidate->username);
+ g_free(candidate->password);
+
+ candidate->username = g_strdup(local->username);
+ candidate->password = g_strdup(local->password);
+ }
+
+ result = priv_add_local_candidate_pruned (agent, stream_id, component, candidate);
+ if (result != TRUE) {
+ /* error: memory allocation, or duplicate candidate */
+ nice_candidate_free (candidate), candidate = NULL;
+ }
+
+ return candidate;
+}
+
+
+/*
+ * Adds a new peer reflexive candidate to the list of known
+ * remote candidates. The candidate is however not paired with
+ * existing local candidates.
+ *
+ * See ICE sect 7.2.1.3 "Learning Peer Reflexive Candidates" (ID-19).
+ *
+ * @return pointer to the created candidate, or NULL on error
+ */
+NiceCandidate *discovery_learn_remote_peer_reflexive_candidate (
+ NiceAgent *agent,
+ NiceStream *stream,
+ NiceComponent *component,
+ guint32 priority,
+ const NiceAddress *remote_address,
+ NiceSocket *nicesock,
+ NiceCandidate *local,
+ NiceCandidate *remote)
+{
+ NiceCandidate *candidate;
+
+ candidate = nice_candidate_new (NICE_CANDIDATE_TYPE_PEER_REFLEXIVE);
+
+ candidate->addr = *remote_address;
+ candidate->base_addr = *remote_address;
+ if (remote)
+ candidate->transport = remote->transport;
+ else if (local)
+ candidate->transport = conn_check_match_transport (local->transport);
+ else {
+ if (nicesock->type == NICE_SOCKET_TYPE_UDP_BSD ||
+ nicesock->type == NICE_SOCKET_TYPE_UDP_TURN)
+ candidate->transport = NICE_CANDIDATE_TRANSPORT_UDP;
+ else
+ candidate->transport = NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE;
+ }
+ candidate->sockptr = nicesock;
+ candidate->stream_id = stream->id;
+ candidate->component_id = component->id;
+
+ /* if the check didn't contain the PRIORITY attribute, then the priority will
+ * be 0, which is invalid... */
+ if (priority != 0) {
+ candidate->priority = priority;
+ } else if (agent->compatibility == NICE_COMPATIBILITY_GOOGLE) {
+ candidate->priority = nice_candidate_jingle_priority (candidate);
+ } else if (agent->compatibility == NICE_COMPATIBILITY_MSN ||
+ agent->compatibility == NICE_COMPATIBILITY_OC2007) {
+ candidate->priority = nice_candidate_msn_priority (candidate);
+ } else if (agent->compatibility == NICE_COMPATIBILITY_OC2007R2) {
+ candidate->priority = nice_candidate_ms_ice_priority (candidate,
+ agent->reliable, FALSE);
+ } else {
+ candidate->priority = nice_candidate_ice_priority (candidate,
+ agent->reliable, FALSE);
+ }
+
+ priv_assign_remote_foundation (agent, candidate);
+
+ if ((agent->compatibility == NICE_COMPATIBILITY_MSN ||
+ agent->compatibility == NICE_COMPATIBILITY_OC2007) &&
+ remote && local) {
+ guchar *new_username = NULL;
+ guchar *decoded_local = NULL;
+ guchar *decoded_remote = NULL;
+ gsize local_size;
+ gsize remote_size;
+ g_free(candidate->username);
+ g_free (candidate->password);
+
+ decoded_local = g_base64_decode (local->username, &local_size);
+ decoded_remote = g_base64_decode (remote->username, &remote_size);
+
+ new_username = g_new0(guchar, local_size + remote_size);
+ memcpy(new_username, decoded_remote, remote_size);
+ memcpy(new_username + remote_size, decoded_local, local_size);
+
+ candidate->username = g_base64_encode (new_username, local_size + remote_size);
+ g_free(new_username);
+ g_free(decoded_local);
+ g_free(decoded_remote);
+
+ candidate->password = g_strdup(remote->password);
+ } else if (remote) {
+ g_free (candidate->username);
+ g_free (candidate->password);
+ candidate->username = g_strdup(remote->username);
+ candidate->password = g_strdup(remote->password);
+ }
+
+ /* note: candidate username and password are left NULL as stream
+ level ufrag/password are used */
+
+ component->remote_candidates = g_slist_append (component->remote_candidates,
+ candidate);
+
+ agent_signal_new_remote_candidate (agent, candidate);
+
+ return candidate;
+}
+
+/*
+ * Timer callback that handles scheduling new candidate discovery
+ * processes (paced by the Ta timer), and handles running of the
+ * existing discovery processes.
+ *
+ * This function is designed for the g_timeout_add() interface.
+ *
+ * @return will return FALSE when no more pending timers.
+ */
+static gboolean priv_discovery_tick_unlocked (NiceAgent *agent)
+{
+ CandidateDiscovery *cand;
+ GSList *i;
+ int not_done = 0; /* note: track whether to continue timer */
+ size_t buffer_len = 0;
+
+ {
+ static int tick_counter = 0;
+ if (tick_counter++ % 50 == 0)
+ nice_debug ("Agent %p : discovery tick #%d with list %p (1)", agent, tick_counter, agent->discovery_list);
+ }
+
+ for (i = agent->discovery_list; i ; i = i->next) {
+ cand = i->data;
+
+ if (cand->pending != TRUE) {
+ cand->pending = TRUE;
+
+ if (agent->discovery_unsched_items)
+ --agent->discovery_unsched_items;
+
+ if (nice_debug_is_enabled ()) {
+ gchar tmpbuf[INET6_ADDRSTRLEN];
+ nice_address_to_string (&cand->server, tmpbuf);
+ nice_debug ("Agent %p : discovery - scheduling cand type %u addr %s.",
+ agent, cand->type, tmpbuf);
+ }
+ if (nice_address_is_valid (&cand->server) &&
+ (cand->type == NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE ||
+ cand->type == NICE_CANDIDATE_TYPE_RELAYED)) {
+ NiceComponent *component;
+
+ if (agent_find_component (agent, cand->stream_id,
+ cand->component_id, NULL, &component) &&
+ (component->state == NICE_COMPONENT_STATE_DISCONNECTED ||
+ component->state == NICE_COMPONENT_STATE_FAILED))
+ agent_signal_component_state_change (agent,
+ cand->stream_id,
+ cand->component_id,
+ NICE_COMPONENT_STATE_GATHERING);
+
+ if (cand->type == NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE) {
+ buffer_len = stun_usage_bind_create (&cand->stun_agent,
+ &cand->stun_message, cand->stun_buffer, sizeof(cand->stun_buffer));
+ } else if (cand->type == NICE_CANDIDATE_TYPE_RELAYED) {
+ uint8_t *username = (uint8_t *)cand->turn->username;
+ gsize username_len = strlen (cand->turn->username);
+ uint8_t *password = (uint8_t *)cand->turn->password;
+ gsize password_len = strlen (cand->turn->password);
+ StunUsageTurnCompatibility turn_compat =
+ agent_to_turn_compatibility (agent);
+
+ if (turn_compat == STUN_USAGE_TURN_COMPATIBILITY_MSN ||
+ turn_compat == STUN_USAGE_TURN_COMPATIBILITY_OC2007) {
+ username = g_base64_decode ((gchar *)username, &username_len);
+ password = g_base64_decode ((gchar *)password, &password_len);
+ }
+
+ buffer_len = stun_usage_turn_create (&cand->stun_agent,
+ &cand->stun_message, cand->stun_buffer, sizeof(cand->stun_buffer),
+ cand->stun_resp_msg.buffer == NULL ? NULL : &cand->stun_resp_msg,
+ STUN_USAGE_TURN_REQUEST_PORT_NORMAL,
+ -1, -1,
+ username, username_len,
+ password, password_len,
+ turn_compat);
+
+ if (turn_compat == STUN_USAGE_TURN_COMPATIBILITY_MSN ||
+ turn_compat == STUN_USAGE_TURN_COMPATIBILITY_OC2007) {
+ g_free (username);
+ g_free (password);
+ }
+ }
+
+ if (buffer_len > 0) {
+ if (nice_socket_is_reliable (cand->nicesock)) {
+ stun_timer_start_reliable (&cand->timer, agent->stun_reliable_timeout);
+ } else {
+ stun_timer_start (&cand->timer,
+ agent->stun_initial_timeout,
+ agent->stun_max_retransmissions);
+ }
+
+ /* send the conncheck */
+ agent_socket_send (cand->nicesock, &cand->server,
+ buffer_len, (gchar *)cand->stun_buffer);
+
+ /* case: success, start waiting for the result */
+ g_get_current_time (&cand->next_tick);
+
+ } else {
+ /* case: error in starting discovery, start the next discovery */
+ cand->done = TRUE;
+ cand->stun_message.buffer = NULL;
+ cand->stun_message.buffer_len = 0;
+ continue;
+ }
+ }
+ else
+ /* allocate relayed candidates */
+ g_assert_not_reached ();
+
+ ++not_done; /* note: new discovery scheduled */
+ }
+
+ if (cand->done != TRUE) {
+ GTimeVal now;
+
+ g_get_current_time (&now);
+
+ if (cand->stun_message.buffer == NULL) {
+ nice_debug ("Agent %p : STUN discovery was cancelled, marking discovery done.", agent);
+ cand->done = TRUE;
+ }
+ else if (priv_timer_expired (&cand->next_tick, &now)) {
+ switch (stun_timer_refresh (&cand->timer)) {
+ case STUN_USAGE_TIMER_RETURN_TIMEOUT:
+ {
+ /* Time out */
+ /* case: error, abort processing */
+ StunTransactionId id;
+
+ stun_message_id (&cand->stun_message, id);
+ stun_agent_forget_transaction (&cand->stun_agent, id);
+
+ cand->done = TRUE;
+ cand->stun_message.buffer = NULL;
+ cand->stun_message.buffer_len = 0;
+ nice_debug ("Agent %p : bind discovery timed out, aborting discovery item.", agent);
+ break;
+ }
+ case STUN_USAGE_TIMER_RETURN_RETRANSMIT:
+ {
+ /* case: not ready complete, so schedule next timeout */
+ unsigned int timeout = stun_timer_remainder (&cand->timer);
+
+ stun_debug ("STUN transaction retransmitted (timeout %dms).",
+ timeout);
+
+ /* retransmit */
+ agent_socket_send (cand->nicesock, &cand->server,
+ stun_message_length (&cand->stun_message),
+ (gchar *)cand->stun_buffer);
+
+ /* note: convert from milli to microseconds for g_time_val_add() */
+ cand->next_tick = now;
+ g_time_val_add (&cand->next_tick, timeout * 1000);
+
+ ++not_done; /* note: retry later */
+ break;
+ }
+ case STUN_USAGE_TIMER_RETURN_SUCCESS:
+ {
+ unsigned int timeout = stun_timer_remainder (&cand->timer);
+
+ cand->next_tick = now;
+ g_time_val_add (&cand->next_tick, timeout * 1000);
+
+ ++not_done; /* note: retry later */
+ break;
+ }
+ default:
+ /* Nothing to do. */
+ break;
+ }
+
+ } else {
+ ++not_done; /* note: discovery not expired yet */
+ }
+ }
+ }
+
+ if (not_done == 0) {
+ nice_debug ("Agent %p : Candidate gathering FINISHED, stopping discovery timer.", agent);
+
+ discovery_free (agent);
+
+ agent_gathering_done (agent);
+
+ /* note: no pending timers, return FALSE to stop timer */
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean priv_discovery_tick_agent_locked (NiceAgent *agent,
+ gpointer pointer)
+{
+ gboolean ret;
+
+ ret = priv_discovery_tick_unlocked (agent);
+ if (ret == FALSE) {
+ if (agent->discovery_timer_source != NULL) {
+ g_source_destroy (agent->discovery_timer_source);
+ g_source_unref (agent->discovery_timer_source);
+ agent->discovery_timer_source = NULL;
+ }
+ }
+
+ return ret;
+}
+
+/*
+ * Initiates the candidate discovery process by starting
+ * the necessary timers.
+ *
+ * @pre agent->discovery_list != NULL // unsched discovery items available
+ */
+void discovery_schedule (NiceAgent *agent)
+{
+ g_assert (agent->discovery_list != NULL);
+
+ if (agent->discovery_unsched_items > 0) {
+
+ if (agent->discovery_timer_source == NULL) {
+ /* step: run first iteration immediately */
+ gboolean res = priv_discovery_tick_unlocked (agent);
+ if (res == TRUE) {
+ agent_timeout_add_with_context (agent, &agent->discovery_timer_source,
+ "Candidate discovery tick", agent->timer_ta,
+ priv_discovery_tick_agent_locked, NULL);
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2007-2009 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ * Kai Vehmanen, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef _NICE_DISCOVERY_H
+#define _NICE_DISCOVERY_H
+
+/* note: this is a private header to libnice */
+
+#include "stream.h"
+#include "agent.h"
+
+typedef struct
+{
+ NiceCandidateType type; /* candidate type STUN or TURN */
+ NiceSocket *nicesock; /* XXX: should be taken from local cand: existing socket to use */
+ NiceAddress server; /* STUN/TURN server address */
+ GTimeVal next_tick; /* next tick timestamp */
+ gboolean pending; /* is discovery in progress? */
+ gboolean done; /* is discovery complete? */
+ guint stream_id;
+ guint component_id;
+ TurnServer *turn;
+ StunAgent stun_agent;
+ StunTimer timer;
+ uint8_t stun_buffer[STUN_MAX_MESSAGE_SIZE_IPV6];
+ StunMessage stun_message;
+ uint8_t stun_resp_buffer[STUN_MAX_MESSAGE_SIZE];
+ StunMessage stun_resp_msg;
+} CandidateDiscovery;
+
+typedef struct
+{
+ NiceSocket *nicesock; /* existing socket to use */
+ NiceAddress server; /* STUN/TURN server address */
+ NiceCandidate *candidate; /* candidate to refresh */
+ guint stream_id;
+ guint component_id;
+ StunAgent stun_agent;
+ GSource *timer_source;
+ GSource *tick_source;
+ StunTimer timer;
+ uint8_t stun_buffer[STUN_MAX_MESSAGE_SIZE_IPV6];
+ StunMessage stun_message;
+ uint8_t stun_resp_buffer[STUN_MAX_MESSAGE_SIZE];
+ StunMessage stun_resp_msg;
+
+ gboolean disposing;
+ GDestroyNotify destroy_cb;
+ gpointer destroy_cb_data;
+} CandidateRefresh;
+
+void refresh_free (NiceAgent *agent, CandidateRefresh *refresh);
+void refresh_prune_agent_async (NiceAgent *agent,
+ NiceTimeoutLockedCallback function, gpointer user_data);
+void refresh_prune_stream_async (NiceAgent *agent, NiceStream *stream,
+ NiceTimeoutLockedCallback function);
+void refresh_prune_candidate (NiceAgent *agent, NiceCandidate *candidate);
+void refresh_prune_candidate_async (NiceAgent *agent, NiceCandidate *candidate,
+ NiceTimeoutLockedCallback function);
+
+
+void discovery_free (NiceAgent *agent);
+void discovery_prune_stream (NiceAgent *agent, guint stream_id);
+void discovery_prune_socket (NiceAgent *agent, NiceSocket *sock);
+void discovery_schedule (NiceAgent *agent);
+
+typedef enum {
+ HOST_CANDIDATE_SUCCESS,
+ HOST_CANDIDATE_FAILED,
+ HOST_CANDIDATE_CANT_CREATE_SOCKET,
+ HOST_CANDIDATE_REDUNDANT
+} HostCandidateResult;
+
+HostCandidateResult
+discovery_add_local_host_candidate (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ NiceAddress *address,
+ NiceCandidateTransport transport,
+ NiceCandidate **candidate);
+
+NiceCandidate*
+discovery_add_relay_candidate (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ NiceAddress *address,
+ NiceCandidateTransport transport,
+ NiceSocket *base_socket,
+ TurnServer *turn);
+
+NiceCandidate*
+discovery_add_server_reflexive_candidate (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ NiceAddress *address,
+ NiceCandidateTransport transport,
+ NiceSocket *base_socket,
+ gboolean nat_assisted);
+
+void
+discovery_discover_tcp_server_reflexive_candidates (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ NiceAddress *address,
+ NiceSocket *base_socket);
+
+NiceCandidate*
+discovery_add_peer_reflexive_candidate (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ NiceAddress *address,
+ NiceSocket *base_socket,
+ NiceCandidate *local,
+ NiceCandidate *remote);
+
+NiceCandidate *
+discovery_learn_remote_peer_reflexive_candidate (
+ NiceAgent *agent,
+ NiceStream *stream,
+ NiceComponent *component,
+ guint32 priority,
+ const NiceAddress *remote_address,
+ NiceSocket *udp_socket,
+ NiceCandidate *local,
+ NiceCandidate *remote);
+
+#endif /*_NICE_CONNCHECK_H */
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2010, 2013 Collabora Ltd.
+ * Contact: Youness Alaoui
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ * Philip Withnall, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+/***
+ * SECTION:nice_input_stream
+ * @short_description: #GInputStream implementation for libnice
+ * @see_also: #NiceAgent
+ * @include: inputstream.h
+ * @stability: Stable
+ *
+ * #NiceInputStream is a #GInputStream wrapper for a single reliable stream and
+ * component of a #NiceAgent. Given an existing reliable #NiceAgent, plus the
+ * IDs of an existing stream and component in the agent, it will provide a
+ * streaming input interface for reading from the given component.
+ *
+ * A single #NiceInputStream can only be used with a single agent, stream and
+ * component triple, and will be closed as soon as that stream is removed from
+ * the agent (e.g. if nice_agent_remove_stream() is called from another thread).
+ * If g_input_stream_close() is called on a #NiceInputStream, the input stream
+ * and underlying #NiceAgent stream will be closed, but the underlying stream
+ * will not be removed. Use nice_agent_remove_stream() to do that.
+ *
+ * Since: 0.1.5
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <errno.h>
+
+#include "inputstream.h"
+#include "agent-priv.h"
+
+static void streams_removed_cb (NiceAgent *agent, guint *stream_ids,
+ gpointer user_data);
+static void nice_input_stream_init_pollable (
+ GPollableInputStreamInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (NiceInputStream,
+ nice_input_stream, G_TYPE_INPUT_STREAM,
+ G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_INPUT_STREAM,
+ nice_input_stream_init_pollable));
+
+enum
+{
+ PROP_AGENT = 1,
+ PROP_STREAM_ID,
+ PROP_COMPONENT_ID,
+};
+
+struct _NiceInputStreamPrivate
+{
+ GWeakRef/*<NiceAgent>*/ agent_ref;
+ guint stream_id;
+ guint component_id;
+};
+
+static void nice_input_stream_dispose (GObject *object);
+static void nice_input_stream_get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec);
+static void nice_input_stream_set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec);
+static gssize nice_input_stream_read (GInputStream *stream, void *buffer,
+ gsize count, GCancellable *cancellable, GError **error);
+static gboolean nice_input_stream_close (GInputStream *stream,
+ GCancellable *cancellable, GError **error);
+static gboolean nice_input_stream_is_readable (GPollableInputStream *stream);
+static gssize nice_input_stream_read_nonblocking (GPollableInputStream *stream,
+ void *buffer, gsize count, GError **error);
+static GSource *nice_input_stream_create_source (GPollableInputStream *stream,
+ GCancellable *cancellable);
+
+static void
+nice_input_stream_class_init (NiceInputStreamClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GInputStreamClass *stream_class = G_INPUT_STREAM_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (NiceInputStreamPrivate));
+
+ gobject_class->set_property = nice_input_stream_set_property;
+ gobject_class->get_property = nice_input_stream_get_property;
+ gobject_class->dispose = nice_input_stream_dispose;
+
+ stream_class->read_fn = nice_input_stream_read;
+ stream_class->close_fn = nice_input_stream_close;
+
+ /***
+ * NiceInputStream:agent:
+ *
+ * The #NiceAgent to wrap with an input stream. This must be an existing
+ * reliable agent.
+ *
+ * A reference is not held on the #NiceAgent. If the agent is destroyed before
+ * the #NiceInputStream, %G_IO_ERROR_CLOSED will be returned for all
+ * subsequent operations on the stream.
+ *
+ * Since: 0.1.5
+ */
+ g_object_class_install_property (gobject_class, PROP_AGENT,
+ g_param_spec_object ("agent",
+ "NiceAgent",
+ "The underlying NiceAgent",
+ NICE_TYPE_AGENT,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ /***
+ * NiceInputStream:stream-id:
+ *
+ * ID of the stream to use in the #NiceInputStream:agent.
+ *
+ * Since: 0.1.5
+ */
+ g_object_class_install_property (gobject_class, PROP_STREAM_ID,
+ g_param_spec_uint (
+ "stream-id",
+ "Agent’s stream ID",
+ "The ID of the agent’s stream to wrap.",
+ 0, G_MAXUINT,
+ 0,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ /***
+ * NiceInputStream:component-id:
+ *
+ * ID of the component to use in the #NiceInputStream:agent.
+ *
+ * Since: 0.1.5
+ */
+ g_object_class_install_property (gobject_class, PROP_COMPONENT_ID,
+ g_param_spec_uint (
+ "component-id",
+ "Agent’s component ID",
+ "The ID of the agent’s component to wrap.",
+ 0, G_MAXUINT,
+ 0,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+}
+
+static void
+nice_input_stream_dispose (GObject *object)
+{
+ NiceInputStream *self = NICE_INPUT_STREAM (object);
+ NiceAgent *agent;
+
+ /* Ensure the stream is closed first, otherwise the agent can’t be found in
+ * the close handler called by the parent implementation. */
+ if (!g_input_stream_is_closed (G_INPUT_STREAM (object)))
+ g_input_stream_close (G_INPUT_STREAM (object), NULL, NULL);
+
+ agent = g_weak_ref_get (&self->priv->agent_ref);
+ if (agent != NULL) {
+ g_signal_handlers_disconnect_by_func (agent, streams_removed_cb, self);
+ g_object_unref (agent);
+ }
+
+ g_weak_ref_clear (&self->priv->agent_ref);
+
+ G_OBJECT_CLASS (nice_input_stream_parent_class)->dispose (object);
+}
+
+static void
+nice_input_stream_get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec)
+{
+ NiceInputStream *self = NICE_INPUT_STREAM (object);
+
+ switch (prop_id) {
+ case PROP_AGENT:
+ g_value_take_object (value, g_weak_ref_get (&self->priv->agent_ref));
+ break;
+ case PROP_STREAM_ID:
+ g_value_set_uint (value, self->priv->stream_id);
+ break;
+ case PROP_COMPONENT_ID:
+ g_value_set_uint (value, self->priv->component_id);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+nice_input_stream_set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ NiceInputStream *self = NICE_INPUT_STREAM (object);
+
+ switch (prop_id) {
+ case PROP_AGENT: {
+ /* Construct only. */
+ NiceAgent *agent = g_value_dup_object (value);
+ g_weak_ref_set (&self->priv->agent_ref, agent);
+
+ /* agent may be NULL if the stream is being constructed by
+ * nice_io_stream_get_input_stream() after the NiceIOStream’s agent has
+ * already been finalised. */
+ if (agent != NULL) {
+ g_signal_connect (agent, "streams-removed",
+ (GCallback) streams_removed_cb, self);
+ g_object_unref (agent);
+ }
+
+ break;
+ }
+ case PROP_STREAM_ID:
+ /* Construct only. */
+ self->priv->stream_id = g_value_get_uint (value);
+ break;
+ case PROP_COMPONENT_ID:
+ /* Construct only. */
+ self->priv->component_id = g_value_get_uint (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+nice_input_stream_init (NiceInputStream *stream)
+{
+ stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (stream, NICE_TYPE_INPUT_STREAM,
+ NiceInputStreamPrivate);
+
+ g_weak_ref_init (&stream->priv->agent_ref, NULL);
+}
+
+static void
+nice_input_stream_init_pollable (GPollableInputStreamInterface *iface)
+{
+ iface->is_readable = nice_input_stream_is_readable;
+ iface->read_nonblocking = nice_input_stream_read_nonblocking;
+ iface->create_source = nice_input_stream_create_source;
+}
+
+/***
+ * nice_input_stream_new:
+ * @agent: A #NiceAgent
+ * @stream_id: The ID of the agent’s stream to wrap
+ * @component_id: The ID of the agent’s component to wrap
+ *
+ * Create a new #NiceInputStream wrapping the given stream/component from
+ * @agent, which must be a reliable #NiceAgent.
+ *
+ * The constructed #NiceInputStream will not hold a reference to @agent. If
+ * @agent is destroyed before the input stream, %G_IO_ERROR_CLOSED will be
+ * returned for all subsequent operations on the stream.
+ *
+ * Returns: The new #NiceInputStream object
+ *
+ * Since: 0.1.5
+ */
+NiceInputStream *
+nice_input_stream_new (NiceAgent *agent, guint stream_id, guint component_id)
+{
+ g_return_val_if_fail (NICE_IS_AGENT (agent), NULL);
+ g_return_val_if_fail (stream_id >= 1, NULL);
+ g_return_val_if_fail (component_id >= 1, NULL);
+
+ return g_object_new (NICE_TYPE_INPUT_STREAM,
+ "agent", agent,
+ "stream-id", stream_id,
+ "component-id", component_id,
+ NULL);
+}
+
+static gssize
+nice_input_stream_read (GInputStream *stream, void *buffer, gsize count,
+ GCancellable *cancellable, GError **error)
+{
+ NiceInputStreamPrivate *priv = NICE_INPUT_STREAM (stream)->priv;
+ NiceAgent *agent; /* owned */
+ gssize len;
+
+ /* Closed streams are not readable. */
+ if (g_input_stream_is_closed (stream)) {
+ return 0;
+ }
+
+ /* Has the agent disappeared? */
+ agent = g_weak_ref_get (&priv->agent_ref);
+ if (agent == NULL) {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
+ "Stream is closed due to the NiceAgent being finalised.");
+ return -1;
+ }
+
+ len = nice_agent_recv (agent, priv->stream_id, priv->component_id,
+ buffer, count, cancellable, error);
+
+ g_object_unref (agent);
+
+ return len;
+}
+
+static gboolean
+nice_input_stream_close (GInputStream *stream, GCancellable *cancellable,
+ GError **error)
+{
+ NiceInputStreamPrivate *priv = NICE_INPUT_STREAM (stream)->priv;
+ NiceComponent *component = NULL;
+ NiceStream *_stream = NULL;
+ NiceAgent *agent; /* owned */
+
+ /* Has the agent disappeared? */
+ agent = g_weak_ref_get (&priv->agent_ref);
+ if (agent == NULL)
+ return TRUE;
+
+ agent_lock (agent);
+
+ /* Shut down the read side of the pseudo-TCP stream, if it still exists. */
+ if (agent_find_component (agent, priv->stream_id, priv->component_id,
+ &_stream, &component) && agent->reliable &&
+ !pseudo_tcp_socket_is_closed (component->tcp)) {
+ pseudo_tcp_socket_shutdown (component->tcp, PSEUDO_TCP_SHUTDOWN_RD);
+ }
+
+ agent_unlock (agent);
+
+ g_object_unref (agent);
+
+ return TRUE;
+}
+
+static gboolean
+nice_input_stream_is_readable (GPollableInputStream *stream)
+{
+ NiceInputStreamPrivate *priv = NICE_INPUT_STREAM (stream)->priv;
+ NiceComponent *component = NULL;
+ NiceStream *_stream = NULL;
+ gboolean retval = FALSE;
+ GSList *i;
+ NiceAgent *agent; /* owned */
+
+ /* Closed streams are not readable. */
+ if (g_input_stream_is_closed (G_INPUT_STREAM (stream)))
+ return FALSE;
+
+ /* Has the agent disappeared? */
+ agent = g_weak_ref_get (&priv->agent_ref);
+ if (agent == NULL)
+ return FALSE;
+
+ agent_lock (agent);
+
+ if (!agent_find_component (agent, priv->stream_id, priv->component_id,
+ &_stream, &component)) {
+ g_warning ("Could not find component %u in stream %u", priv->component_id,
+ priv->stream_id);
+ goto done;
+ }
+
+ /* If it’s a reliable agent, see if there’s any pending data in the pseudo-TCP
+ * buffer. */
+ if (agent->reliable &&
+ pseudo_tcp_socket_get_available_bytes (component->tcp) > 0) {
+ retval = TRUE;
+ goto done;
+ }
+
+ /* Check whether any of the component’s FDs are pollable. */
+ for (i = component->socket_sources; i != NULL; i = i->next) {
+ SocketSource *socket_source = i->data;
+ NiceSocket *nicesock = socket_source->socket;
+
+ if (g_socket_condition_check (nicesock->fileno, G_IO_IN) != 0) {
+ retval = TRUE;
+ break;
+ }
+ }
+
+done:
+ agent_unlock (agent);
+
+ g_object_unref (agent);
+
+ return retval;
+}
+
+static gssize
+nice_input_stream_read_nonblocking (GPollableInputStream *stream, void *buffer,
+ gsize count, GError **error)
+{
+ NiceInputStreamPrivate *priv = NICE_INPUT_STREAM (stream)->priv;
+ NiceAgent *agent; /* owned */
+ gssize len;
+
+ /* Closed streams are not readable. */
+ if (g_input_stream_is_closed (G_INPUT_STREAM (stream))) {
+ return 0;
+ }
+
+ /* Has the agent disappeared? */
+ agent = g_weak_ref_get (&priv->agent_ref);
+ if (agent == NULL) {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
+ "Stream is closed due to the NiceAgent being finalised.");
+ return -1;
+ }
+
+ len = nice_agent_recv_nonblocking (agent, priv->stream_id,
+ priv->component_id, (guint8 *) buffer, count, NULL, error);
+
+ g_object_unref (agent);
+
+ return len;
+}
+
+static GSource *
+nice_input_stream_create_source (GPollableInputStream *stream,
+ GCancellable *cancellable)
+{
+ NiceInputStreamPrivate *priv = NICE_INPUT_STREAM (stream)->priv;
+ GSource *component_source = NULL;
+ NiceAgent *agent; /* owned */
+
+ /* Closed streams cannot have sources. */
+ if (g_input_stream_is_closed (G_INPUT_STREAM (stream)))
+ goto dummy_source;
+
+ /* Has the agent disappeared? */
+ agent = g_weak_ref_get (&priv->agent_ref);
+ if (agent == NULL)
+ goto dummy_source;
+
+ component_source = nice_component_input_source_new (agent, priv->stream_id,
+ priv->component_id, stream, cancellable);
+
+ g_object_unref (agent);
+
+ return component_source;
+
+ dummy_source:
+
+ component_source = g_pollable_source_new (G_OBJECT (stream));
+
+ if (cancellable) {
+ GSource *cancellable_source = g_cancellable_source_new (cancellable);
+
+ g_source_set_dummy_callback (cancellable_source);
+ g_source_add_child_source (component_source, cancellable_source);
+ g_source_unref (cancellable_source);
+ }
+
+ return component_source;
+}
+
+static void
+streams_removed_cb (NiceAgent *agent, guint *stream_ids, gpointer user_data)
+{
+ NiceInputStream *self = NICE_INPUT_STREAM (user_data);
+ guint i;
+
+ for (i = 0; stream_ids[i] != 0; i++) {
+ if (stream_ids[i] == self->priv->stream_id) {
+ /* The socket has been closed. */
+ g_input_stream_close (G_INPUT_STREAM (self), NULL, NULL);
+ break;
+ }
+ }
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2010, 2013 Collabora Ltd.
+ * Contact: Youness Alaoui
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef __NICE_INPUT_STREAM_H__
+#define __NICE_INPUT_STREAM_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+#include "agent.h"
+
+G_BEGIN_DECLS
+
+/* TYPE MACROS */
+#define NICE_TYPE_INPUT_STREAM \
+ (nice_input_stream_get_type ())
+#define NICE_INPUT_STREAM(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), NICE_TYPE_INPUT_STREAM, \
+ NiceInputStream))
+#define NICE_INPUT_STREAM_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), NICE_TYPE_INPUT_STREAM, \
+ NiceInputStreamClass))
+#define NICE_IS_INPUT_STREAM(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), NICE_TYPE_INPUT_STREAM))
+#define NICE_IS_INPUT_STREAM_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), NICE_TYPE_INPUT_STREAM))
+#define NICE_INPUT_STREAM_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), NICE_TYPE_INPUT_STREAM, \
+ NiceInputStreamClass))
+
+
+typedef struct _NiceInputStreamPrivate NiceInputStreamPrivate;
+typedef struct _NiceInputStreamClass NiceInputStreamClass;
+typedef struct _NiceInputStream NiceInputStream;
+
+GType nice_input_stream_get_type (void);
+
+struct _NiceInputStreamClass
+{
+ GInputStreamClass parent_class;
+};
+
+struct _NiceInputStream
+{
+ GInputStream parent_instance;
+ NiceInputStreamPrivate *priv;
+};
+
+
+NiceInputStream *nice_input_stream_new (NiceAgent *agent,
+ guint stream_id, guint component_id);
+
+
+G_END_DECLS
+
+#endif /* __NICE_INPUT_STREAM_H__ */
--- /dev/null
+/*
+ * interfaces.c - Source for interface discovery code
+ *
+ * Copyright (C) 2006 Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ * Copyright (C) 2007 Collabora, Nokia
+ * Contact: Youness Alaoui
+ * Copyright (C) 2008 Haakon Sporsheim <haakon.sporsheim@tandberg.com>
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Dafydd Harries, Collabora Ltd.
+ * Youness Alaoui, Collabora Ltd.
+ * Kai Vehmanen, Nokia
+ * Philip Withnall, Collabora Ltd.
+ * Haakon Sporsheim
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "interfaces.h"
+#include "agent-priv.h"
+
+#ifdef G_OS_UNIX
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+#ifdef __sun
+#include <sys/sockio.h>
+#endif
+
+#ifdef HAVE_GETIFADDRS
+ #include <ifaddrs.h>
+#endif
+
+#include <net/if.h>
+#include <arpa/inet.h>
+
+#endif /* G_OS_UNIX */
+
+#if (defined(G_OS_UNIX) && defined(HAVE_GETIFADDRS)) || defined(G_OS_WIN32)
+/* Works on both UNIX and Windows. Magic! */
+static gchar *
+sockaddr_to_string (const struct sockaddr *addr)
+{
+ char addr_as_string[INET6_ADDRSTRLEN+1];
+ size_t addr_len;
+
+ switch (addr->sa_family) {
+ case AF_INET: addr_len = sizeof (struct sockaddr_in); break;
+ case AF_INET6: addr_len = sizeof (struct sockaddr_in6); break;
+ default: return NULL;
+ }
+
+ if (getnameinfo (addr, addr_len,
+ addr_as_string, sizeof (addr_as_string), NULL, 0,
+ NI_NUMERICHOST) != 0) {
+ return NULL;
+ }
+
+ return g_strdup (addr_as_string);
+}
+#endif
+
+#ifdef G_OS_UNIX
+
+#ifdef HAVE_GETIFADDRS
+
+GList *
+nice_interfaces_get_local_interfaces (void)
+{
+ GList *interfaces = NULL;
+ struct ifaddrs *ifa, *results;
+
+ if (getifaddrs (&results) < 0) {
+ return NULL;
+ }
+
+ /* Loop and get each interface the system has, one by one... */
+ for (ifa = results; ifa; ifa = ifa->ifa_next) {
+ /* no ip address from interface that is down */
+ if ((ifa->ifa_flags & IFF_UP) == 0)
+ continue;
+
+ if (ifa->ifa_addr == NULL)
+ continue;
+
+ if (ifa->ifa_addr->sa_family == AF_INET || ifa->ifa_addr->sa_family == AF_INET6) {
+ nice_debug ("Found interface : %s", ifa->ifa_name);
+ interfaces = g_list_prepend (interfaces, g_strdup (ifa->ifa_name));
+ }
+ }
+
+ freeifaddrs (results);
+
+ return interfaces;
+}
+
+#else /* ! HAVE_GETIFADDRS */
+
+GList *
+nice_interfaces_get_local_interfaces (void)
+{
+ GList *interfaces = NULL;
+ gint sockfd;
+ gint size = 0;
+ struct ifreq *ifr;
+ struct ifconf ifc;
+
+ if ((sockfd = socket (AF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) {
+ nice_debug ("error : Cannot open socket to retrieve interface list");
+ return NULL;
+ }
+
+ ifc.ifc_len = 0;
+ ifc.ifc_req = NULL;
+
+ /* Loop and get each interface the system has, one by one... */
+ do {
+ size += sizeof (struct ifreq);
+ /* realloc buffer size until no overflow occurs */
+ if (NULL == (ifc.ifc_req = realloc (ifc.ifc_req, size))) {
+ nice_debug ("Error : Out of memory while allocation interface"
+ "configuration structure");
+ close (sockfd);
+ return NULL;
+ }
+ ifc.ifc_len = size;
+
+ if (ioctl (sockfd, SIOCGIFCONF, &ifc)) {
+ perror ("ioctl SIOCFIFCONF");
+ close (sockfd);
+ free (ifc.ifc_req);
+ return NULL;
+ }
+ } while (size <= ifc.ifc_len);
+
+
+ /* Loop throught the interface list and get the IP address of each IF */
+ for (ifr = ifc.ifc_req;
+ (gchar *) ifr < (gchar *) ifc.ifc_req + ifc.ifc_len;
+ ++ifr) {
+ nice_debug ("Found interface : %s", ifr->ifr_name);
+ interfaces = g_list_prepend (interfaces, g_strdup (ifr->ifr_name));
+ }
+
+ free (ifc.ifc_req);
+ close (sockfd);
+
+ return interfaces;
+}
+#endif /* HAVE_GETIFADDRS */
+
+
+static gboolean
+nice_interfaces_is_private_ip (const struct sockaddr *_sa)
+{
+ union {
+ const struct sockaddr *addr;
+ const struct sockaddr_in *in;
+ } sa;
+
+ sa.addr = _sa;
+
+ if (sa.addr->sa_family == AF_INET) {
+ /* 10.x.x.x/8 */
+ if (sa.in->sin_addr.s_addr >> 24 == 0x0A)
+ return TRUE;
+
+ /* 172.16.0.0 - 172.31.255.255 = 172.16.0.0/10 */
+ if (sa.in->sin_addr.s_addr >> 20 == 0xAC1)
+ return TRUE;
+
+ /* 192.168.x.x/16 */
+ if (sa.in->sin_addr.s_addr >> 16 == 0xC0A8)
+ return TRUE;
+
+ /* 169.254.x.x/16 (for APIPA) */
+ if (sa.in->sin_addr.s_addr >> 16 == 0xA9FE)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static GList *
+add_ip_to_list (GList *list, gchar *ip, gboolean append)
+{
+ GList *i;
+
+ for (i = list; i; i = i->next) {
+ gchar *addr = (gchar *) i->data;
+
+ if (g_strcmp0 (addr, ip) == 0)
+ return list;
+ }
+ if (append)
+ return g_list_append (list, ip);
+ else
+ return g_list_prepend (list, ip);
+}
+
+#ifdef HAVE_GETIFADDRS
+
+GList *
+nice_interfaces_get_local_ips (gboolean include_loopback)
+{
+ GList *ips = NULL;
+ struct ifaddrs *ifa, *results;
+ GList *loopbacks = NULL;
+
+
+ if (getifaddrs (&results) < 0)
+ return NULL;
+
+ /* Loop through the interface list and get the IP address of each IF */
+ for (ifa = results; ifa; ifa = ifa->ifa_next) {
+ gchar *addr_string;
+
+ /* no ip address from interface that is down */
+ if ((ifa->ifa_flags & IFF_UP) == 0)
+ continue;
+
+ if (ifa->ifa_addr == NULL)
+ continue;
+
+ /* Convert to a string. */
+ addr_string = sockaddr_to_string (ifa->ifa_addr);
+ if (addr_string == NULL) {
+ nice_debug ("Failed to convert address to string for interface ‘%s’.",
+ ifa->ifa_name);
+ continue;
+ }
+
+ nice_debug ("Interface: %s", ifa->ifa_name);
+ nice_debug ("IP Address: %s", addr_string);
+ if ((ifa->ifa_flags & IFF_LOOPBACK) == IFF_LOOPBACK) {
+ if (include_loopback) {
+ loopbacks = add_ip_to_list (loopbacks, addr_string, TRUE);
+ } else {
+ nice_debug ("Ignoring loopback interface");
+ g_free (addr_string);
+ }
+#ifdef IGNORED_IFACE_PREFIX
+ } else if (g_str_has_prefix (ifa->ifa_name, IGNORED_IFACE_PREFIX)) {
+ nice_debug ("Ignoring interface %s as it matches prefix %s",
+ ifa->ifa_name, IGNORED_IFACE_PREFIX);
+ g_free (addr_string);
+#endif
+ } else {
+ if (nice_interfaces_is_private_ip (ifa->ifa_addr))
+ ips = add_ip_to_list (ips, addr_string, TRUE);
+ else
+ ips = add_ip_to_list (ips, addr_string, FALSE);
+ }
+ }
+
+ freeifaddrs (results);
+
+ if (loopbacks)
+ ips = g_list_concat (ips, loopbacks);
+
+ return ips;
+}
+
+#else /* ! HAVE_GETIFADDRS */
+
+GList *
+nice_interfaces_get_local_ips (gboolean include_loopback)
+{
+ GList *ips = NULL;
+ gint sockfd;
+ gint size = 0;
+ struct ifreq *ifr;
+ struct ifconf ifc;
+ struct sockaddr_in *sa;
+ gchar *loopback = NULL;
+
+ if ((sockfd = socket (AF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) {
+ nice_debug ("Error : Cannot open socket to retrieve interface list");
+ return NULL;
+ }
+
+ ifc.ifc_len = 0;
+ ifc.ifc_req = NULL;
+
+ /* Loop and get each interface the system has, one by one... */
+ do {
+ size += sizeof (struct ifreq);
+ /* realloc buffer size until no overflow occurs */
+ if (NULL == (ifc.ifc_req = realloc (ifc.ifc_req, size))) {
+ nice_debug ("Error : Out of memory while allocation interface"
+ " configuration structure");
+ close (sockfd);
+ return NULL;
+ }
+ ifc.ifc_len = size;
+
+ if (ioctl (sockfd, SIOCGIFCONF, &ifc)) {
+ perror ("ioctl SIOCFIFCONF");
+ close (sockfd);
+ free (ifc.ifc_req);
+ return NULL;
+ }
+ } while (size <= ifc.ifc_len);
+
+
+ /* Loop throught the interface list and get the IP address of each IF */
+ for (ifr = ifc.ifc_req;
+ (gchar *) ifr < (gchar *) ifc.ifc_req + ifc.ifc_len;
+ ++ifr) {
+
+ if (ioctl (sockfd, SIOCGIFFLAGS, ifr)) {
+ nice_debug ("Error : Unable to get IP information for interface %s."
+ " Skipping...", ifr->ifr_name);
+ continue; /* failed to get flags, skip it */
+ }
+ sa = (struct sockaddr_in *) &ifr->ifr_addr;
+ nice_debug ("Interface: %s", ifr->ifr_name);
+ nice_debug ("IP Address: %s", inet_ntoa (sa->sin_addr));
+ if ((ifr->ifr_flags & IFF_LOOPBACK) == IFF_LOOPBACK){
+ if (include_loopback)
+ loopback = g_strdup (inet_ntoa (sa->sin_addr));
+ else
+ nice_debug ("Ignoring loopback interface");
+ } else {
+ if (nice_interfaces_is_private_ip ((struct sockaddr *) sa)) {
+ ips = add_ip_to_list (ips, g_strdup (inet_ntoa (sa->sin_addr)), TRUE);
+ } else {
+ ips = add_ip_to_list (ips, g_strdup (inet_ntoa (sa->sin_addr)), FALSE);
+ }
+ }
+ }
+
+ close (sockfd);
+ free (ifc.ifc_req);
+
+ if (loopback)
+ ips = add_ip_to_list (ips, loopback, TRUE);
+
+ return ips;
+}
+
+#endif /* HAVE_GETIFADDRS */
+
+gchar *
+nice_interfaces_get_ip_for_interface (gchar *interface_name)
+{
+ struct ifreq ifr;
+ union {
+ struct sockaddr *addr;
+ struct sockaddr_in *in;
+ } sa;
+ gint sockfd;
+
+ g_return_val_if_fail (interface_name != NULL, NULL);
+
+ ifr.ifr_addr.sa_family = AF_INET;
+ memset (ifr.ifr_name, 0, sizeof (ifr.ifr_name));
+ g_strlcpy (ifr.ifr_name, interface_name, sizeof (ifr.ifr_name));
+
+ if ((sockfd = socket (AF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) {
+ nice_debug ("Error : Cannot open socket to retrieve interface list");
+ return NULL;
+ }
+
+ if (ioctl (sockfd, SIOCGIFADDR, &ifr) < 0) {
+ nice_debug ("Error : Unable to get IP information for interface %s",
+ interface_name);
+ close (sockfd);
+ return NULL;
+ }
+
+ close (sockfd);
+ sa.addr = &ifr.ifr_addr;
+ nice_debug ("Address for %s: %s", interface_name, inet_ntoa (sa.in->sin_addr));
+ return g_strdup (inet_ntoa (sa.in->sin_addr));
+}
+
+#else /* G_OS_UNIX */
+#ifdef G_OS_WIN32
+
+#include <winsock2.h>
+#include <iphlpapi.h>
+
+// Should be in Iphlpapi.h, but mingw doesn't seem to have these
+// Values copied directly from:
+// http://msdn.microsoft.com/en-us/library/aa366845(v=vs.85).aspx
+// (Title: MIB_IPADDRROW structure)
+
+#ifndef MIB_IPADDR_DISCONNECTED
+#define MIB_IPADDR_DISCONNECTED 0x0008
+#endif
+
+#ifndef MIB_IPADDR_DELETED
+#define MIB_IPADDR_DELETED 0x0040
+#endif
+
+#if 0
+static gboolean started_wsa_engine = FALSE;
+
+/*
+ * private function that initializes the WinSock engine and
+ * returns a prebuilt socket
+ */
+SOCKET nice_interfaces_get_WSA_socket ()
+{
+ WORD wVersionRequested;
+ WSADATA wsaData;
+ int err;
+ SOCKET sock;
+
+ if (started_wsa_engine == FALSE) {
+ wVersionRequested = MAKEWORD ( 2, 0 );
+
+ err = WSAStartup ( wVersionRequested, &wsaData );
+ if ( err != 0 ) {
+ nice_debug ("Error : Could not start the winsocket engine");
+ return INVALID_SOCKET;
+ }
+ started_wsa_engine = TRUE;
+ }
+
+
+ if ((sock = socket (AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET) {
+ nice_debug ("Error : Could not open socket to retrieve interface list,"
+ " error no : %d", WSAGetLastError ());
+ return INVALID_SOCKET;
+ }
+
+ return sock;
+}
+#endif
+
+GList * nice_interfaces_get_local_interfaces (void)
+{
+ ULONG size = 0;
+ PMIB_IFTABLE if_table;
+ GList * ret = NULL;
+
+ GetIfTable(NULL, &size, TRUE);
+
+ if (!size)
+ return NULL;
+
+ if_table = (PMIB_IFTABLE)g_malloc0(size);
+
+ if (GetIfTable(if_table, &size, TRUE) == ERROR_SUCCESS) {
+ DWORD i;
+ for (i = 0; i < if_table->dwNumEntries; i++) {
+ ret = g_list_prepend (ret, g_strdup ((gchar*)if_table->table[i].bDescr));
+ }
+ }
+
+ g_free(if_table);
+
+ return ret;
+}
+
+GList * nice_interfaces_get_local_ips (gboolean include_loopback)
+{
+ IP_ADAPTER_ADDRESSES *addresses = NULL, *a;
+ ULONG status;
+ guint iterations;
+ ULONG addresses_size;
+ DWORD pref = 0;
+ GList *ret = NULL;
+
+ /* As suggested on
+ * http://msdn.microsoft.com/en-gb/library/windows/desktop/aa365915%28v=vs.85%29.aspx */
+ #define MAX_TRIES 3
+ #define INITIAL_BUFFER_SIZE 15000
+
+ addresses_size = INITIAL_BUFFER_SIZE;
+ iterations = 0;
+
+ do {
+ g_free (addresses);
+ addresses = g_malloc0 (addresses_size);
+
+ status = GetAdaptersAddresses (AF_UNSPEC,
+ GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST |
+ GAA_FLAG_SKIP_DNS_SERVER, NULL, addresses, &addresses_size);
+ } while ((status == ERROR_BUFFER_OVERFLOW) && (iterations++ < MAX_TRIES));
+
+ nice_debug ("Queried addresses with status %lu.", status);
+
+ #undef INITIAL_BUFFER_SIZE
+ #undef MAX_TRIES
+
+ /* Error? */
+ if (status != NO_ERROR) {
+ nice_debug ("Error retrieving local addresses (error code %lu).", status);
+ g_free (addresses);
+ return NULL;
+ }
+
+ /*
+ * Get the best interface for transport to 0.0.0.0.
+ * This interface should be first in list!
+ */
+ if (GetBestInterface (0, &pref) != NO_ERROR)
+ pref = 0;
+
+ /* Loop over the adapters. */
+ for (a = addresses; a != NULL; a = a->Next) {
+ IP_ADAPTER_UNICAST_ADDRESS *unicast;
+
+ nice_debug ("Interface ‘%S’:", a->FriendlyName);
+
+ /* Various conditions for ignoring the interface. */
+ if (a->Flags & IP_ADAPTER_RECEIVE_ONLY ||
+ a->OperStatus == IfOperStatusDown ||
+ a->OperStatus == IfOperStatusNotPresent ||
+ a->OperStatus == IfOperStatusLowerLayerDown) {
+ nice_debug ("Rejecting interface due to being down or read-only.");
+ continue;
+ }
+
+ if (!include_loopback &&
+ a->IfType == IF_TYPE_SOFTWARE_LOOPBACK) {
+ nice_debug ("Rejecting loopback interface ‘%S’.", a->FriendlyName);
+ continue;
+ }
+
+ /* Grab the interface’s unicast addresses. */
+ for (unicast = a->FirstUnicastAddress;
+ unicast != NULL; unicast = unicast->Next) {
+ gchar *addr_string;
+
+ addr_string = sockaddr_to_string (unicast->Address.lpSockaddr);
+ if (addr_string == NULL) {
+ nice_debug ("Failed to convert address to string for interface ‘%S’.",
+ a->FriendlyName);
+ continue;
+ }
+
+ nice_debug ("IP address: %s", addr_string);
+
+ if (a->IfIndex == pref || a->Ipv6IfIndex == pref)
+ ret = g_list_prepend (ret, addr_string);
+ else
+ ret = g_list_append (ret, addr_string);
+ }
+ }
+
+ g_free (addresses);
+
+ return ret;
+}
+
+/*
+ * returns ip address as an utf8 string
+ */
+// Source for idx's type (Was IF_INDEX):
+// http://msdn.microsoft.com/en-us/library/aa366836(v=VS.85).aspx
+// (Title: MIB_IFROW structure)
+static gchar *
+win32_get_ip_for_interface (DWORD idx)
+{
+ ULONG size = 0;
+ PMIB_IPADDRTABLE ip_table;
+ gchar * ret = NULL;
+
+ GetIpAddrTable (NULL, &size, TRUE);
+
+ if (!size)
+ return NULL;
+
+ ip_table = (PMIB_IPADDRTABLE)g_malloc0 (size);
+
+ if (GetIpAddrTable (ip_table, &size, TRUE) == ERROR_SUCCESS) {
+ DWORD i;
+ for (i = 0; i < ip_table->dwNumEntries; i++) {
+ PMIB_IPADDRROW ipaddr = &ip_table->table[i];
+ if (ipaddr->dwIndex == idx &&
+ !(ipaddr->wType & (MIB_IPADDR_DISCONNECTED | MIB_IPADDR_DELETED))) {
+ ret = g_strdup_printf ("%lu.%lu.%lu.%lu",
+ (ipaddr->dwAddr ) & 0xFF,
+ (ipaddr->dwAddr >> 8) & 0xFF,
+ (ipaddr->dwAddr >> 16) & 0xFF,
+ (ipaddr->dwAddr >> 24) & 0xFF);
+ break;
+ }
+ }
+ }
+
+ g_free (ip_table);
+ return ret;
+}
+
+gchar * nice_interfaces_get_ip_for_interface (gchar *interface_name)
+{
+ ULONG size = 0;
+ PMIB_IFTABLE if_table;
+ gchar * ret = NULL;
+
+ GetIfTable (NULL, &size, TRUE);
+
+ if (!size)
+ return NULL;
+
+ if_table = (PMIB_IFTABLE)g_malloc0 (size);
+
+ if (GetIfTable (if_table, &size, TRUE) == ERROR_SUCCESS) {
+ DWORD i;
+ gchar * tmp_str;
+ for (i = 0; i < if_table->dwNumEntries; i++) {
+ tmp_str = g_utf16_to_utf8 (
+ if_table->table[i].wszName, MAX_INTERFACE_NAME_LEN,
+ NULL, NULL, NULL);
+
+ if (strlen (interface_name) == strlen (tmp_str) &&
+ g_ascii_strncasecmp (interface_name, tmp_str, strlen (interface_name)) == 0) {
+ ret = win32_get_ip_for_interface (if_table->table[i].dwIndex);
+ g_free (tmp_str);
+ break;
+ }
+
+ g_free (tmp_str);
+ }
+ }
+
+ g_free (if_table);
+
+ return ret;
+}
+
+
+#else /* G_OS_WIN32 */
+#error Can not use this method for retreiving ip list from OS other than unix or windows
+#endif /* G_OS_WIN32 */
+#endif /* G_OS_UNIX */
--- /dev/null
+/*
+ * interfaces.h - Source for interface discovery code
+ *
+ * Farsight Helper functions
+ * Copyright (C) 2006 Youness Alaoui <kakaroto@kakaroto.homelinux.net>
+ * Copyright (C) 2008-2009 Collabora, Nokia
+ * Contact: Youness Alaoui
+ * Copyright (C) 2008-2009 Nokia Corporation. All rights reserved.
+ *
+ * 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
+ */
+
+#ifndef __LIBNICE_INTERFACES_H__
+#define __LIBNICE_INTERFACES_H__
+
+/**
+ * SECTION:interfaces
+ * @short_description: Utility functions to discover local network interfaces
+ * @include: interfaces.h
+ * @stability: Stable
+ *
+ * These utility functions allow the discovery of local network interfaces
+ * in a portable manner, they also allow finding the local ip addresses or
+ * the address allocated to a network interface.
+ */
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+
+/**
+ * nice_interfaces_get_ip_for_interface:
+ * @interface_name: name of local interface
+ *
+ * Retrieves the IP address of an interface by its name. If this fails, %NULL
+ * is returned.
+ *
+ * Returns: (nullable) (transfer full): a newly-allocated string with the IP
+ * address
+ */
+gchar * nice_interfaces_get_ip_for_interface (gchar *interface_name);
+
+
+/**
+ * nice_interfaces_get_local_ips:
+ * @include_loopback: Include any loopback devices
+ *
+ * Get a list of local ipv4 interface addresses
+ *
+ * Returns: (element-type utf8) (transfer full): a newly-allocated #GList of
+ * strings. The caller must free it.
+ */
+
+GList * nice_interfaces_get_local_ips (gboolean include_loopback);
+
+
+/**
+ * nice_interfaces_get_local_interfaces:
+ *
+ * Get the list of local interfaces
+ *
+ * Returns: (element-type utf8) (transfer full): a newly-allocated #GList of
+ * strings. The caller must free it.
+ */
+GList * nice_interfaces_get_local_interfaces (void);
+
+G_END_DECLS
+
+#endif /* __LIBNICE_INTERFACES_H__ */
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2010, 2013 Collabora Ltd.
+ * Contact: Youness Alaoui
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ * Philip Withnall, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+/***
+ * SECTION:nice_io_stream
+ * @short_description: #GIOStream implementation for libnice
+ * @see_also: #NiceAgent
+ * @include: iostream.h
+ * @stability: Stable
+ *
+ * #NiceIOStream is a #GIOStream wrapper for a single reliable stream and
+ * component of a #NiceAgent. Given an existing reliable #NiceAgent, plus the
+ * IDs of an existing stream and component in the agent, it will provide a
+ * streaming input and output interface for communication over the given
+ * component.
+ *
+ * A single #NiceIOStream can only be used with a single agent, stream and
+ * component triple, and will be closed as soon as that stream is removed from
+ * the agent (e.g. if nice_agent_remove_stream() is called from another thread).
+ * If g_io_stream_close() is called on a #NiceIOStream, the I/O stream and
+ * underlying #NiceAgent stream will be closed in both directions, but the
+ * underlying stream will not be removed. Use nice_agent_remove_stream() to do
+ * that, but only do so after g_io_stream_close() has completed, or the stream
+ * will return broken pipe errors.
+ *
+ * Since: 0.1.5
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "iostream.h"
+#include "inputstream.h"
+#include "outputstream.h"
+
+G_DEFINE_TYPE (NiceIOStream, nice_io_stream, G_TYPE_IO_STREAM);
+
+enum
+{
+ PROP_AGENT = 1,
+ PROP_STREAM_ID,
+ PROP_COMPONENT_ID,
+};
+
+struct _NiceIOStreamPrivate
+{
+ GWeakRef/*<NiceAgent>*/ agent_ref;
+ guint stream_id;
+ guint component_id;
+
+ GInputStream *input_stream; /* owned */
+ GOutputStream *output_stream; /* owned */
+};
+
+static void nice_io_stream_dispose (GObject *object);
+static void nice_io_stream_get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec);
+static void nice_io_stream_set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec);
+static GInputStream *nice_io_stream_get_input_stream (GIOStream *stream);
+static GOutputStream *nice_io_stream_get_output_stream (GIOStream *stream);
+
+static void streams_removed_cb (NiceAgent *agent, guint *stream_ids,
+ gpointer user_data);
+
+static void
+nice_io_stream_class_init (NiceIOStreamClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GIOStreamClass *stream_class = G_IO_STREAM_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (NiceIOStreamPrivate));
+
+ gobject_class->set_property = nice_io_stream_set_property;
+ gobject_class->get_property = nice_io_stream_get_property;
+ gobject_class->dispose = nice_io_stream_dispose;
+
+ stream_class->get_input_stream = nice_io_stream_get_input_stream;
+ stream_class->get_output_stream = nice_io_stream_get_output_stream;
+
+ /*
+ * NiceIOStream:agent:
+ *
+ * The #NiceAgent to wrap with an I/O stream. This must be an existing
+ * reliable agent.
+ *
+ * A reference is not held on the #NiceAgent. If the agent is destroyed before
+ * the #NiceIOStream, %G_IO_ERROR_CLOSED will be returned for all subsequent
+ * operations on the stream.
+ *
+ * Since: 0.1.5
+ */
+ g_object_class_install_property (gobject_class, PROP_AGENT,
+ g_param_spec_object ("agent",
+ "NiceAgent",
+ "The underlying NiceAgent",
+ NICE_TYPE_AGENT,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ /*
+ * NiceIOStream:stream-id:
+ *
+ * ID of the stream to use in the #NiceIOStream:agent.
+ *
+ * Since: 0.1.5
+ */
+ g_object_class_install_property (gobject_class, PROP_STREAM_ID,
+ g_param_spec_uint (
+ "stream-id",
+ "Agent’s stream ID",
+ "The ID of the agent’s stream to wrap.",
+ 0, G_MAXUINT,
+ 0,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ /*
+ * NiceIOStream:component-id:
+ *
+ * ID of the component to use in the #NiceIOStream:agent.
+ *
+ * Since: 0.1.5
+ */
+ g_object_class_install_property (gobject_class, PROP_COMPONENT_ID,
+ g_param_spec_uint (
+ "component-id",
+ "Agent’s component ID",
+ "The ID of the agent’s component to wrap.",
+ 0, G_MAXUINT,
+ 0,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+}
+
+static void
+nice_io_stream_init (NiceIOStream *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NICE_TYPE_IO_STREAM,
+ NiceIOStreamPrivate);
+
+ g_weak_ref_init (&self->priv->agent_ref, NULL);
+
+ /* Invalidate the stream/component IDs to begin with. */
+ self->priv->stream_id = 0;
+ self->priv->component_id = 0;
+}
+
+static void
+nice_io_stream_dispose (GObject *object)
+{
+ NiceIOStream *self = NICE_IO_STREAM (object);
+ NiceAgent *agent;
+
+ /* Ensure the stream is closed before continuing. Otherwise, if the input or
+ * output streams haven’t yet been lazily created, closing the stream in
+ * g_io_stream_dispose() will lazily create them, but NiceAgent will be NULL
+ * by that point and things will explode. */
+ if (!g_io_stream_is_closed (G_IO_STREAM (object)))
+ g_io_stream_close (G_IO_STREAM (object), NULL, NULL);
+
+ /* Clear everything away. */
+ if (self->priv->input_stream != NULL)
+ g_object_unref (self->priv->input_stream);
+ self->priv->input_stream = NULL;
+
+ if (self->priv->output_stream != NULL)
+ g_object_unref (self->priv->output_stream);
+ self->priv->output_stream = NULL;
+
+ agent = g_weak_ref_get (&self->priv->agent_ref);
+ if (agent != NULL) {
+ g_signal_handlers_disconnect_by_func (agent, streams_removed_cb, self);
+ g_object_unref (agent);
+ }
+
+ g_weak_ref_clear (&self->priv->agent_ref);
+
+ G_OBJECT_CLASS (nice_io_stream_parent_class)->dispose (object);
+}
+
+static void
+nice_io_stream_get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec)
+{
+ NiceIOStream *self = NICE_IO_STREAM (object);
+
+ switch (prop_id) {
+ case PROP_AGENT:
+ g_value_take_object (value, g_weak_ref_get (&self->priv->agent_ref));
+ break;
+ case PROP_STREAM_ID:
+ g_value_set_uint (value, self->priv->stream_id);
+ break;
+ case PROP_COMPONENT_ID:
+ g_value_set_uint (value, self->priv->component_id);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+nice_io_stream_set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ NiceIOStream *self = NICE_IO_STREAM (object);
+
+ switch (prop_id) {
+ case PROP_AGENT: {
+ /* Construct only. */
+ NiceAgent *agent = g_value_dup_object (value);
+ g_weak_ref_set (&self->priv->agent_ref, agent);
+ g_signal_connect (agent, "streams-removed",
+ (GCallback) streams_removed_cb, self);
+ g_object_unref (agent);
+
+ break;
+ }
+ case PROP_STREAM_ID:
+ /* Construct only. */
+ self->priv->stream_id = g_value_get_uint (value);
+ break;
+ case PROP_COMPONENT_ID:
+ /* Construct only. */
+ self->priv->component_id = g_value_get_uint (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+/***
+ * nice_io_stream_new:
+ * @agent: A #NiceAgent
+ * @stream_id: The ID of the agent’s stream to wrap
+ * @component_id: The ID of the agent’s component to wrap
+ *
+ * Create a new #NiceIOStream wrapping the given stream/component from @agent,
+ * which must be a reliable #NiceAgent.
+ *
+ * The constructed #NiceIOStream will not hold a reference to @agent. If @agent
+ * is destroyed before the I/O stream, %G_IO_ERROR_CLOSED will be returned for
+ * all subsequent operations on the stream.
+ *
+ * Returns: The new #NiceIOStream object
+ *
+ * Since: 0.1.5
+ */
+GIOStream *
+nice_io_stream_new (NiceAgent *agent, guint stream_id, guint component_id)
+{
+ g_return_val_if_fail (NICE_IS_AGENT (agent), NULL);
+ g_return_val_if_fail (stream_id > 0, NULL);
+ g_return_val_if_fail (component_id > 0, NULL);
+
+ return g_object_new (NICE_TYPE_IO_STREAM,
+ "agent", agent,
+ "stream-id", stream_id,
+ "component-id", component_id,
+ NULL);
+}
+
+static GInputStream *
+nice_io_stream_get_input_stream (GIOStream *stream)
+{
+ NiceIOStream *self = NICE_IO_STREAM (stream);
+
+ if (G_UNLIKELY (self->priv->input_stream == NULL)) {
+ NiceAgent *agent;
+
+ /* Note that agent may be NULL here. NiceInputStream must support
+ * construction with a NULL agent. */
+ agent = g_weak_ref_get (&self->priv->agent_ref);
+ self->priv->input_stream = G_INPUT_STREAM (nice_input_stream_new (
+ agent, self->priv->stream_id, self->priv->component_id));
+ if (agent != NULL)
+ g_object_unref (agent);
+ }
+
+ return self->priv->input_stream;
+}
+
+static GOutputStream *
+nice_io_stream_get_output_stream (GIOStream *stream)
+{
+ NiceIOStream *self = NICE_IO_STREAM (stream);
+
+ if (G_UNLIKELY (self->priv->output_stream == NULL)) {
+ NiceAgent *agent;
+
+ /* Note that agent may be NULL here. NiceOutputStream must support
+ * construction with a NULL agent. */
+ agent = g_weak_ref_get (&self->priv->agent_ref);
+ self->priv->output_stream = g_object_new (NICE_TYPE_OUTPUT_STREAM,
+ "agent", agent,
+ "stream-id", self->priv->stream_id,
+ "component-id", self->priv->component_id,
+ NULL);
+
+ if (agent != NULL)
+ g_object_unref (agent);
+ }
+
+ return self->priv->output_stream;
+}
+
+static void
+streams_removed_cb (NiceAgent *agent, guint *stream_ids, gpointer user_data)
+{
+ NiceIOStream *self = NICE_IO_STREAM (user_data);
+ guint i;
+
+ for (i = 0; stream_ids[i] != 0; i++) {
+ if (stream_ids[i] == self->priv->stream_id) {
+ /* The socket has been closed. */
+ g_io_stream_close (G_IO_STREAM (self), NULL, NULL);
+ break;
+ }
+ }
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2010, 2013 Collabora Ltd.
+ * Contact: Youness Alaoui
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef __NICE_IO_STREAM_H__
+#define __NICE_IO_STREAM_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+/* TYPE MACROS */
+
+/* IO Stream */
+#define NICE_TYPE_IO_STREAM \
+ (nice_io_stream_get_type ())
+#define NICE_IO_STREAM(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), NICE_TYPE_IO_STREAM, \
+ NiceIOStream))
+#define NICE_IO_STREAM_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), NICE_TYPE_IO_STREAM, \
+ NiceIOStreamClass))
+#define NICE_IS_IO_STREAM(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), NICE_TYPE_IO_STREAM))
+#define NICE_IS_IO_STREAM_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), NICE_TYPE_IO_STREAM))
+#define NICE_IO_STREAM_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), NICE_TYPE_IO_STREAM, \
+ NiceIOStreamClass))
+
+/* IO Stream */
+typedef struct _NiceIOStreamPrivate NiceIOStreamPrivate;
+typedef struct _NiceIOStreamClass NiceIOStreamClass;
+typedef struct _NiceIOStream NiceIOStream;
+
+#include "agent.h"
+#include "inputstream.h"
+#include "outputstream.h"
+
+/* IO Stream */
+GType nice_io_stream_get_type (void);
+
+struct _NiceIOStreamClass
+{
+ GIOStreamClass parent_class;
+};
+
+struct _NiceIOStream
+{
+ GIOStream parent_instance;
+ NiceIOStreamPrivate *priv;
+};
+
+GIOStream *nice_io_stream_new (NiceAgent *agent,
+ guint stream_id, guint component_id);
+
+G_END_DECLS
+
+#endif /* __NICE_IO_STREAM_H__ */
--- /dev/null
+agent_headers = files([
+ 'address.h',
+ 'agent.h',
+ 'candidate.h',
+ 'debug.h',
+ 'interfaces.h',
+ 'pseudotcp.h',
+])
+install_headers(agent_headers, subdir : 'nice')
+agent_include = include_directories('.')
+
+agent_sources = files([
+ 'address.c',
+ 'agent.c',
+ 'candidate.c',
+ 'component.c',
+ 'conncheck.c',
+ 'debug.c',
+ 'discovery.c',
+ 'inputstream.c',
+ 'interfaces.c',
+ 'iostream.c',
+ 'outputstream.c',
+ 'pseudotcp.c',
+ 'stream.c',
+])
+
+gnome = import('gnome')
+
+agent_enum_types = gnome.mkenums_simple('agent-enum-types', sources : agent_headers)
+agent_enum_types_c = agent_enum_types[0]
+agent_enum_types_h = agent_enum_types[1]
+
+libagent = static_library('agent',
+ agent_enum_types, agent_sources,
+ c_args: ['-DG_LOG_DOMAIN="libnice"'],
+ include_directories: nice_incs,
+ dependencies: nice_deps,
+ install: false)
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2010, 2013 Collabora Ltd.
+ * Contact: Youness Alaoui
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ * Philip Withnall, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+/***
+ * SECTION:nice_output_stream
+ * @short_description: #GOutputStream implementation for libnice
+ * @see_also: #NiceAgent
+ * @include: outputstream.h
+ * @stability: Stable
+ *
+ * #NiceOutputStream is a #GOutputStream wrapper for a single reliable stream
+ * and component of a #NiceAgent. Given an existing reliable #NiceAgent, plus
+ * the IDs of an existing stream and component in the agent, it will provide a
+ * streaming output interface for writing to the given component.
+ *
+ * A single #NiceOutputStream can only be used with a single agent, stream and
+ * component triple, and will be closed as soon as that stream is removed from
+ * the agent (e.g. if nice_agent_remove_stream() is called from another thread).
+ * If g_output_stream_close() is called on a #NiceOutputStream, the output
+ * stream and underlying #NiceAgent stream will be closed, but the underlying
+ * stream will not be removed. Use nice_agent_remove_stream() to do that.
+ *
+ * The output stream can only be used once the
+ * #NiceAgent::reliable-transport-writable signal has been received for the
+ * stream/component pair. Any calls to g_output_stream_write() before then will
+ * return %G_IO_ERROR_BROKEN_PIPE.
+ *
+ * Since: 0.1.5
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <errno.h>
+
+#include "outputstream.h"
+#include "agent-priv.h"
+
+static void nice_output_stream_init_pollable (
+ GPollableOutputStreamInterface *iface);
+static void streams_removed_cb (NiceAgent *agent, guint *stream_ids,
+ gpointer user_data);
+
+G_DEFINE_TYPE_WITH_CODE (NiceOutputStream,
+ nice_output_stream, G_TYPE_OUTPUT_STREAM,
+ G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_OUTPUT_STREAM,
+ nice_output_stream_init_pollable));
+
+enum
+{
+ PROP_AGENT = 1,
+ PROP_STREAM_ID,
+ PROP_COMPONENT_ID,
+};
+
+struct _NiceOutputStreamPrivate
+{
+ GWeakRef/*<NiceAgent>*/ agent_ref;
+ guint stream_id;
+ guint component_id;
+
+ GCancellable *closed_cancellable;
+};
+
+static void nice_output_stream_dispose (GObject *object);
+static void nice_output_stream_get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec);
+static void nice_output_stream_set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec);
+
+static gssize nice_output_stream_write (GOutputStream *stream,
+ const void *buffer, gsize count, GCancellable *cancellable, GError **error);
+static gboolean nice_output_stream_close (GOutputStream *stream,
+ GCancellable *cancellable, GError **error);
+
+static gboolean nice_output_stream_is_writable (GPollableOutputStream *stream);
+static gssize nice_output_stream_write_nonblocking (
+ GPollableOutputStream *stream, const void *buffer, gsize count,
+ GError **error);
+static GSource *nice_output_stream_create_source (GPollableOutputStream *stream,
+ GCancellable *cancellable);
+
+/* Output Stream */
+static void
+nice_output_stream_class_init (NiceOutputStreamClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GOutputStreamClass *stream_class = G_OUTPUT_STREAM_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (NiceOutputStreamPrivate));
+
+ stream_class->write_fn = nice_output_stream_write;
+ stream_class->close_fn = nice_output_stream_close;
+
+ gobject_class->set_property = nice_output_stream_set_property;
+ gobject_class->get_property = nice_output_stream_get_property;
+ gobject_class->dispose = nice_output_stream_dispose;
+
+ /***
+ * NiceOutputStream:agent:
+ *
+ * The #NiceAgent to wrap with an output stream. This must be an existing
+ * reliable agent.
+ *
+ * A reference is not held on the #NiceAgent. If the agent is destroyed before
+ * the #NiceOutputStream, %G_IO_ERROR_CLOSED will be returned for all
+ * subsequent operations on the stream.
+ *
+ * Since: 0.1.5
+ */
+ g_object_class_install_property (gobject_class, PROP_AGENT,
+ g_param_spec_object ("agent",
+ "NiceAgent",
+ "The underlying NiceAgent",
+ NICE_TYPE_AGENT,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ /***
+ * NiceOutputStream:stream-id:
+ *
+ * ID of the stream to use in the #NiceOutputStream:agent.
+ *
+ * Since: 0.1.5
+ */
+ g_object_class_install_property (gobject_class, PROP_STREAM_ID,
+ g_param_spec_uint (
+ "stream-id",
+ "Agent’s stream ID",
+ "The ID of the agent’s stream to wrap.",
+ 0, G_MAXUINT,
+ 0,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ /***
+ * NiceOutputStream:component-id:
+ *
+ * ID of the component to use in the #NiceOutputStream:agent.
+ *
+ * Since: 0.1.5
+ */
+ g_object_class_install_property (gobject_class, PROP_COMPONENT_ID,
+ g_param_spec_uint (
+ "component-id",
+ "Agent’s component ID",
+ "The ID of the agent’s component to wrap.",
+ 0, G_MAXUINT,
+ 0,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+}
+
+static void
+nice_output_stream_dispose (GObject *object)
+{
+ NiceOutputStream *self = NICE_OUTPUT_STREAM (object);
+ NiceAgent *agent;
+
+ /* Ensure the stream is closed first, otherwise the agent can’t be found in
+ * the close handler called by the parent implementation. */
+ if (!g_output_stream_is_closed (G_OUTPUT_STREAM (object)))
+ g_output_stream_close (G_OUTPUT_STREAM (object), NULL, NULL);
+
+ agent = g_weak_ref_get (&self->priv->agent_ref);
+ if (agent != NULL) {
+ g_signal_handlers_disconnect_by_func (agent, streams_removed_cb, self);
+ g_object_unref (agent);
+ }
+
+ g_weak_ref_clear (&self->priv->agent_ref);
+
+ g_clear_object (&self->priv->closed_cancellable);
+
+ G_OBJECT_CLASS (nice_output_stream_parent_class)->dispose (object);
+}
+
+static void
+nice_output_stream_get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec)
+{
+ NiceOutputStream *self = NICE_OUTPUT_STREAM (object);
+
+ switch (prop_id) {
+ case PROP_AGENT:
+ g_value_take_object (value, g_weak_ref_get (&self->priv->agent_ref));
+ break;
+ case PROP_STREAM_ID:
+ g_value_set_uint (value, self->priv->stream_id);
+ break;
+ case PROP_COMPONENT_ID:
+ g_value_set_uint (value, self->priv->component_id);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+nice_output_stream_set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ NiceOutputStream *self = NICE_OUTPUT_STREAM (object);
+
+ switch (prop_id) {
+ case PROP_AGENT: {
+ /* Construct only. */
+ NiceAgent *agent = g_value_dup_object (value);
+ g_weak_ref_set (&self->priv->agent_ref, agent);
+
+ /* agent may be NULL if the stream is being constructed by
+ * nice_io_stream_get_output_stream() after the NiceIOStream’s agent has
+ * already been finalised. */
+ if (agent != NULL) {
+ g_signal_connect (agent, "streams-removed",
+ (GCallback) streams_removed_cb, self);
+ g_object_unref (agent);
+ }
+
+ break;
+ }
+ case PROP_STREAM_ID:
+ /* Construct only. */
+ self->priv->stream_id = g_value_get_uint (value);
+ break;
+ case PROP_COMPONENT_ID:
+ /* Construct only. */
+ self->priv->component_id = g_value_get_uint (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+nice_output_stream_init (NiceOutputStream *stream)
+{
+ stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (stream, NICE_TYPE_OUTPUT_STREAM,
+ NiceOutputStreamPrivate);
+
+ g_weak_ref_init (&stream->priv->agent_ref, NULL);
+ stream->priv->closed_cancellable = g_cancellable_new ();
+}
+
+static void
+nice_output_stream_init_pollable (GPollableOutputStreamInterface *iface)
+{
+ iface->is_writable = nice_output_stream_is_writable;
+ iface->write_nonblocking = nice_output_stream_write_nonblocking;
+ iface->create_source = nice_output_stream_create_source;
+}
+
+/***
+ * nice_output_stream_new:
+ * @agent: A #NiceAgent
+ * @stream_id: The ID of the agent’s stream to wrap
+ * @component_id: The ID of the agent’s component to wrap
+ *
+ * Create a new #NiceOutputStream wrapping the given stream/component from
+ * @agent, which must be a reliable #NiceAgent.
+ *
+ * The constructed #NiceOutputStream will not hold a reference to @agent. If
+ * @agent is destroyed before the output stream, %G_IO_ERROR_CLOSED will be
+ * returned for all subsequent operations on the stream.
+ *
+ * Returns: The new #NiceOutputStream object
+ *
+ * Since: 0.1.5
+ */
+NiceOutputStream *
+nice_output_stream_new (NiceAgent *agent, guint stream_id, guint component_id)
+{
+ g_return_val_if_fail (NICE_IS_AGENT (agent), NULL);
+ g_return_val_if_fail (stream_id >= 1, NULL);
+ g_return_val_if_fail (component_id >= 1, NULL);
+
+ return g_object_new (NICE_TYPE_OUTPUT_STREAM,
+ "agent", agent,
+ "stream-id", stream_id,
+ "component-id", component_id,
+ NULL);
+}
+
+typedef struct {
+ volatile gint ref_count;
+
+ GCond cond;
+ GMutex mutex;
+
+ gboolean writable;
+ gboolean cancelled;
+} WriteData;
+
+static WriteData *
+write_data_ref (WriteData *write_data)
+{
+ g_atomic_int_inc (&write_data->ref_count);
+ return write_data;
+}
+
+static void
+write_data_unref (WriteData *write_data)
+{
+ if (g_atomic_int_dec_and_test (&write_data->ref_count)) {
+ g_cond_clear (&write_data->cond);
+ g_mutex_clear (&write_data->mutex);
+ g_slice_free (WriteData, write_data);
+ }
+}
+
+static void
+write_cancelled_cb (GCancellable *cancellable, gpointer user_data)
+{
+ WriteData *write_data = user_data;
+
+ g_mutex_lock (&write_data->mutex);
+ g_cond_broadcast (&write_data->cond);
+ write_data->cancelled = TRUE;
+ g_mutex_unlock (&write_data->mutex);
+}
+
+static void
+reliable_transport_writeable_cb (NiceAgent *agent, guint stream_id,
+ guint component_id, gpointer user_data)
+{
+ WriteData *write_data = user_data;
+
+ g_mutex_lock (&write_data->mutex);
+ write_data->writable = TRUE;
+ g_cond_broadcast (&write_data->cond);
+ g_mutex_unlock (&write_data->mutex);
+}
+
+static gssize
+nice_output_stream_write (GOutputStream *stream, const void *buffer, gsize count,
+ GCancellable *cancellable, GError **error)
+{
+ NiceOutputStream *self = NICE_OUTPUT_STREAM (stream);
+ const gchar* buf = buffer;
+ gssize len = 0;
+ gint n_sent;
+ NiceAgent *agent = NULL; /* owned */
+ gulong cancel_id = 0, closed_cancel_id, writeable_id;
+ WriteData *write_data;
+
+ /* Closed streams are not writeable. */
+ if (g_output_stream_is_closed (stream)) {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
+ "Stream is closed.");
+ return -1;
+ }
+
+ /* Has the agent disappeared? */
+ agent = g_weak_ref_get (&self->priv->agent_ref);
+ if (agent == NULL) {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
+ "Stream is closed due to the NiceAgent being finalised.");
+ return -1;
+ }
+
+ if (count == 0) {
+ g_object_unref (agent);
+ return 0;
+ }
+
+ /* FIXME: nice_agent_send() is non-blocking, which is a bit unexpected
+ * since nice_agent_recv() is blocking. Currently this uses a fairly dodgy
+ * GCond solution; would be much better for nice_agent_send() to block
+ * properly in the main loop. */
+ write_data = g_slice_new0 (WriteData);
+ write_data->ref_count = 1;
+ g_mutex_init (&write_data->mutex);
+ g_cond_init (&write_data->cond);
+
+ if (cancellable != NULL) {
+ cancel_id = g_cancellable_connect (cancellable,
+ (GCallback) write_cancelled_cb, write_data_ref (write_data),
+ (GDestroyNotify) write_data_unref);
+ }
+
+ closed_cancel_id = g_cancellable_connect (self->priv->closed_cancellable,
+ (GCallback) write_cancelled_cb, write_data_ref (write_data),
+ (GDestroyNotify) write_data_unref);
+
+ g_mutex_lock (&write_data->mutex);
+
+ writeable_id = g_signal_connect_data (G_OBJECT (agent),
+ "reliable-transport-writable",
+ (GCallback) reliable_transport_writeable_cb, write_data_ref (write_data),
+ (GClosureNotify) G_CALLBACK (write_data_unref), 0);
+
+
+ do {
+ /* Have to unlock while calling into the agent because
+ * it will take the agent lock which will cause a deadlock if one of
+ * the callbacks is called.
+ */
+ if (g_cancellable_is_cancelled (cancellable) ||
+ g_cancellable_is_cancelled (self->priv->closed_cancellable))
+ break;
+
+ write_data->writable = FALSE;
+ g_mutex_unlock (&write_data->mutex);
+
+ n_sent = nice_agent_send (agent, self->priv->stream_id,
+ self->priv->component_id, count - len, buf + len);
+
+ g_mutex_lock (&write_data->mutex);
+
+ if (n_sent <= 0) {
+ if (!write_data->writable && !write_data->cancelled)
+ g_cond_wait (&write_data->cond, &write_data->mutex);
+ } else if (n_sent > 0) {
+ /* Success. */
+ len += n_sent;
+ }
+ } while ((gsize) len < count);
+
+ g_signal_handler_disconnect (G_OBJECT (agent), writeable_id);
+ g_mutex_unlock (&write_data->mutex);
+
+ if (cancel_id)
+ g_cancellable_disconnect (cancellable, cancel_id);
+ g_cancellable_disconnect (self->priv->closed_cancellable, closed_cancel_id);
+
+ if (len == 0) {
+ len = -1;
+ if (!g_cancellable_set_error_if_cancelled (cancellable, error)) {
+ if (g_cancellable_is_cancelled (self->priv->closed_cancellable))
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
+ "Stream has been removed from agent");
+ }
+ }
+
+ write_data_unref (write_data);
+
+ g_object_unref (agent);
+ g_assert (len != 0);
+
+ return len;
+}
+
+static gboolean
+nice_output_stream_close (GOutputStream *stream, GCancellable *cancellable,
+ GError **error)
+{
+ NiceOutputStreamPrivate *priv = NICE_OUTPUT_STREAM (stream)->priv;
+ NiceComponent *component = NULL;
+ NiceStream *_stream = NULL;
+ NiceAgent *agent; /* owned */
+
+ /* Has the agent disappeared? */
+ agent = g_weak_ref_get (&priv->agent_ref);
+ if (agent == NULL)
+ return TRUE;
+
+ agent_lock (agent);
+
+ /* Shut down the write side of the pseudo-TCP stream. */
+ if (agent_find_component (agent, priv->stream_id, priv->component_id,
+ &_stream, &component) && agent->reliable &&
+ !pseudo_tcp_socket_is_closed (component->tcp)) {
+ pseudo_tcp_socket_shutdown (component->tcp, PSEUDO_TCP_SHUTDOWN_WR);
+ }
+
+ agent_unlock (agent);
+
+ g_object_unref (agent);
+
+ return TRUE;
+}
+
+static gboolean
+nice_output_stream_is_writable (GPollableOutputStream *stream)
+{
+ NiceOutputStreamPrivate *priv = NICE_OUTPUT_STREAM (stream)->priv;
+ NiceComponent *component = NULL;
+ NiceStream *_stream = NULL;
+ gboolean retval = FALSE;
+ NiceAgent *agent; /* owned */
+
+ /* Closed streams are not writeable. */
+ if (g_output_stream_is_closed (G_OUTPUT_STREAM (stream)))
+ return FALSE;
+
+ /* Has the agent disappeared? */
+ agent = g_weak_ref_get (&priv->agent_ref);
+ if (agent == NULL)
+ return FALSE;
+
+ agent_lock (agent);
+
+ if (!agent_find_component (agent, priv->stream_id, priv->component_id,
+ &_stream, &component)) {
+ g_warning ("Could not find component %u in stream %u", priv->component_id,
+ priv->stream_id);
+ goto done;
+ }
+ if (component->selected_pair.local != NULL) {
+ NiceSocket *sockptr = component->selected_pair.local->sockptr;
+
+ /* If it’s a reliable agent, see if there’s any space in the pseudo-TCP
+ * output buffer. */
+ if (!nice_socket_is_reliable (sockptr)) {
+ retval = pseudo_tcp_socket_can_send (component->tcp);
+ } else {
+ retval = (g_socket_condition_check (sockptr->fileno, G_IO_OUT) != 0);
+ }
+ }
+
+done:
+ agent_unlock (agent);
+
+ g_object_unref (agent);
+
+ return retval;
+}
+
+static gssize
+nice_output_stream_write_nonblocking (GPollableOutputStream *stream,
+ const void *buffer, gsize count, GError **error)
+{
+ NiceOutputStreamPrivate *priv = NICE_OUTPUT_STREAM (stream)->priv;
+ NiceAgent *agent; /* owned */
+ gint n_sent;
+
+ /* Closed streams are not writeable. */
+ if (g_output_stream_is_closed (G_OUTPUT_STREAM (stream))) {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
+ "Stream is closed.");
+ return -1;
+ }
+
+ /* Has the agent disappeared? */
+ agent = g_weak_ref_get (&priv->agent_ref);
+ if (agent == NULL) {
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
+ "Stream is closed due to the NiceAgent being finalised.");
+ return -1;
+ }
+
+ if (count == 0) {
+ n_sent = 0;
+ goto done;
+ }
+
+ n_sent = nice_agent_send (agent, priv->stream_id, priv->component_id,
+ count, buffer);
+
+ if (n_sent == -1)
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK,
+ g_strerror (EAGAIN));
+
+ done:
+
+ g_object_unref (agent);
+
+ return n_sent;
+}
+
+static GSource *
+nice_output_stream_create_source (GPollableOutputStream *stream,
+ GCancellable *cancellable)
+{
+ NiceOutputStreamPrivate *priv = NICE_OUTPUT_STREAM (stream)->priv;
+ GSource *component_source = NULL;
+ NiceComponent *component = NULL;
+ NiceStream *_stream = NULL;
+ NiceAgent *agent; /* owned */
+
+ component_source = g_pollable_source_new (G_OBJECT (stream));
+
+ if (cancellable) {
+ GSource *cancellable_source = g_cancellable_source_new (cancellable);
+
+ g_source_set_dummy_callback (cancellable_source);
+ g_source_add_child_source (component_source, cancellable_source);
+ g_source_unref (cancellable_source);
+ }
+
+ /* Closed streams cannot have sources. */
+ if (g_output_stream_is_closed (G_OUTPUT_STREAM (stream)))
+ return component_source;
+
+ /* Has the agent disappeared? */
+ agent = g_weak_ref_get (&priv->agent_ref);
+ if (agent == NULL)
+ return component_source;
+
+ agent_lock (agent);
+
+ /* Grab the socket for this component. */
+ if (!agent_find_component (agent, priv->stream_id, priv->component_id,
+ &_stream, &component)) {
+ g_warning ("Could not find component %u in stream %u", priv->component_id,
+ priv->stream_id);
+ goto done;
+ }
+
+ if (component->tcp_writable_cancellable) {
+ GSource *cancellable_source =
+ g_cancellable_source_new (component->tcp_writable_cancellable);
+
+ g_source_set_dummy_callback (cancellable_source);
+ g_source_add_child_source (component_source, cancellable_source);
+ g_source_unref (cancellable_source);
+ }
+
+done:
+ agent_unlock (agent);
+
+ g_object_unref (agent);
+
+ return component_source;
+}
+
+static void
+streams_removed_cb (NiceAgent *agent, guint *stream_ids, gpointer user_data)
+{
+ NiceOutputStream *self = NICE_OUTPUT_STREAM (user_data);
+ guint i;
+
+ for (i = 0; stream_ids[i] != 0; i++) {
+ if (stream_ids[i] == self->priv->stream_id) {
+ /* The socket has been closed. */
+ g_cancellable_cancel (self->priv->closed_cancellable);
+
+ g_output_stream_close (G_OUTPUT_STREAM (self), NULL, NULL);
+ break;
+ }
+ }
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2010, 2013 Collabora Ltd.
+ * Contact: Youness Alaoui
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef __NICE_OUTPUT_STREAM_H__
+#define __NICE_OUTPUT_STREAM_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+#include "agent.h"
+
+G_BEGIN_DECLS
+
+/* TYPE MACROS */
+#define NICE_TYPE_OUTPUT_STREAM \
+ (nice_output_stream_get_type ())
+#define NICE_OUTPUT_STREAM(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), NICE_TYPE_OUTPUT_STREAM, \
+ NiceOutputStream))
+#define NICE_OUTPUT_STREAM_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), NICE_TYPE_OUTPUT_STREAM, \
+ NiceOutputStreamClass))
+#define NICE_IS_OUTPUT_STREAM(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), NICE_TYPE_OUTPUT_STREAM))
+#define NICE_IS_OUTPUT_STREAM_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), NICE_TYPE_OUTPUT_STREAM))
+#define NICE_OUTPUT_STREAM_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), NICE_TYPE_OUTPUT_STREAM, \
+ NiceOutputStreamClass))
+
+
+typedef struct _NiceOutputStreamPrivate NiceOutputStreamPrivate;
+typedef struct _NiceOutputStreamClass NiceOutputStreamClass;
+typedef struct _NiceOutputStream NiceOutputStream;
+
+
+GType nice_output_stream_get_type (void);
+
+struct _NiceOutputStreamClass
+{
+ GOutputStreamClass parent_class;
+};
+
+struct _NiceOutputStream
+{
+ GOutputStream parent_instance;
+ NiceOutputStreamPrivate *priv;
+};
+
+
+NiceOutputStream *nice_output_stream_new (NiceAgent *agent,
+ guint stream_id, guint component_id);
+
+G_END_DECLS
+
+#endif /* __NICE_OUTPUT_STREAM_H__ */
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2010, 2014 Collabora Ltd.
+ * Contact: Philip Withnall
+
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ * Philip Withnall, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+/* Reproducing license from libjingle for copied code */
+
+/*
+ * libjingle
+ * Copyright 2004--2005, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+#include <glib.h>
+
+#ifndef G_OS_WIN32
+# include <arpa/inet.h>
+#endif
+
+#include "pseudotcp.h"
+#include "agent-priv.h"
+
+struct _PseudoTcpSocketClass {
+ GObjectClass parent_class;
+};
+
+typedef struct _PseudoTcpSocketPrivate PseudoTcpSocketPrivate;
+
+
+struct _PseudoTcpSocket {
+ GObject parent;
+ PseudoTcpSocketPrivate *priv;
+};
+
+G_DEFINE_TYPE (PseudoTcpSocket, pseudo_tcp_socket, G_TYPE_OBJECT);
+
+//////////////////////////////////////////////////////////////////////
+// Network Constants
+//////////////////////////////////////////////////////////////////////
+
+// Standard MTUs
+const guint16 PACKET_MAXIMUMS[] = {
+ 65535, // Theoretical maximum, Hyperchannel
+ 32000, // Nothing
+ 17914, // 16Mb IBM Token Ring
+ 8166, // IEEE 802.4
+ //4464, // IEEE 802.5 (4Mb max)
+ 4352, // FDDI
+ //2048, // Wideband Network
+ 2002, // IEEE 802.5 (4Mb recommended)
+ //1536, // Expermental Ethernet Networks
+ //1500, // Ethernet, Point-to-Point (default)
+ 1492, // IEEE 802.3
+ 1006, // SLIP, ARPANET
+ //576, // X.25 Networks
+ //544, // DEC IP Portal
+ //512, // NETBIOS
+ 508, // IEEE 802/Source-Rt Bridge, ARCNET
+ 296, // Point-to-Point (low delay)
+ //68, // Official minimum
+ 0, // End of list marker
+};
+
+// FIXME: This is a reasonable MTU, but we should get it from the lower layer
+#define DEF_MTU 1400
+#define MAX_PACKET 65532
+// Note: we removed lowest level because packet overhead was larger!
+#define MIN_PACKET 296
+
+// (+ up to 40 bytes of options?)
+#define IP_HEADER_SIZE 20
+#define ICMP_HEADER_SIZE 8
+#define UDP_HEADER_SIZE 8
+// TODO: Make JINGLE_HEADER_SIZE transparent to this code?
+// when relay framing is in use
+#define JINGLE_HEADER_SIZE 64
+
+//////////////////////////////////////////////////////////////////////
+// Global Constants and Functions
+//////////////////////////////////////////////////////////////////////
+//
+// 0 1 2 3
+// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// 0 | Conversation Number |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// 4 | Sequence Number |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// 8 | Acknowledgment Number |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// | | |U|A|P|R|S|F| |
+// 12 | Control | |R|C|S|S|Y|I| Window |
+// | | |G|K|H|T|N|N| |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// 16 | Timestamp sending |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// 20 | Timestamp receiving |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+// 24 | data |
+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//
+//////////////////////////////////////////////////////////////////////
+
+#define MAX_SEQ 0xFFFFFFFF
+#define HEADER_SIZE 24
+
+#define PACKET_OVERHEAD (HEADER_SIZE + UDP_HEADER_SIZE + \
+ IP_HEADER_SIZE + JINGLE_HEADER_SIZE)
+
+// MIN_RTO = 1 second (RFC6298, Sec 2.4)
+#define MIN_RTO 1000
+#define DEF_RTO 1000 /* 1 seconds (RFC 6298 sect 2.1) */
+#define MAX_RTO 60000 /* 60 seconds */
+#define DEFAULT_ACK_DELAY 100 /* 100 milliseconds */
+#define DEFAULT_NO_DELAY FALSE
+
+#define DEFAULT_RCV_BUF_SIZE (60 * 1024)
+#define DEFAULT_SND_BUF_SIZE (90 * 1024)
+
+/* NOTE: This must fit in 8 bits. This is used on the wire. */
+typedef enum {
+ /* Google-provided options: */
+ TCP_OPT_EOL = 0, /* end of list */
+ TCP_OPT_NOOP = 1, /* no-op */
+ TCP_OPT_MSS = 2, /* maximum segment size */
+ TCP_OPT_WND_SCALE = 3, /* window scale factor */
+ /* libnice extensions: */
+ TCP_OPT_FIN_ACK = 254, /* FIN-ACK support */
+} TcpOption;
+
+
+/*
+#define FLAG_SYN 0x02
+#define FLAG_ACK 0x10
+*/
+
+/* NOTE: This must fit in 5 bits. This is used on the wire. */
+typedef enum {
+ FLAG_NONE = 0,
+ FLAG_FIN = 1 << 0,
+ FLAG_CTL = 1 << 1,
+ FLAG_RST = 1 << 2,
+} TcpFlags;
+
+#define CTL_CONNECT 0
+//#define CTL_REDIRECT 1
+#define CTL_EXTRA 255
+
+
+#define CTRL_BOUND 0x80000000
+
+/* Maximum segment lifetime (1 minute).
+ * RFC 793, §3.3 specifies 2 minutes; but Linux uses 1 minute, so let’s go with
+ * that. */
+#define TCP_MSL (60 * 1000)
+
+// If there are no pending clocks, wake up every 4 seconds
+#define DEFAULT_TIMEOUT 4000
+// If the connection is closed, once per minute
+#define CLOSED_TIMEOUT (60 * 1000)
+/* Timeout after reaching the TIME_WAIT state, in milliseconds.
+ * See: RFC 1122, §4.2.2.13.
+ *
+ * XXX: Since we can control the underlying layer’s channel ID, we can guarantee
+ * delayed segments won’t affect subsequent connections, so can radically
+ * shorten the TIME-WAIT timeout (to the extent that it basically doesn’t
+ * exist). It would normally be (2 * TCP_MSL). */
+#define TIME_WAIT_TIMEOUT 1
+
+//////////////////////////////////////////////////////////////////////
+// Helper Functions
+//////////////////////////////////////////////////////////////////////
+#ifndef G_OS_WIN32
+# define min(first, second) ((first) < (second) ? (first) : (second))
+# define max(first, second) ((first) > (second) ? (first) : (second))
+#endif
+
+static guint32
+bound(guint32 lower, guint32 middle, guint32 upper)
+{
+ return min (max (lower, middle), upper);
+}
+
+static gboolean
+time_is_between(guint32 later, guint32 middle, guint32 earlier)
+{
+ if (earlier <= later) {
+ return ((earlier <= middle) && (middle <= later));
+ } else {
+ return !((later < middle) && (middle < earlier));
+ }
+}
+
+static gint32
+time_diff(guint32 later, guint32 earlier)
+{
+ guint32 LAST = 0xFFFFFFFF;
+ guint32 HALF = 0x80000000;
+ if (time_is_between(earlier + HALF, later, earlier)) {
+ if (earlier <= later) {
+ return (long)(later - earlier);
+ } else {
+ return (long)(later + (LAST - earlier) + 1);
+ }
+ } else {
+ if (later <= earlier) {
+ return -(long) (earlier - later);
+ } else {
+ return -(long)(earlier + (LAST - later) + 1);
+ }
+ }
+}
+
+////////////////////////////////////////////////////////
+// PseudoTcpFifo works exactly like FifoBuffer in libjingle
+////////////////////////////////////////////////////////
+
+
+typedef struct {
+ guint8 *buffer;
+ gsize buffer_length;
+ gsize data_length;
+ gsize read_position;
+} PseudoTcpFifo;
+
+
+static void
+pseudo_tcp_fifo_init (PseudoTcpFifo *b, gsize size)
+{
+ b->buffer = g_slice_alloc (size);
+ b->buffer_length = size;
+}
+
+static void
+pseudo_tcp_fifo_clear (PseudoTcpFifo *b)
+{
+ if (b->buffer)
+ g_slice_free1 (b->buffer_length, b->buffer);
+ b->buffer = NULL;
+ b->buffer_length = 0;
+}
+
+static gsize
+pseudo_tcp_fifo_get_buffered (PseudoTcpFifo *b)
+{
+ return b->data_length;
+}
+
+static gboolean
+pseudo_tcp_fifo_set_capacity (PseudoTcpFifo *b, gsize size)
+{
+ if (b->data_length > size)
+ return FALSE;
+
+ if (size != b->data_length) {
+ guint8 *buffer = g_slice_alloc (size);
+ gsize copy = b->data_length;
+ gsize tail_copy = min (copy, b->buffer_length - b->read_position);
+
+ memcpy (buffer, &b->buffer[b->read_position], tail_copy);
+ memcpy (buffer + tail_copy, &b->buffer[0], copy - tail_copy);
+ g_slice_free1 (b->buffer_length, b->buffer);
+ b->buffer = buffer;
+ b->buffer_length = size;
+ b->read_position = 0;
+ }
+
+ return TRUE;
+}
+
+static void
+pseudo_tcp_fifo_consume_read_data (PseudoTcpFifo *b, gsize size)
+{
+ g_assert (size <= b->data_length);
+
+ b->read_position = (b->read_position + size) % b->buffer_length;
+ b->data_length -= size;
+}
+
+static void
+pseudo_tcp_fifo_consume_write_buffer (PseudoTcpFifo *b, gsize size)
+{
+ g_assert (size <= b->buffer_length - b->data_length);
+
+ b->data_length += size;
+}
+
+static gsize
+pseudo_tcp_fifo_get_write_remaining (PseudoTcpFifo *b)
+{
+ return b->buffer_length - b->data_length;
+}
+
+static gsize
+pseudo_tcp_fifo_read_offset (PseudoTcpFifo *b, guint8 *buffer, gsize bytes,
+ gsize offset)
+{
+ gsize available = b->data_length - offset;
+ gsize read_position = (b->read_position + offset) % b->buffer_length;
+ gsize copy = min (bytes, available);
+ gsize tail_copy = min(copy, b->buffer_length - read_position);
+
+ /* EOS */
+ if (offset >= b->data_length)
+ return 0;
+
+ memcpy(buffer, &b->buffer[read_position], tail_copy);
+ memcpy(buffer + tail_copy, &b->buffer[0], copy - tail_copy);
+
+ return copy;
+}
+
+static gsize
+pseudo_tcp_fifo_write_offset (PseudoTcpFifo *b, const guint8 *buffer,
+ gsize bytes, gsize offset)
+{
+ gsize available = b->buffer_length - b->data_length - offset;
+ gsize write_position = (b->read_position + b->data_length + offset)
+ % b->buffer_length;
+ gsize copy = min (bytes, available);
+ gsize tail_copy = min(copy, b->buffer_length - write_position);
+
+ if (b->data_length + offset >= b->buffer_length) {
+ return 0;
+ }
+
+ memcpy(&b->buffer[write_position], buffer, tail_copy);
+ memcpy(&b->buffer[0], buffer + tail_copy, copy - tail_copy);
+
+ return copy;
+}
+
+static gsize
+pseudo_tcp_fifo_read (PseudoTcpFifo *b, guint8 *buffer, gsize bytes)
+{
+ gsize copy;
+
+ copy = pseudo_tcp_fifo_read_offset (b, buffer, bytes, 0);
+
+ b->read_position = (b->read_position + copy) % b->buffer_length;
+ b->data_length -= copy;
+
+ return copy;
+}
+
+static gsize
+pseudo_tcp_fifo_write (PseudoTcpFifo *b, const guint8 *buffer, gsize bytes)
+{
+ gsize copy;
+
+ copy = pseudo_tcp_fifo_write_offset (b, buffer, bytes, 0);
+ b->data_length += copy;
+
+ return copy;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+// PseudoTcp
+//////////////////////////////////////////////////////////////////////
+
+/* Only used if FIN-ACK support is disabled. */
+typedef enum {
+ SD_NONE,
+ SD_GRACEFUL,
+ SD_FORCEFUL
+} Shutdown;
+
+typedef enum {
+ sfNone,
+ sfDelayedAck,
+ sfImmediateAck,
+ sfFin,
+ sfRst,
+ sfDuplicateAck,
+} SendFlags;
+
+typedef struct {
+ guint32 conv, seq, ack;
+ TcpFlags flags;
+ guint16 wnd;
+ const gchar * data;
+ guint32 len;
+ guint32 tsval, tsecr;
+} Segment;
+
+typedef struct {
+ guint32 seq, len;
+ guint8 xmit;
+ TcpFlags flags;
+} SSegment;
+
+typedef struct {
+ guint32 seq, len;
+} RSegment;
+
+/**
+ * ClosedownSource:
+ * @CLOSEDOWN_LOCAL: Error detected locally, or connection forcefully closed
+ * locally.
+ * @CLOSEDOWN_REMOTE: RST segment received from the peer.
+ *
+ * Reasons for calling closedown().
+ *
+ * Since: 0.1.8
+ */
+typedef enum {
+ CLOSEDOWN_LOCAL,
+ CLOSEDOWN_REMOTE,
+} ClosedownSource;
+
+
+struct _PseudoTcpSocketPrivate {
+ PseudoTcpCallbacks callbacks;
+
+ Shutdown shutdown; /* only used if !support_fin_ack */
+ gboolean shutdown_reads;
+ gint error;
+
+ // TCB data
+ PseudoTcpState state;
+ guint32 conv;
+ gboolean bReadEnable, bWriteEnable, bOutgoing;
+ guint32 last_traffic;
+
+ // Incoming data
+ GList *rlist;
+ guint32 rbuf_len, rcv_nxt, rcv_wnd, lastrecv;
+ guint8 rwnd_scale; // Window scale factor
+ PseudoTcpFifo rbuf;
+ guint32 rcv_fin; /* sequence number of the received FIN octet, or 0 */
+
+ // Outgoing data
+ GQueue slist;
+ GQueue unsent_slist;
+ guint32 sbuf_len, snd_nxt, snd_wnd, lastsend;
+ guint32 snd_una; /* oldest unacknowledged sequence number */
+ guint8 swnd_scale; // Window scale factor
+ PseudoTcpFifo sbuf;
+
+ // Maximum segment size, estimated protocol level, largest segment sent
+ guint32 mss, msslevel, largest, mtu_advise;
+ // Retransmit timer
+ guint32 rto_base;
+
+ // Timestamp tracking
+ guint32 ts_recent, ts_lastack;
+
+ // Round-trip calculation
+ guint32 rx_rttvar, rx_srtt, rx_rto;
+
+ // Congestion avoidance, Fast retransmit/recovery, Delayed ACKs
+ guint32 ssthresh, cwnd;
+ guint8 dup_acks;
+ guint32 recover;
+ gboolean fast_recovery;
+ guint32 t_ack; /* time a delayed ack was scheduled; 0 if no acks scheduled */
+ guint32 last_acked_ts;
+
+ gboolean use_nagling;
+ guint32 ack_delay;
+
+ // This is used by unit tests to test backward compatibility of
+ // PseudoTcp implementations that don't support window scaling.
+ gboolean support_wnd_scale;
+
+ /* Current time. Typically only used for testing, when non-zero. When zero,
+ * the system monotonic clock is used. Units: monotonic milliseconds. */
+ guint32 current_time;
+
+ /* This is used by compatible implementations (with the TCP_OPT_FIN_ACK
+ * option) to enable correct FIN-ACK connection termination. Defaults to
+ * TRUE unless no compatible option is received. */
+ gboolean support_fin_ack;
+};
+
+#define LARGER(a,b) (((a) - (b) - 1) < (G_MAXUINT32 >> 1))
+#define LARGER_OR_EQUAL(a,b) (((a) - (b)) < (G_MAXUINT32 >> 1))
+#define SMALLER(a,b) LARGER ((b),(a))
+#define SMALLER_OR_EQUAL(a,b) LARGER_OR_EQUAL ((b),(a))
+
+/* properties */
+enum
+{
+ PROP_CONVERSATION = 1,
+ PROP_CALLBACKS,
+ PROP_STATE,
+ PROP_ACK_DELAY,
+ PROP_NO_DELAY,
+ PROP_RCV_BUF,
+ PROP_SND_BUF,
+ PROP_SUPPORT_FIN_ACK,
+ LAST_PROPERTY
+};
+
+
+static void pseudo_tcp_socket_get_property (GObject *object, guint property_id,
+ GValue *value, GParamSpec *pspec);
+static void pseudo_tcp_socket_set_property (GObject *object, guint property_id,
+ const GValue *value, GParamSpec *pspec);
+static void pseudo_tcp_socket_finalize (GObject *object);
+
+
+static void queue_connect_message (PseudoTcpSocket *self);
+static guint32 queue (PseudoTcpSocket *self, const gchar *data,
+ guint32 len, TcpFlags flags);
+static PseudoTcpWriteResult packet(PseudoTcpSocket *self, guint32 seq,
+ TcpFlags flags, guint32 offset, guint32 len, guint32 now);
+static gboolean parse (PseudoTcpSocket *self,
+ const guint8 *_header_buf, gsize header_buf_len,
+ const guint8 *data_buf, gsize data_buf_len);
+static gboolean process(PseudoTcpSocket *self, Segment *seg);
+static int transmit(PseudoTcpSocket *self, SSegment *sseg, guint32 now);
+static void attempt_send(PseudoTcpSocket *self, SendFlags sflags);
+static void closedown (PseudoTcpSocket *self, guint32 err,
+ ClosedownSource source);
+static void adjustMTU(PseudoTcpSocket *self);
+static void parse_options (PseudoTcpSocket *self, const guint8 *data,
+ guint32 len);
+static void resize_send_buffer (PseudoTcpSocket *self, guint32 new_size);
+static void resize_receive_buffer (PseudoTcpSocket *self, guint32 new_size);
+static void set_state (PseudoTcpSocket *self, PseudoTcpState new_state);
+static void set_state_established (PseudoTcpSocket *self);
+static void set_state_closed (PseudoTcpSocket *self, guint32 err);
+
+static const gchar *pseudo_tcp_state_get_name (PseudoTcpState state);
+static gboolean pseudo_tcp_state_has_sent_fin (PseudoTcpState state);
+static gboolean pseudo_tcp_state_has_received_fin (PseudoTcpState state);
+static gboolean pseudo_tcp_state_has_received_fin_ack (PseudoTcpState state);
+
+// The following logging is for detailed (packet-level) pseudotcp analysis only.
+static PseudoTcpDebugLevel debug_level = PSEUDO_TCP_DEBUG_NONE;
+
+#define DEBUG(level, fmt, ...) \
+ if (debug_level >= level) \
+ g_log (level == PSEUDO_TCP_DEBUG_NORMAL ? "libnice-pseudotcp" : "libnice-pseudotcp-verbose", G_LOG_LEVEL_DEBUG, "PseudoTcpSocket %p %s: " fmt, \
+ self, pseudo_tcp_state_get_name (self->priv->state), ## __VA_ARGS__)
+
+void
+pseudo_tcp_set_debug_level (PseudoTcpDebugLevel level)
+{
+ debug_level = level;
+}
+
+static guint32
+get_current_time (PseudoTcpSocket *socket)
+{
+ if (G_UNLIKELY (socket->priv->current_time != 0))
+ return socket->priv->current_time;
+
+ return g_get_monotonic_time () / 1000;
+}
+
+void
+pseudo_tcp_socket_set_time (PseudoTcpSocket *self, guint32 current_time)
+{
+ self->priv->current_time = current_time;
+}
+
+static void
+pseudo_tcp_socket_class_init (PseudoTcpSocketClass *cls)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (cls);
+
+ object_class->get_property = pseudo_tcp_socket_get_property;
+ object_class->set_property = pseudo_tcp_socket_set_property;
+ object_class->finalize = pseudo_tcp_socket_finalize;
+
+ g_object_class_install_property (object_class, PROP_CONVERSATION,
+ g_param_spec_uint ("conversation", "TCP Conversation ID",
+ "The TCP Conversation ID",
+ 0, G_MAXUINT32, 0,
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (object_class, PROP_CALLBACKS,
+ g_param_spec_pointer ("callbacks", "PseudoTcp socket callbacks",
+ "Structure with the callbacks to call when PseudoTcp events happen",
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (object_class, PROP_STATE,
+ g_param_spec_uint ("state", "PseudoTcp State",
+ "The current state (enum PseudoTcpState) of the PseudoTcp socket",
+ PSEUDO_TCP_LISTEN, PSEUDO_TCP_CLOSED, PSEUDO_TCP_LISTEN,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (object_class, PROP_ACK_DELAY,
+ g_param_spec_uint ("ack-delay", "ACK Delay",
+ "Delayed ACK timeout (in milliseconds)",
+ 0, G_MAXUINT, DEFAULT_ACK_DELAY,
+ G_PARAM_READWRITE| G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (object_class, PROP_NO_DELAY,
+ g_param_spec_boolean ("no-delay", "No Delay",
+ "Disable the Nagle algorithm (like the TCP_NODELAY option)",
+ DEFAULT_NO_DELAY,
+ G_PARAM_READWRITE| G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (object_class, PROP_RCV_BUF,
+ g_param_spec_uint ("rcv-buf", "Receive Buffer",
+ "Receive Buffer size",
+ 1, G_MAXUINT, DEFAULT_RCV_BUF_SIZE,
+ G_PARAM_READWRITE| G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (object_class, PROP_SND_BUF,
+ g_param_spec_uint ("snd-buf", "Send Buffer",
+ "Send Buffer size",
+ 1, G_MAXUINT, DEFAULT_SND_BUF_SIZE,
+ G_PARAM_READWRITE| G_PARAM_STATIC_STRINGS));
+
+ /**
+ * PseudoTcpSocket:support-fin-ack:
+ *
+ * Whether to support the FIN–ACK extension to the pseudo-TCP protocol for
+ * this socket. The extension is only compatible with other libnice pseudo-TCP
+ * stacks, and not with Jingle pseudo-TCP stacks. If enabled, support is
+ * negotiatied on connection setup, so it is safe for a #PseudoTcpSocket with
+ * support enabled to be used with one with it disabled, or with a Jingle
+ * pseudo-TCP socket which doesn’t support it at all.
+ *
+ * Support is enabled by default.
+ *
+ * Since: 0.1.8
+ */
+ g_object_class_install_property (object_class, PROP_SUPPORT_FIN_ACK,
+ g_param_spec_boolean ("support-fin-ack", "Support FIN–ACK",
+ "Whether to enable the optional FIN–ACK support.",
+ TRUE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+}
+
+
+static void
+pseudo_tcp_socket_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ PseudoTcpSocket *self = PSEUDO_TCP_SOCKET (object);
+
+ switch (property_id) {
+ case PROP_CONVERSATION:
+ g_value_set_uint (value, self->priv->conv);
+ break;
+ case PROP_CALLBACKS:
+ g_value_set_pointer (value, (gpointer) &self->priv->callbacks);
+ break;
+ case PROP_STATE:
+ g_value_set_uint (value, self->priv->state);
+ break;
+ case PROP_ACK_DELAY:
+ g_value_set_uint (value, self->priv->ack_delay);
+ break;
+ case PROP_NO_DELAY:
+ g_value_set_boolean (value, !self->priv->use_nagling);
+ break;
+ case PROP_RCV_BUF:
+ g_value_set_uint (value, self->priv->rbuf_len);
+ break;
+ case PROP_SND_BUF:
+ g_value_set_uint (value, self->priv->sbuf_len);
+ break;
+ case PROP_SUPPORT_FIN_ACK:
+ g_value_set_boolean (value, self->priv->support_fin_ack);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+pseudo_tcp_socket_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ PseudoTcpSocket *self = PSEUDO_TCP_SOCKET (object);
+
+ switch (property_id) {
+ case PROP_CONVERSATION:
+ self->priv->conv = g_value_get_uint (value);
+ break;
+ case PROP_CALLBACKS:
+ {
+ PseudoTcpCallbacks *c = g_value_get_pointer (value);
+ self->priv->callbacks = *c;
+ }
+ break;
+ case PROP_ACK_DELAY:
+ self->priv->ack_delay = g_value_get_uint (value);
+ break;
+ case PROP_NO_DELAY:
+ self->priv->use_nagling = !g_value_get_boolean (value);
+ break;
+ case PROP_RCV_BUF:
+ g_return_if_fail (self->priv->state == PSEUDO_TCP_LISTEN);
+ resize_receive_buffer (self, g_value_get_uint (value));
+ break;
+ case PROP_SND_BUF:
+ g_return_if_fail (self->priv->state == PSEUDO_TCP_LISTEN);
+ resize_send_buffer (self, g_value_get_uint (value));
+ break;
+ case PROP_SUPPORT_FIN_ACK:
+ self->priv->support_fin_ack = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+pseudo_tcp_socket_finalize (GObject *object)
+{
+ PseudoTcpSocket *self = PSEUDO_TCP_SOCKET (object);
+ PseudoTcpSocketPrivate *priv = self->priv;
+ GList *i;
+ SSegment *sseg;
+
+ if (priv == NULL)
+ return;
+
+ while ((sseg = g_queue_pop_head (&priv->slist)))
+ g_slice_free (SSegment, sseg);
+ g_queue_clear (&priv->unsent_slist);
+ for (i = priv->rlist; i; i = i->next) {
+ RSegment *rseg = i->data;
+ g_slice_free (RSegment, rseg);
+ }
+ g_list_free (priv->rlist);
+ priv->rlist = NULL;
+
+ pseudo_tcp_fifo_clear (&priv->rbuf);
+ pseudo_tcp_fifo_clear (&priv->sbuf);
+
+ g_free (priv);
+ self->priv = NULL;
+
+ if (G_OBJECT_CLASS (pseudo_tcp_socket_parent_class)->finalize)
+ G_OBJECT_CLASS (pseudo_tcp_socket_parent_class)->finalize (object);
+}
+
+
+static void
+pseudo_tcp_socket_init (PseudoTcpSocket *obj)
+{
+ /* Use g_new0, and do not use g_object_set_private because the size of
+ * our private data is too big (150KB+) and the g_slice_allow cannot allocate
+ * it. So we handle the private ourselves */
+ PseudoTcpSocketPrivate *priv = g_new0 (PseudoTcpSocketPrivate, 1);
+
+ obj->priv = priv;
+
+ priv->shutdown = SD_NONE;
+ priv->error = 0;
+
+ priv->rbuf_len = DEFAULT_RCV_BUF_SIZE;
+ pseudo_tcp_fifo_init (&priv->rbuf, priv->rbuf_len);
+ priv->sbuf_len = DEFAULT_SND_BUF_SIZE;
+ pseudo_tcp_fifo_init (&priv->sbuf, priv->sbuf_len);
+
+ priv->state = PSEUDO_TCP_LISTEN;
+ priv->conv = 0;
+ g_queue_init (&priv->slist);
+ g_queue_init (&priv->unsent_slist);
+ priv->rcv_wnd = priv->rbuf_len;
+ priv->rwnd_scale = priv->swnd_scale = 0;
+ priv->snd_nxt = 0;
+ priv->snd_wnd = 1;
+ priv->snd_una = priv->rcv_nxt = 0;
+ priv->bReadEnable = TRUE;
+ priv->bWriteEnable = FALSE;
+ priv->rcv_fin = 0;
+
+ priv->t_ack = 0;
+
+ priv->msslevel = 0;
+ priv->largest = 0;
+ priv->mss = MIN_PACKET - PACKET_OVERHEAD;
+ priv->mtu_advise = DEF_MTU;
+
+ priv->rto_base = 0;
+
+ priv->cwnd = 2 * priv->mss;
+ priv->ssthresh = priv->rbuf_len;
+ priv->lastrecv = priv->lastsend = priv->last_traffic = 0;
+ priv->bOutgoing = FALSE;
+
+ priv->dup_acks = 0;
+ priv->recover = 0;
+ priv->last_acked_ts = 0;
+
+ priv->ts_recent = priv->ts_lastack = 0;
+
+ priv->rx_rto = DEF_RTO;
+ priv->rx_srtt = priv->rx_rttvar = 0;
+
+ priv->ack_delay = DEFAULT_ACK_DELAY;
+ priv->use_nagling = !DEFAULT_NO_DELAY;
+
+ priv->support_wnd_scale = TRUE;
+ priv->support_fin_ack = TRUE;
+}
+
+PseudoTcpSocket *pseudo_tcp_socket_new (guint32 conversation,
+ PseudoTcpCallbacks *callbacks)
+{
+
+ return g_object_new (PSEUDO_TCP_SOCKET_TYPE,
+ "conversation", conversation,
+ "callbacks", callbacks,
+ NULL);
+}
+
+static void
+queue_connect_message (PseudoTcpSocket *self)
+{
+ PseudoTcpSocketPrivate *priv = self->priv;
+ guint8 buf[8];
+ gsize size = 0;
+
+ buf[size++] = CTL_CONNECT;
+
+ if (priv->support_wnd_scale) {
+ buf[size++] = TCP_OPT_WND_SCALE;
+ buf[size++] = 1;
+ buf[size++] = priv->rwnd_scale;
+ }
+
+ if (priv->support_fin_ack) {
+ buf[size++] = TCP_OPT_FIN_ACK;
+ buf[size++] = 1; /* option length; zero is invalid (RFC 1122, §4.2.2.5) */
+ buf[size++] = 0; /* currently unused */
+ }
+
+ priv->snd_wnd = size;
+
+ queue (self, (char *) buf, size, FLAG_CTL);
+}
+
+static void
+queue_fin_message (PseudoTcpSocket *self)
+{
+ g_assert (self->priv->support_fin_ack);
+
+ /* FIN segments are always zero-length. */
+ queue (self, "", 0, FLAG_FIN);
+}
+
+static void
+queue_rst_message (PseudoTcpSocket *self)
+{
+ g_assert (self->priv->support_fin_ack);
+
+ /* RST segments are always zero-length. */
+ queue (self, "", 0, FLAG_RST);
+}
+
+gboolean
+pseudo_tcp_socket_connect(PseudoTcpSocket *self)
+{
+ PseudoTcpSocketPrivate *priv = self->priv;
+
+ if (priv->state != PSEUDO_TCP_LISTEN) {
+ priv->error = EINVAL;
+ return FALSE;
+ }
+
+ set_state (self, PSEUDO_TCP_SYN_SENT);
+
+ queue_connect_message (self);
+ attempt_send(self, sfNone);
+
+ return TRUE;
+}
+
+void
+pseudo_tcp_socket_notify_mtu(PseudoTcpSocket *self, guint16 mtu)
+{
+ PseudoTcpSocketPrivate *priv = self->priv;
+ priv->mtu_advise = mtu;
+ if (priv->state == PSEUDO_TCP_ESTABLISHED) {
+ adjustMTU(self);
+ }
+}
+
+void
+pseudo_tcp_socket_notify_clock(PseudoTcpSocket *self)
+{
+ PseudoTcpSocketPrivate *priv = self->priv;
+ guint32 now = get_current_time (self);
+
+ if (priv->state == PSEUDO_TCP_CLOSED)
+ return;
+
+ /* If in the TIME-WAIT state, any delayed segments have passed and the
+ * connection can be considered closed from both ends.
+ * FIXME: This should probably actually compare a timestamp before
+ * operating. */
+ if (priv->support_fin_ack && priv->state == PSEUDO_TCP_TIME_WAIT) {
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL,
+ "Notified clock in TIME-WAIT state; closing connection.");
+ set_state_closed (self, 0);
+ }
+
+ /* If in the LAST-ACK state, resend the FIN because it hasn’t been ACKed yet.
+ * FIXME: This should probably actually compare a timestamp before
+ * operating. */
+ if (priv->support_fin_ack && priv->state == PSEUDO_TCP_LAST_ACK) {
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL,
+ "Notified clock in LAST-ACK state; resending FIN segment.");
+ queue_fin_message (self);
+ attempt_send (self, sfFin);
+ }
+
+ // Check if it's time to retransmit a segment
+ if (priv->rto_base &&
+ (time_diff(priv->rto_base + priv->rx_rto, now) <= 0)) {
+ if (g_queue_get_length (&priv->slist) == 0) {
+ g_assert_not_reached ();
+ } else {
+ // Note: (priv->slist.front().xmit == 0)) {
+ // retransmit segments
+ guint32 nInFlight;
+ guint32 rto_limit;
+ int transmit_status;
+
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "timeout retransmit (rto: %u) "
+ "(rto_base: %u) (now: %u) (dup_acks: %u)",
+ priv->rx_rto, priv->rto_base, now, (guint) priv->dup_acks);
+
+ transmit_status = transmit(self, g_queue_peek_head (&priv->slist), now);
+ if (transmit_status != 0) {
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL,
+ "Error transmitting segment. Closing down.");
+ closedown (self, transmit_status, CLOSEDOWN_LOCAL);
+ return;
+ }
+
+ nInFlight = priv->snd_nxt - priv->snd_una;
+ priv->ssthresh = max(nInFlight / 2, 2 * priv->mss);
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "ssthresh: %u = (nInFlight: %u / 2) + "
+ "2 * mss: %u", priv->ssthresh, nInFlight, priv->mss);
+ //LOG(LS_INFO) << "priv->ssthresh: " << priv->ssthresh << " nInFlight: " << nInFlight << " priv->mss: " << priv->mss;
+ priv->cwnd = priv->mss;
+
+ // Back off retransmit timer. Note: the limit is lower when connecting.
+ rto_limit = (priv->state < PSEUDO_TCP_ESTABLISHED) ? DEF_RTO : MAX_RTO;
+ priv->rx_rto = min(rto_limit, priv->rx_rto * 2);
+ priv->rto_base = now;
+
+ priv->recover = priv->snd_nxt;
+ if (priv->dup_acks >= 3) {
+ priv->dup_acks = 0;
+ priv->fast_recovery = FALSE;
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "exit recovery on timeout");
+ }
+ }
+ }
+
+ // Check if it's time to probe closed windows
+ if ((priv->snd_wnd == 0)
+ && (time_diff(priv->lastsend + priv->rx_rto, now) <= 0)) {
+ if (time_diff(now, priv->lastrecv) >= 15000) {
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "Receive window closed. Closing down.");
+ closedown (self, ECONNABORTED, CLOSEDOWN_LOCAL);
+ return;
+ }
+
+ // probe the window
+ packet(self, priv->snd_nxt - 1, 0, 0, 0, now);
+ priv->lastsend = now;
+
+ // back off retransmit timer
+ priv->rx_rto = min(MAX_RTO, priv->rx_rto * 2);
+ }
+
+ // Check if it's time to send delayed acks
+ if (priv->t_ack && (time_diff(priv->t_ack + priv->ack_delay, now) <= 0)) {
+ packet(self, priv->snd_nxt, 0, 0, 0, now);
+ }
+
+}
+
+gboolean
+pseudo_tcp_socket_notify_packet(PseudoTcpSocket *self,
+ const gchar * buffer, guint32 len)
+{
+ gboolean retval;
+
+ if (len > MAX_PACKET) {
+ //LOG_F(WARNING) << "packet too large";
+ self->priv->error = EMSGSIZE;
+ return FALSE;
+ } else if (len < HEADER_SIZE) {
+ //LOG_F(WARNING) << "packet too small";
+ self->priv->error = EINVAL;
+ return FALSE;
+ }
+
+ /* Hold a reference to the PseudoTcpSocket during parsing, since it may be
+ * closed from within a callback. */
+ g_object_ref (self);
+ retval = parse (self, (guint8 *) buffer, HEADER_SIZE,
+ (guint8 *) buffer + HEADER_SIZE, len - HEADER_SIZE);
+ g_object_unref (self);
+
+ return retval;
+}
+
+/* Assume there are two buffers in the given #NiceInputMessage: a 24-byte one
+ * containing the header, and a bigger one for the data. */
+gboolean
+pseudo_tcp_socket_notify_message (PseudoTcpSocket *self,
+ NiceInputMessage *message)
+{
+ gboolean retval;
+
+ g_assert_cmpuint (message->n_buffers, >, 0);
+
+ if (message->n_buffers == 1)
+ return pseudo_tcp_socket_notify_packet (self, message->buffers[0].buffer,
+ message->buffers[0].size);
+
+ g_assert_cmpuint (message->n_buffers, ==, 2);
+ g_assert_cmpuint (message->buffers[0].size, ==, HEADER_SIZE);
+
+ if (message->length > MAX_PACKET) {
+ //LOG_F(WARNING) << "packet too large";
+ return FALSE;
+ } else if (message->length < HEADER_SIZE) {
+ //LOG_F(WARNING) << "packet too small";
+ return FALSE;
+ }
+
+ /* Hold a reference to the PseudoTcpSocket during parsing, since it may be
+ * closed from within a callback. */
+ g_object_ref (self);
+ retval = parse (self, message->buffers[0].buffer, message->buffers[0].size,
+ message->buffers[1].buffer, message->length - message->buffers[0].size);
+ g_object_unref (self);
+
+ return retval;
+}
+
+gboolean
+pseudo_tcp_socket_get_next_clock(PseudoTcpSocket *self, guint64 *timeout)
+{
+ PseudoTcpSocketPrivate *priv = self->priv;
+ guint32 now = get_current_time (self);
+ gsize snd_buffered;
+ guint32 closed_timeout;
+
+ if (priv->shutdown == SD_FORCEFUL) {
+ if (priv->support_fin_ack) {
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL,
+ "‘Forceful’ shutdown used when FIN-ACK support is enabled");
+ }
+
+ /* Transition to the CLOSED state. */
+ closedown (self, 0, CLOSEDOWN_REMOTE);
+
+ return FALSE;
+ }
+
+ snd_buffered = pseudo_tcp_fifo_get_buffered (&priv->sbuf);
+ if ((priv->shutdown == SD_GRACEFUL)
+ && ((priv->state != PSEUDO_TCP_ESTABLISHED)
+ || ((snd_buffered == 0) && (priv->t_ack == 0)))) {
+ if (priv->support_fin_ack) {
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL,
+ "‘Graceful’ shutdown used when FIN-ACK support is enabled");
+ }
+
+ /* Transition to the CLOSED state. */
+ closedown (self, 0, CLOSEDOWN_REMOTE);
+
+ return FALSE;
+ }
+
+ /* FIN-ACK support. The timeout for closing the socket if nothing is received
+ * varies depending on whether the socket is waiting in the TIME-WAIT state
+ * for delayed segments to pass.
+ *
+ * See: http://vincent.bernat.im/en/blog/2014-tcp-time-wait-state-linux.html
+ */
+ closed_timeout = CLOSED_TIMEOUT;
+ if (priv->support_fin_ack && priv->state == PSEUDO_TCP_TIME_WAIT)
+ closed_timeout = TIME_WAIT_TIMEOUT;
+
+ if (priv->support_fin_ack && priv->state == PSEUDO_TCP_CLOSED) {
+ return FALSE;
+ }
+
+ if (*timeout == 0 || *timeout < now)
+ *timeout = now + closed_timeout;
+
+ if (priv->support_fin_ack && priv->state == PSEUDO_TCP_TIME_WAIT) {
+ *timeout = min (*timeout, now + TIME_WAIT_TIMEOUT);
+ return TRUE;
+ }
+
+ if (priv->state == PSEUDO_TCP_CLOSED && !priv->support_fin_ack) {
+ *timeout = min (*timeout, now + CLOSED_TIMEOUT);
+ return TRUE;
+ }
+
+ *timeout = min (*timeout, now + DEFAULT_TIMEOUT);
+
+ if (priv->t_ack) {
+ *timeout = min(*timeout, priv->t_ack + priv->ack_delay);
+ }
+ if (priv->rto_base) {
+ *timeout = min(*timeout, priv->rto_base + priv->rx_rto);
+ }
+ if (priv->snd_wnd == 0) {
+ *timeout = min(*timeout, priv->lastsend + priv->rx_rto);
+ }
+
+ return TRUE;
+}
+
+
+gint
+pseudo_tcp_socket_recv(PseudoTcpSocket *self, char * buffer, size_t len)
+{
+ PseudoTcpSocketPrivate *priv = self->priv;
+ gsize bytesread;
+ gsize available_space;
+
+ /* Received a FIN from the peer, so return 0. RFC 793, §3.5, Case 2. */
+ if (priv->support_fin_ack && priv->shutdown_reads) {
+ return 0;
+ }
+
+ /* Return 0 if FIN-ACK is not supported but the socket has been closed. */
+ if (!priv->support_fin_ack && pseudo_tcp_socket_is_closed (self)) {
+ return 0;
+ }
+
+ /* Return ENOTCONN if FIN-ACK is not supported and the connection is not
+ * ESTABLISHED. */
+ if (!priv->support_fin_ack && priv->state != PSEUDO_TCP_ESTABLISHED) {
+ priv->error = ENOTCONN;
+ return -1;
+ }
+
+ if (len == 0)
+ return 0;
+
+ bytesread = pseudo_tcp_fifo_read (&priv->rbuf, (guint8 *) buffer, len);
+
+ // If there's no data in |m_rbuf|.
+ if (bytesread == 0 &&
+ !(pseudo_tcp_state_has_received_fin (priv->state) ||
+ pseudo_tcp_state_has_received_fin_ack (priv->state))) {
+ priv->bReadEnable = TRUE;
+ priv->error = EWOULDBLOCK;
+ return -1;
+ }
+
+ available_space = pseudo_tcp_fifo_get_write_remaining (&priv->rbuf);
+
+ if (available_space - priv->rcv_wnd >=
+ min (priv->rbuf_len / 2, priv->mss)) {
+ // !?! Not sure about this was closed business
+ gboolean bWasClosed = (priv->rcv_wnd == 0);
+
+ priv->rcv_wnd = available_space;
+
+ if (bWasClosed) {
+ attempt_send(self, sfImmediateAck);
+ }
+ }
+
+ return bytesread;
+}
+
+gint
+pseudo_tcp_socket_send(PseudoTcpSocket *self, const char * buffer, guint32 len)
+{
+ PseudoTcpSocketPrivate *priv = self->priv;
+ gint written;
+ gsize available_space;
+
+ if (priv->state != PSEUDO_TCP_ESTABLISHED) {
+ priv->error = pseudo_tcp_state_has_sent_fin (priv->state) ? EPIPE : ENOTCONN;
+ return -1;
+ }
+
+ available_space = pseudo_tcp_fifo_get_write_remaining (&priv->sbuf);
+
+ if (!available_space) {
+ priv->bWriteEnable = TRUE;
+ priv->error = EWOULDBLOCK;
+ return -1;
+ }
+
+ written = queue (self, buffer, len, FLAG_NONE);
+ attempt_send(self, sfNone);
+
+ if (written > 0 && (guint32)written < len) {
+ priv->bWriteEnable = TRUE;
+ }
+
+ return written;
+}
+
+void
+pseudo_tcp_socket_close(PseudoTcpSocket *self, gboolean force)
+{
+ PseudoTcpSocketPrivate *priv = self->priv;
+
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "Closing socket %p %s", self,
+ force ? "forcefully" : "gracefully");
+
+ /* Forced closure by sending an RST segment. RFC 1122, §4.2.2.13. */
+ if (force && priv->state != PSEUDO_TCP_CLOSED) {
+ closedown (self, ECONNABORTED, CLOSEDOWN_LOCAL);
+ return;
+ }
+
+ /* Fall back to shutdown(). */
+ pseudo_tcp_socket_shutdown (self, PSEUDO_TCP_SHUTDOWN_RDWR);
+}
+
+void
+pseudo_tcp_socket_shutdown (PseudoTcpSocket *self, PseudoTcpShutdown how)
+{
+ PseudoTcpSocketPrivate *priv = self->priv;
+
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "Shutting down socket %p: %u", self, how);
+
+ /* FIN-ACK--only stuff below here. */
+ if (!priv->support_fin_ack) {
+ if (priv->shutdown == SD_NONE)
+ priv->shutdown = SD_GRACEFUL;
+ return;
+ }
+
+ /* What needs shutting down? */
+ switch (how) {
+ case PSEUDO_TCP_SHUTDOWN_RD:
+ case PSEUDO_TCP_SHUTDOWN_RDWR:
+ priv->shutdown_reads = TRUE;
+ break;
+ case PSEUDO_TCP_SHUTDOWN_WR:
+ /* Handled below. */
+ break;
+ default:
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "Invalid shutdown method: %u.", how);
+ break;
+ }
+
+ if (how == PSEUDO_TCP_SHUTDOWN_RD) {
+ return;
+ }
+
+ /* Unforced write closure. */
+ switch (priv->state) {
+ case PSEUDO_TCP_LISTEN:
+ case PSEUDO_TCP_SYN_SENT:
+ /* Just abort the connection without completing the handshake. */
+ set_state_closed (self, 0);
+ break;
+ case PSEUDO_TCP_SYN_RECEIVED:
+ case PSEUDO_TCP_ESTABLISHED:
+ /* Local user initiating the close: RFC 793, §3.5, Cases 1 and 3.
+ * If there is pending receive data, send RST instead of FIN;
+ * see RFC 1122, §4.2.2.13. */
+ if (pseudo_tcp_socket_get_available_bytes (self) > 0) {
+ closedown (self, ECONNABORTED, CLOSEDOWN_LOCAL);
+ } else {
+ queue_fin_message (self);
+ attempt_send (self, sfFin);
+ set_state (self, PSEUDO_TCP_FIN_WAIT_1);
+ }
+ break;
+ case PSEUDO_TCP_CLOSE_WAIT:
+ /* Remote user initiating the close: RFC 793, §3.5, Case 2.
+ * We’ve previously received a FIN from the peer; now the user is closing
+ * the local end of the connection. */
+ queue_fin_message (self);
+ attempt_send (self, sfFin);
+ set_state (self, PSEUDO_TCP_LAST_ACK);
+ break;
+ case PSEUDO_TCP_CLOSING:
+ case PSEUDO_TCP_CLOSED:
+ /* Already closed on both sides. */
+ break;
+ case PSEUDO_TCP_FIN_WAIT_1:
+ case PSEUDO_TCP_FIN_WAIT_2:
+ case PSEUDO_TCP_TIME_WAIT:
+ case PSEUDO_TCP_LAST_ACK:
+ /* Already closed locally. */
+ break;
+ default:
+ /* Do nothing. */
+ break;
+ }
+}
+
+int
+pseudo_tcp_socket_get_error(PseudoTcpSocket *self)
+{
+ PseudoTcpSocketPrivate *priv = self->priv;
+ return priv->error;
+}
+
+//
+// Internal Implementation
+//
+
+static guint32
+queue (PseudoTcpSocket *self, const gchar * data, guint32 len, TcpFlags flags)
+{
+ PseudoTcpSocketPrivate *priv = self->priv;
+ gsize available_space;
+
+ available_space = pseudo_tcp_fifo_get_write_remaining (&priv->sbuf);
+ if (len > available_space) {
+ g_assert (flags == FLAG_NONE);
+ len = available_space;
+ }
+
+ // We can concatenate data if the last segment is the same type
+ // (control v. regular data), and has not been transmitted yet
+ if (g_queue_get_length (&priv->slist) &&
+ (((SSegment *)g_queue_peek_tail (&priv->slist))->flags == flags) &&
+ (((SSegment *)g_queue_peek_tail (&priv->slist))->xmit == 0)) {
+ ((SSegment *)g_queue_peek_tail (&priv->slist))->len += len;
+ } else {
+ SSegment *sseg = g_slice_new0 (SSegment);
+ gsize snd_buffered = pseudo_tcp_fifo_get_buffered (&priv->sbuf);
+
+ sseg->seq = priv->snd_una + snd_buffered;
+ sseg->len = len;
+ sseg->flags = flags;
+ g_queue_push_tail (&priv->slist, sseg);
+ g_queue_push_tail (&priv->unsent_slist, sseg);
+ }
+
+ //LOG(LS_INFO) << "PseudoTcp::queue - priv->slen = " << priv->slen;
+ return pseudo_tcp_fifo_write (&priv->sbuf, (guint8*) data, len);;
+}
+
+// Creates a packet and submits it to the network. This method can either
+// send payload or just an ACK packet.
+//
+// |seq| is the sequence number of this packet.
+// |flags| is the flags for sending this packet.
+// |offset| is the offset to read from |m_sbuf|.
+// |len| is the number of bytes to read from |m_sbuf| as payload. If this
+// value is 0 then this is an ACK packet, otherwise this packet has payload.
+
+static PseudoTcpWriteResult
+packet(PseudoTcpSocket *self, guint32 seq, TcpFlags flags,
+ guint32 offset, guint32 len, guint32 now)
+{
+ PseudoTcpSocketPrivate *priv = self->priv;
+ union {
+ guint8 u8[MAX_PACKET];
+ guint16 u16[MAX_PACKET / 2];
+ guint32 u32[MAX_PACKET / 4];
+ } buffer;
+ PseudoTcpWriteResult wres = WR_SUCCESS;
+
+ g_assert(HEADER_SIZE + len <= MAX_PACKET);
+
+ *buffer.u32 = htonl(priv->conv);
+ *(buffer.u32 + 1) = htonl(seq);
+ *(buffer.u32 + 2) = htonl(priv->rcv_nxt);
+ buffer.u8[12] = 0;
+ buffer.u8[13] = flags;
+ *(buffer.u16 + 7) = htons((guint16)(priv->rcv_wnd >> priv->rwnd_scale));
+
+ // Timestamp computations
+ *(buffer.u32 + 4) = htonl(now);
+ *(buffer.u32 + 5) = htonl(priv->ts_recent);
+ priv->ts_lastack = priv->rcv_nxt;
+
+ if (len) {
+ gsize bytes_read;
+
+ bytes_read = pseudo_tcp_fifo_read_offset (&priv->sbuf, buffer.u8 + HEADER_SIZE,
+ len, offset);
+ g_assert (bytes_read == len);
+ }
+
+ DEBUG (PSEUDO_TCP_DEBUG_VERBOSE, "Sending <CONV=%u><FLG=%u><SEQ=%u:%u><ACK=%u>"
+ "<WND=%u><TS=%u><TSR=%u><LEN=%u>",
+ priv->conv, (unsigned)flags, seq, seq + len, priv->rcv_nxt, priv->rcv_wnd,
+ now % 10000, priv->ts_recent % 10000, len);
+
+ wres = priv->callbacks.WritePacket(self, (gchar *) buffer.u8, len + HEADER_SIZE,
+ priv->callbacks.user_data);
+ /* Note: When len is 0, this is an ACK packet. We don't read the
+ return value for those, and thus we won't retry. So go ahead and treat
+ the packet as a success (basically simulate as if it were dropped),
+ which will prevent our timers from being messed up. */
+ if ((wres != WR_SUCCESS) && (0 != len))
+ return wres;
+
+ priv->t_ack = 0;
+ if (len > 0) {
+ priv->lastsend = now;
+ }
+ priv->last_traffic = now;
+ priv->bOutgoing = TRUE;
+
+ return WR_SUCCESS;
+}
+
+static gboolean
+parse (PseudoTcpSocket *self, const guint8 *_header_buf, gsize header_buf_len,
+ const guint8 *data_buf, gsize data_buf_len)
+{
+ Segment seg;
+
+ union {
+ const guint8 *u8;
+ const guint16 *u16;
+ const guint32 *u32;
+ } header_buf;
+
+ header_buf.u8 = _header_buf;
+
+ if (header_buf_len != 24)
+ return FALSE;
+
+ seg.conv = ntohl(*header_buf.u32);
+ seg.seq = ntohl(*(header_buf.u32 + 1));
+ seg.ack = ntohl(*(header_buf.u32 + 2));
+ seg.flags = header_buf.u8[13];
+ seg.wnd = ntohs(*(header_buf.u16 + 7));
+
+ seg.tsval = ntohl(*(header_buf.u32 + 4));
+ seg.tsecr = ntohl(*(header_buf.u32 + 5));
+
+ seg.data = (const gchar *) data_buf;
+ seg.len = data_buf_len;
+
+ DEBUG (PSEUDO_TCP_DEBUG_VERBOSE,
+ "Received <CONV=%u><FLG=%u><SEQ=%u:%u><ACK=%u>"
+ "<WND=%u><TS=%u><TSR=%u><LEN=%u>",
+ seg.conv, (unsigned)seg.flags, seg.seq, seg.seq + seg.len, seg.ack,
+ seg.wnd, seg.tsval % 10000, seg.tsecr % 10000, seg.len);
+
+ return process(self, &seg);
+}
+
+/* True iff the @state requires that a FIN has already been sent by this
+ * host. */
+static gboolean
+pseudo_tcp_state_has_sent_fin (PseudoTcpState state)
+{
+ switch (state) {
+ case PSEUDO_TCP_LISTEN:
+ case PSEUDO_TCP_SYN_SENT:
+ case PSEUDO_TCP_SYN_RECEIVED:
+ case PSEUDO_TCP_ESTABLISHED:
+ case PSEUDO_TCP_CLOSE_WAIT:
+ return FALSE;
+ case PSEUDO_TCP_CLOSED:
+ case PSEUDO_TCP_FIN_WAIT_1:
+ case PSEUDO_TCP_FIN_WAIT_2:
+ case PSEUDO_TCP_CLOSING:
+ case PSEUDO_TCP_TIME_WAIT:
+ case PSEUDO_TCP_LAST_ACK:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+/* True iff the @state requires that a FIN has already been received from the
+ * peer. */
+static gboolean
+pseudo_tcp_state_has_received_fin (PseudoTcpState state)
+{
+ switch (state) {
+ case PSEUDO_TCP_LISTEN:
+ case PSEUDO_TCP_SYN_SENT:
+ case PSEUDO_TCP_SYN_RECEIVED:
+ case PSEUDO_TCP_ESTABLISHED:
+ case PSEUDO_TCP_FIN_WAIT_1:
+ case PSEUDO_TCP_FIN_WAIT_2:
+ return FALSE;
+ case PSEUDO_TCP_CLOSED:
+ case PSEUDO_TCP_CLOSING:
+ case PSEUDO_TCP_TIME_WAIT:
+ case PSEUDO_TCP_CLOSE_WAIT:
+ case PSEUDO_TCP_LAST_ACK:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+/* True iff the @state requires that a FIN-ACK has already been received from
+ * the peer. */
+static gboolean
+pseudo_tcp_state_has_received_fin_ack (PseudoTcpState state)
+{
+ switch (state) {
+ case PSEUDO_TCP_LISTEN:
+ case PSEUDO_TCP_SYN_SENT:
+ case PSEUDO_TCP_SYN_RECEIVED:
+ case PSEUDO_TCP_ESTABLISHED:
+ case PSEUDO_TCP_FIN_WAIT_1:
+ case PSEUDO_TCP_FIN_WAIT_2:
+ case PSEUDO_TCP_CLOSING:
+ case PSEUDO_TCP_CLOSE_WAIT:
+ case PSEUDO_TCP_LAST_ACK:
+ return FALSE;
+ case PSEUDO_TCP_CLOSED:
+ case PSEUDO_TCP_TIME_WAIT:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+static gboolean
+process(PseudoTcpSocket *self, Segment *seg)
+{
+ PseudoTcpSocketPrivate *priv = self->priv;
+ guint32 now;
+ SendFlags sflags = sfNone;
+ gboolean bIgnoreData;
+ gboolean bNewData;
+ gboolean bConnect = FALSE;
+ gsize snd_buffered;
+ gsize available_space;
+ guint32 kIdealRefillSize;
+ gboolean is_valuable_ack, is_duplicate_ack, is_fin_ack = FALSE;
+ gboolean received_fin = FALSE;
+
+ /* If this is the wrong conversation, send a reset!?!
+ (with the correct conversation?) */
+ if (seg->conv != priv->conv) {
+ //if ((seg->flags & FLAG_RST) == 0) {
+ // packet(sock, tcb, seg->ack, 0, FLAG_RST, 0, 0);
+ //}
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "wrong conversation");
+ return FALSE;
+ }
+
+ now = get_current_time (self);
+ priv->last_traffic = priv->lastrecv = now;
+ priv->bOutgoing = FALSE;
+
+ if (priv->state == PSEUDO_TCP_CLOSED ||
+ (pseudo_tcp_state_has_received_fin_ack (priv->state) && seg->len > 0)) {
+ /* Send an RST segment. See: RFC 1122, §4.2.2.13; RFC 793, §3.4, point 3,
+ * page 37. We can only send RST if we know the peer knows we’re closed;
+ * otherwise this could be a timeout retransmit from them, due to our
+ * packets from data through to FIN being dropped. */
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL,
+ "Segment received while closed; sending RST.");
+ if ((seg->flags & FLAG_RST) == 0) {
+ closedown (self, 0, CLOSEDOWN_LOCAL);
+ }
+
+ return FALSE;
+ }
+
+ // Check if this is a reset segment
+ if (seg->flags & FLAG_RST) {
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "Received RST segment; closing down.");
+ closedown (self, ECONNRESET, CLOSEDOWN_REMOTE);
+ return FALSE;
+ }
+
+ // Check for control data
+ bConnect = FALSE;
+ if (seg->flags & FLAG_CTL) {
+ if (seg->len == 0) {
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "Missing control code");
+ return FALSE;
+ } else if (seg->data[0] == CTL_CONNECT) {
+ bConnect = TRUE;
+
+ parse_options (self, (guint8 *) &seg->data[1], seg->len - 1);
+
+ if (priv->state == PSEUDO_TCP_LISTEN) {
+ set_state (self, PSEUDO_TCP_SYN_RECEIVED);
+ queue_connect_message (self);
+ } else if (priv->state == PSEUDO_TCP_SYN_SENT) {
+ set_state_established (self);
+ }
+ } else {
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "Unknown control code: %u", seg->data[0]);
+ return FALSE;
+ }
+ }
+
+ // Update timestamp
+ if (SMALLER_OR_EQUAL (seg->seq, priv->ts_lastack) &&
+ SMALLER (priv->ts_lastack, seg->seq + seg->len)) {
+ priv->ts_recent = seg->tsval;
+ }
+
+ // Check if this is a valuable ack
+ is_valuable_ack = (LARGER(seg->ack, priv->snd_una) &&
+ SMALLER_OR_EQUAL(seg->ack, priv->snd_nxt));
+ is_duplicate_ack = (seg->ack == priv->snd_una);
+
+ if (is_valuable_ack) {
+ guint32 nAcked;
+ guint32 nFree;
+
+ // Calculate round-trip time
+ if (seg->tsecr) {
+ long rtt = time_diff(now, seg->tsecr);
+ if (rtt >= 0) {
+ if (priv->rx_srtt == 0) {
+ priv->rx_srtt = rtt;
+ priv->rx_rttvar = rtt / 2;
+ } else {
+ priv->rx_rttvar = (3 * priv->rx_rttvar +
+ labs((long)(rtt - priv->rx_srtt))) / 4;
+ priv->rx_srtt = (7 * priv->rx_srtt + rtt) / 8;
+ }
+ priv->rx_rto = bound(MIN_RTO,
+ priv->rx_srtt + max(1LU, 4 * priv->rx_rttvar), MAX_RTO);
+
+ DEBUG (PSEUDO_TCP_DEBUG_VERBOSE, "rtt: %ld srtt: %u rttvar: %u rto: %u",
+ rtt, priv->rx_srtt, priv->rx_rttvar, priv->rx_rto);
+ } else {
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "Invalid RTT: %ld", rtt);
+ return FALSE;
+ }
+
+ priv->last_acked_ts = seg->tsecr;
+ }
+
+ priv->snd_wnd = seg->wnd << priv->swnd_scale;
+
+ nAcked = seg->ack - priv->snd_una;
+ priv->snd_una = seg->ack;
+
+ priv->rto_base = (priv->snd_una == priv->snd_nxt) ? 0 : now;
+
+ /* ACKs for FIN segments give an increment on nAcked, but there is no
+ * corresponding byte to read because the FIN segment is empty (it just has
+ * a sequence number). */
+ if (nAcked == priv->sbuf.data_length + 1 &&
+ pseudo_tcp_state_has_sent_fin (priv->state)) {
+ is_fin_ack = TRUE;
+ nAcked--;
+ }
+
+ pseudo_tcp_fifo_consume_read_data (&priv->sbuf, nAcked);
+
+ for (nFree = nAcked; nFree > 0; ) {
+ SSegment *data;
+
+ g_assert(g_queue_get_length (&priv->slist) != 0);
+ data = (SSegment *) g_queue_peek_head (&priv->slist);
+
+ if (nFree < data->len) {
+ data->len -= nFree;
+ data->seq += nFree;
+ nFree = 0;
+ } else {
+ if (data->len > priv->largest) {
+ priv->largest = data->len;
+ }
+ nFree -= data->len;
+ g_slice_free (SSegment, data);
+ g_queue_pop_head (&priv->slist);
+ }
+ }
+
+ if (priv->dup_acks >= 3) {
+ if (LARGER_OR_EQUAL (priv->snd_una, priv->recover)) { // NewReno
+ guint32 nInFlight = priv->snd_nxt - priv->snd_una;
+ // (Fast Retransmit)
+ priv->cwnd = min(priv->ssthresh,
+ max (nInFlight, priv->mss) + priv->mss);
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "exit recovery cwnd=%d ssthresh=%d nInFlight=%d mss: %d", priv->cwnd, priv->ssthresh, nInFlight, priv->mss);
+ priv->fast_recovery = FALSE;
+ priv->dup_acks = 0;
+ } else {
+ int transmit_status;
+
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "recovery retransmit");
+ transmit_status = transmit(self, g_queue_peek_head (&priv->slist), now);
+ if (transmit_status != 0) {
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL,
+ "Error transmitting recovery retransmit segment. Closing down.");
+ closedown (self, transmit_status, CLOSEDOWN_LOCAL);
+ return FALSE;
+ }
+ priv->cwnd += (nAcked > priv->mss ? priv->mss : 0) -
+ min(nAcked, priv->cwnd);
+ }
+ } else {
+ priv->dup_acks = 0;
+ // Slow start, congestion avoidance
+ if (priv->cwnd < priv->ssthresh) {
+ priv->cwnd += priv->mss;
+ } else {
+ priv->cwnd += max(1LU, priv->mss * priv->mss / priv->cwnd);
+ }
+ }
+ } else if (is_duplicate_ack) {
+ /* !?! Note, tcp says don't do this... but otherwise how does a
+ closed window become open? */
+ priv->snd_wnd = seg->wnd << priv->swnd_scale;
+
+ // Check duplicate acks
+ if (seg->len > 0) {
+ // it's a dup ack, but with a data payload, so don't modify priv->dup_acks
+ } else if (priv->snd_una != priv->snd_nxt) {
+ guint32 nInFlight;
+
+ priv->dup_acks += 1;
+ DEBUG (PSEUDO_TCP_DEBUG_VERBOSE, "Received dup ack (dups: %u)",
+ priv->dup_acks);
+ if (priv->dup_acks == 3) { // (Fast Retransmit)
+ int transmit_status;
+
+
+ if (LARGER_OR_EQUAL (priv->snd_una, priv->recover) ||
+ seg->tsecr == priv->last_acked_ts) { /* NewReno */
+ /* Invoke fast retransmit RFC3782 section 3 step 1A*/
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "enter recovery");
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "recovery retransmit");
+
+ transmit_status = transmit(self, g_queue_peek_head (&priv->slist),
+ now);
+ if (transmit_status != 0) {
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL,
+ "Error transmitting recovery retransmit segment. Closing down.");
+
+ closedown (self, transmit_status, CLOSEDOWN_LOCAL);
+ return FALSE;
+ }
+ priv->recover = priv->snd_nxt;
+ nInFlight = priv->snd_nxt - priv->snd_una;
+ priv->ssthresh = max(nInFlight / 2, 2 * priv->mss);
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL,
+ "ssthresh: %u = max((nInFlight: %u / 2), 2 * mss: %u)",
+ priv->ssthresh, nInFlight, priv->mss);
+ priv->cwnd = priv->ssthresh + 3 * priv->mss;
+ priv->fast_recovery = TRUE;
+ } else {
+ DEBUG (PSEUDO_TCP_DEBUG_VERBOSE,
+ "Skipping fast recovery: recover: %u snd_una: %u", priv->recover,
+ priv->snd_una);
+ }
+ } else if (priv->dup_acks > 3) {
+ if (priv->fast_recovery)
+ priv->cwnd += priv->mss;
+ }
+ } else {
+ priv->dup_acks = 0;
+ }
+ }
+
+ // !?! A bit hacky
+ if ((priv->state == PSEUDO_TCP_SYN_RECEIVED) && !bConnect) {
+ set_state_established (self);
+ }
+
+ /* Check for connection closure. Only pay attention to FIN segments if they
+ * are in sequence; otherwise we’ve missed a packet earlier in the stream and
+ * need to request retransmission first. */
+ if (priv->support_fin_ack) {
+ /* @received_fin is set when, and only when, all segments preceding the FIN
+ * have been acknowledged. This is to handle the case where the FIN arrives
+ * out of order with a preceding data segment. */
+ if (seg->flags & FLAG_FIN) {
+ priv->rcv_fin = seg->seq;
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "Setting rcv_fin = %u", priv->rcv_fin);
+ }
+
+ /* For the moment, FIN segments must not contain data. */
+ if (seg->flags & FLAG_FIN && seg->len != 0) {
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "FIN segment contained data; ignored");
+ return FALSE;
+ }
+
+ received_fin = (priv->rcv_nxt != 0 && priv->rcv_nxt + seg->len == priv->rcv_fin);
+
+ /* Update the state machine, implementing all transitions on ‘rcv FIN’ or
+ * ‘rcv ACK of FIN’ from RFC 793, Figure 6; and RFC 1122, §4.2.2.8. */
+ switch (priv->state) {
+ case PSEUDO_TCP_ESTABLISHED:
+ if (received_fin) {
+ /* Received a FIN from the network, RFC 793, §3.5, Case 2.
+ * The code below will send an ACK for the FIN. */
+ set_state (self, PSEUDO_TCP_CLOSE_WAIT);
+ }
+ break;
+ case PSEUDO_TCP_CLOSING:
+ if (is_fin_ack) {
+ /* Handle the ACK of a locally-sent FIN flag. RFC 793, §3.5, Case 3. */
+ set_state (self, PSEUDO_TCP_TIME_WAIT);
+ }
+ break;
+ case PSEUDO_TCP_LAST_ACK:
+ if (is_fin_ack) {
+ /* Handle the ACK of a locally-sent FIN flag. RFC 793, §3.5, Case 2. */
+ set_state_closed (self, 0);
+ }
+ break;
+ case PSEUDO_TCP_FIN_WAIT_1:
+ if (is_fin_ack && received_fin) {
+ /* Simultaneous close with an ACK for a FIN previously sent,
+ * RFC 793, §3.5, Case 3. */
+ set_state (self, PSEUDO_TCP_TIME_WAIT);
+ } else if (is_fin_ack) {
+ /* Handle the ACK of a locally-sent FIN flag. RFC 793, §3.5, Case 1. */
+ set_state (self, PSEUDO_TCP_FIN_WAIT_2);
+ } else if (received_fin) {
+ /* Simultaneous close, RFC 793, §3.5, Case 3. */
+ set_state (self, PSEUDO_TCP_CLOSING);
+ }
+ break;
+ case PSEUDO_TCP_FIN_WAIT_2:
+ if (received_fin) {
+ /* Local user closed the connection, RFC 793, §3.5, Case 1. */
+ set_state (self, PSEUDO_TCP_TIME_WAIT);
+ }
+ break;
+ case PSEUDO_TCP_LISTEN:
+ case PSEUDO_TCP_SYN_SENT:
+ case PSEUDO_TCP_SYN_RECEIVED:
+ case PSEUDO_TCP_TIME_WAIT:
+ case PSEUDO_TCP_CLOSED:
+ case PSEUDO_TCP_CLOSE_WAIT:
+ /* Shouldn’t ever hit these cases. */
+ if (received_fin) {
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL,
+ "Unexpected state %u when FIN received", priv->state);
+ } else if (is_fin_ack) {
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL,
+ "Unexpected state %u when FIN-ACK received", priv->state);
+ }
+ break;
+ default:
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "Invalid state %u when FIN received",
+ priv->state);
+ return FALSE;
+ }
+ } else if (seg->flags & FLAG_FIN) {
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL,
+ "Invalid FIN received when FIN-ACK support is disabled");
+ } else if (is_fin_ack) {
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL,
+ "Invalid FIN-ACK received when FIN-ACK support is disabled");
+ }
+
+ // If we make room in the send queue, notify the user
+ // The goal it to make sure we always have at least enough data to fill the
+ // window. We'd like to notify the app when we are halfway to that point.
+ kIdealRefillSize = (priv->sbuf_len + priv->rbuf_len) / 2;
+
+ snd_buffered = pseudo_tcp_fifo_get_buffered (&priv->sbuf);
+ if (priv->bWriteEnable && snd_buffered < kIdealRefillSize) {
+ priv->bWriteEnable = FALSE;
+ if (priv->callbacks.PseudoTcpWritable)
+ priv->callbacks.PseudoTcpWritable(self, priv->callbacks.user_data);
+ }
+
+ /* Conditions where acks must be sent:
+ * 1) Segment is too old (they missed an ACK) (immediately)
+ * 2) Segment is too new (we missed a segment) (immediately)
+ * 3) Segment has data (so we need to ACK!) (delayed)
+ * ... so the only time we don't need to ACK, is an empty segment
+ * that points to rcv_nxt!
+ * 4) Segment has the FIN flag set (immediately) — note that the FIN flag
+ * itself has to be included in the ACK as a numbered byte;
+ * see RFC 793, §3.3. Also see: RFC 793, §3.5.
+ */
+ if (seg->seq != priv->rcv_nxt) {
+ sflags = sfDuplicateAck; // (Fast Recovery)
+ } else if (seg->len != 0) {
+ if (priv->ack_delay == 0) {
+ sflags = sfImmediateAck;
+ } else {
+ sflags = sfDelayedAck;
+ }
+ } else if (received_fin) {
+ /* FIN flags have a sequence number. Only acknowledge them after all
+ * preceding octets have been acknowledged. */
+ sflags = sfImmediateAck;
+ }
+
+ if (sflags == sfDuplicateAck) {
+ if (seg->seq > priv->rcv_nxt) {
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "too new");
+ } else if (SMALLER_OR_EQUAL(seg->seq + seg->len, priv->rcv_nxt)) {
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "too old");
+ }
+ }
+
+ // Adjust the incoming segment to fit our receive buffer
+ if (SMALLER(seg->seq, priv->rcv_nxt)) {
+ guint32 nAdjust = priv->rcv_nxt - seg->seq;
+ if (nAdjust < seg->len) {
+ seg->seq += nAdjust;
+ seg->data += nAdjust;
+ seg->len -= nAdjust;
+ } else {
+ seg->len = 0;
+ }
+ }
+
+ available_space = pseudo_tcp_fifo_get_write_remaining (&priv->rbuf);
+
+ if ((seg->seq + seg->len - priv->rcv_nxt) > available_space) {
+ guint32 nAdjust = seg->seq + seg->len - priv->rcv_nxt - available_space;
+ if (nAdjust < seg->len) {
+ seg->len -= nAdjust;
+ } else {
+ seg->len = 0;
+ }
+ }
+
+ bIgnoreData = (seg->flags & FLAG_CTL);
+ if (!priv->support_fin_ack)
+ bIgnoreData |= (priv->shutdown != SD_NONE);
+
+ bNewData = FALSE;
+
+ if (seg->len > 0) {
+ if (bIgnoreData) {
+ if (seg->seq == priv->rcv_nxt) {
+ priv->rcv_nxt += seg->len;
+ }
+ } else {
+ guint32 nOffset = seg->seq - priv->rcv_nxt;
+ gsize res;
+
+ res = pseudo_tcp_fifo_write_offset (&priv->rbuf, (guint8 *) seg->data,
+ seg->len, nOffset);
+ g_assert (res == seg->len);
+
+ if (seg->seq == priv->rcv_nxt) {
+ GList *iter = NULL;
+
+ pseudo_tcp_fifo_consume_write_buffer (&priv->rbuf, seg->len);
+ priv->rcv_nxt += seg->len;
+ priv->rcv_wnd -= seg->len;
+ bNewData = TRUE;
+
+ iter = priv->rlist;
+ while (iter &&
+ SMALLER_OR_EQUAL(((RSegment *)iter->data)->seq, priv->rcv_nxt)) {
+ RSegment *data = (RSegment *)(iter->data);
+ if (LARGER (data->seq + data->len, priv->rcv_nxt)) {
+ guint32 nAdjust = (data->seq + data->len) - priv->rcv_nxt;
+ sflags = sfImmediateAck; // (Fast Recovery)
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "Recovered %u bytes (%u -> %u)",
+ nAdjust, priv->rcv_nxt, priv->rcv_nxt + nAdjust);
+ pseudo_tcp_fifo_consume_write_buffer (&priv->rbuf, nAdjust);
+ priv->rcv_nxt += nAdjust;
+ priv->rcv_wnd -= nAdjust;
+ }
+ g_slice_free (RSegment, priv->rlist->data);
+ priv->rlist = g_list_delete_link (priv->rlist, priv->rlist);
+ iter = priv->rlist;
+ }
+ } else {
+ GList *iter = NULL;
+ RSegment *rseg = g_slice_new0 (RSegment);
+
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "Saving %u bytes (%u -> %u)",
+ seg->len, seg->seq, seg->seq + seg->len);
+ rseg->seq = seg->seq;
+ rseg->len = seg->len;
+ iter = priv->rlist;
+ while (iter && SMALLER (((RSegment*)iter->data)->seq, rseg->seq)) {
+ iter = g_list_next (iter);
+ }
+ priv->rlist = g_list_insert_before(priv->rlist, iter, rseg);
+ }
+ }
+ }
+
+ if (received_fin) {
+ /* FIN flags have a sequence number. */
+ priv->rcv_nxt++;
+ }
+
+
+ attempt_send(self, sflags);
+
+ // If we have new data, notify the user
+ if (bNewData && priv->bReadEnable) {
+ /* priv->bReadEnable = FALSE; — removed so that we’re always notified of
+ * incoming pseudo-TCP data, rather than having to read the entire buffer
+ * on each readable() callback before the next callback is enabled.
+ * (When client-provided buffers are small, this is not possible.) */
+ if (priv->callbacks.PseudoTcpReadable)
+ priv->callbacks.PseudoTcpReadable(self, priv->callbacks.user_data);
+ }
+
+ return TRUE;
+}
+
+static gboolean
+transmit(PseudoTcpSocket *self, SSegment *segment, guint32 now)
+{
+ PseudoTcpSocketPrivate *priv = self->priv;
+ guint32 nTransmit = min(segment->len, priv->mss);
+
+ if (segment->xmit >= ((priv->state == PSEUDO_TCP_ESTABLISHED) ? 15 : 30)) {
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "too many retransmits");
+ return ETIMEDOUT;
+ }
+
+ while (TRUE) {
+ guint32 seq = segment->seq;
+ guint8 flags = segment->flags;
+ PseudoTcpWriteResult wres;
+
+ /* The packet must not have already been acknowledged. */
+ g_assert_cmpuint (segment->seq - priv->snd_una, <=, 1024 * 1024 * 64);
+
+ /* Write out the packet. */
+ wres = packet(self, seq, flags,
+ segment->seq - priv->snd_una, nTransmit, now);
+
+ if (wres == WR_SUCCESS)
+ break;
+
+ if (wres == WR_FAIL) {
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "packet failed");
+ return ECONNABORTED; /* FIXME: This error code doesn’t quite seem right */
+ }
+
+ g_assert(wres == WR_TOO_LARGE);
+
+ while (TRUE) {
+ if (PACKET_MAXIMUMS[priv->msslevel + 1] == 0) {
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "MTU too small");
+ return EMSGSIZE;
+ }
+ /* !?! We need to break up all outstanding and pending packets
+ and then retransmit!?! */
+
+ priv->mss = PACKET_MAXIMUMS[++priv->msslevel] - PACKET_OVERHEAD;
+ // I added this... haven't researched actual formula
+ priv->cwnd = 2 * priv->mss;
+
+ if (priv->mss < nTransmit) {
+ nTransmit = priv->mss;
+ break;
+ }
+ }
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "Adjusting mss to %u bytes ", priv->mss);
+ }
+
+ if (nTransmit < segment->len) {
+ SSegment *subseg = g_slice_new0 (SSegment);
+ subseg->seq = segment->seq + nTransmit;
+ subseg->len = segment->len - nTransmit;
+ subseg->flags = segment->flags;
+ subseg->xmit = segment->xmit;
+
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "mss reduced to %u", priv->mss);
+
+ segment->len = nTransmit;
+ g_queue_insert_after (&priv->slist,
+ g_queue_find (&priv->slist, segment), subseg);
+ if (subseg->xmit == 0)
+ g_queue_insert_after (&priv->unsent_slist,
+ g_queue_find (&priv->unsent_slist, segment), subseg);
+ }
+
+ if (segment->xmit == 0) {
+ g_assert (g_queue_peek_head (&priv->unsent_slist) == segment);
+ g_queue_pop_head (&priv->unsent_slist);
+ priv->snd_nxt += segment->len;
+
+ /* FIN flags require acknowledgement. */
+ if (segment->len == 0 && segment->flags & FLAG_FIN)
+ priv->snd_nxt++;
+ }
+ segment->xmit += 1;
+
+ if (priv->rto_base == 0) {
+ priv->rto_base = now;
+ }
+
+ return 0;
+}
+
+static void
+attempt_send(PseudoTcpSocket *self, SendFlags sflags)
+{
+ PseudoTcpSocketPrivate *priv = self->priv;
+ guint32 now = get_current_time (self);
+ gboolean bFirst = TRUE;
+
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "Attempting send with flags %u.", sflags);
+
+ if (time_diff(now, priv->lastsend) > (long) priv->rx_rto) {
+ priv->cwnd = priv->mss;
+ }
+
+
+ while (TRUE) {
+ guint32 cwnd;
+ guint32 nWindow;
+ guint32 nInFlight;
+ guint32 nUseable;
+ guint32 nAvailable;
+ gsize snd_buffered;
+ GList *iter;
+ SSegment *sseg;
+ int transmit_status;
+
+ cwnd = priv->cwnd;
+ if ((priv->dup_acks == 1) || (priv->dup_acks == 2)) { // Limited Transmit
+ cwnd += priv->dup_acks * priv->mss;
+ }
+ nWindow = min(priv->snd_wnd, cwnd);
+ nInFlight = priv->snd_nxt - priv->snd_una;
+ nUseable = (nInFlight < nWindow) ? (nWindow - nInFlight) : 0;
+ snd_buffered = pseudo_tcp_fifo_get_buffered (&priv->sbuf);
+ if (snd_buffered < nInFlight) /* iff a FIN has been sent */
+ nAvailable = 0;
+ else
+ nAvailable = min(snd_buffered - nInFlight, priv->mss);
+
+ if (nAvailable > nUseable) {
+ if (nUseable * 4 < nWindow) {
+ // RFC 813 - avoid SWS
+ nAvailable = 0;
+ } else {
+ nAvailable = nUseable;
+ }
+ }
+
+ if (bFirst) {
+ gsize available_space = pseudo_tcp_fifo_get_write_remaining (&priv->sbuf);
+
+ bFirst = FALSE;
+ DEBUG (PSEUDO_TCP_DEBUG_VERBOSE, "[cwnd: %u nWindow: %u nInFlight: %u "
+ "nAvailable: %u nQueued: %" G_GSIZE_FORMAT " nEmpty: %" G_GSIZE_FORMAT
+ " nWaiting: %zu ssthresh: %u]",
+ priv->cwnd, nWindow, nInFlight, nAvailable, snd_buffered,
+ available_space, snd_buffered - nInFlight, priv->ssthresh);
+ }
+
+ if (sflags == sfDuplicateAck) {
+ packet(self, priv->snd_nxt, 0, 0, 0, now);
+ sflags = sfNone;
+ continue;
+ }
+
+ if (nAvailable == 0 && sflags != sfFin && sflags != sfRst) {
+ if (sflags == sfNone)
+ return;
+
+ // If this is an immediate ack, or the second delayed ack
+ if ((sflags == sfImmediateAck || sflags == sfDuplicateAck) ||
+ priv->t_ack) {
+ packet(self, priv->snd_nxt, 0, 0, 0, now);
+ } else {
+ priv->t_ack = now;
+ }
+ return;
+ }
+
+ // Nagle algorithm
+ // If there is data already in-flight, and we haven't a full segment of
+ // data ready to send then hold off until we get more to send, or the
+ // in-flight data is acknowledged.
+ if (priv->use_nagling && sflags != sfFin && sflags != sfRst &&
+ (priv->snd_nxt > priv->snd_una) &&
+ (nAvailable < priv->mss)) {
+ return;
+ }
+
+ // Find the next segment to transmit
+ iter = g_queue_peek_head_link (&priv->unsent_slist);
+ if (iter == NULL)
+ return;
+ sseg = iter->data;
+
+ // If the segment is too large, break it into two
+ if (sseg->len > nAvailable && sflags != sfFin && sflags != sfRst) {
+ SSegment *subseg = g_slice_new0 (SSegment);
+ subseg->seq = sseg->seq + nAvailable;
+ subseg->len = sseg->len - nAvailable;
+ subseg->flags = sseg->flags;
+
+ sseg->len = nAvailable;
+ g_queue_insert_after (&priv->unsent_slist, iter, subseg);
+ g_queue_insert_after (&priv->slist, g_queue_find (&priv->slist, sseg),
+ subseg);
+ }
+
+ transmit_status = transmit(self, sseg, now);
+ if (transmit_status != 0) {
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "transmit failed");
+
+ // TODO: Is this the right thing ?
+ closedown (self, transmit_status, CLOSEDOWN_REMOTE);
+ return;
+ }
+
+ if (sflags == sfImmediateAck || sflags == sfDelayedAck)
+ sflags = sfNone;
+ }
+}
+
+/* If @source is %CLOSEDOWN_REMOTE, don’t send an RST packet, since closedown()
+ * has been called as a result of an RST segment being received.
+ * See: RFC 1122, §4.2.2.13. */
+static void
+closedown (PseudoTcpSocket *self, guint32 err, ClosedownSource source)
+{
+ PseudoTcpSocketPrivate *priv = self->priv;
+
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "Closing down socket %p with %s error %u.",
+ self, (source == CLOSEDOWN_LOCAL) ? "local" : "remote", err);
+
+ if (source == CLOSEDOWN_LOCAL && priv->support_fin_ack) {
+ queue_rst_message (self);
+ attempt_send (self, sfRst);
+ } else if (source == CLOSEDOWN_LOCAL) {
+ priv->shutdown = SD_FORCEFUL;
+ }
+
+ /* ‘Cute’ little navigation through the state machine to avoid breaking the
+ * invariant that CLOSED can only be reached from TIME-WAIT or LAST-ACK. */
+ switch (priv->state) {
+ case PSEUDO_TCP_LISTEN:
+ case PSEUDO_TCP_SYN_SENT:
+ break;
+ case PSEUDO_TCP_SYN_RECEIVED:
+ case PSEUDO_TCP_ESTABLISHED:
+ set_state (self, PSEUDO_TCP_FIN_WAIT_1);
+ /* Fall through. */
+ case PSEUDO_TCP_FIN_WAIT_1:
+ set_state (self, PSEUDO_TCP_FIN_WAIT_2);
+ /* Fall through. */
+ case PSEUDO_TCP_FIN_WAIT_2:
+ case PSEUDO_TCP_CLOSING:
+ set_state (self, PSEUDO_TCP_TIME_WAIT);
+ break;
+ case PSEUDO_TCP_CLOSE_WAIT:
+ set_state (self, PSEUDO_TCP_LAST_ACK);
+ break;
+ case PSEUDO_TCP_LAST_ACK:
+ case PSEUDO_TCP_TIME_WAIT:
+ case PSEUDO_TCP_CLOSED:
+ default:
+ break;
+ }
+
+ set_state_closed (self, err);
+}
+
+static void
+adjustMTU(PseudoTcpSocket *self)
+{
+ PseudoTcpSocketPrivate *priv = self->priv;
+
+ // Determine our current mss level, so that we can adjust appropriately later
+ for (priv->msslevel = 0;
+ PACKET_MAXIMUMS[priv->msslevel + 1] > 0;
+ ++priv->msslevel) {
+ if (((guint16)PACKET_MAXIMUMS[priv->msslevel]) <= priv->mtu_advise) {
+ break;
+ }
+ }
+ priv->mss = priv->mtu_advise - PACKET_OVERHEAD;
+ // !?! Should we reset priv->largest here?
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "Adjusting mss to %u bytes", priv->mss);
+ // Enforce minimums on ssthresh and cwnd
+ priv->ssthresh = max(priv->ssthresh, 2 * priv->mss);
+ priv->cwnd = max(priv->cwnd, priv->mss);
+}
+
+static void
+apply_window_scale_option (PseudoTcpSocket *self, guint8 scale_factor)
+{
+ PseudoTcpSocketPrivate *priv = self->priv;
+
+ priv->swnd_scale = scale_factor;
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "Setting scale factor to %u", scale_factor);
+}
+
+static void
+apply_fin_ack_option (PseudoTcpSocket *self)
+{
+ PseudoTcpSocketPrivate *priv = self->priv;
+
+ priv->support_fin_ack = TRUE;
+}
+
+static void
+apply_option (PseudoTcpSocket *self, guint8 kind, const guint8 *data,
+ guint32 len)
+{
+ switch (kind) {
+ case TCP_OPT_MSS:
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL,
+ "Peer specified MSS option which is not supported.");
+ // TODO: Implement.
+ break;
+ case TCP_OPT_WND_SCALE:
+ // Window scale factor.
+ // http://www.ietf.org/rfc/rfc1323.txt
+ if (len != 1) {
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "Invalid window scale option received.");
+ return;
+ }
+ apply_window_scale_option(self, data[0]);
+ break;
+ case TCP_OPT_FIN_ACK:
+ // FIN-ACK support.
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "FIN-ACK support enabled.");
+ apply_fin_ack_option (self);
+ break;
+ case TCP_OPT_EOL:
+ case TCP_OPT_NOOP:
+ /* Nothing to do. */
+ break;
+ default:
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "Invalid TCP option %u", kind);
+ break;
+ }
+}
+
+
+static void
+parse_options (PseudoTcpSocket *self, const guint8 *data, guint32 len)
+{
+ PseudoTcpSocketPrivate *priv = self->priv;
+ gboolean has_window_scaling_option = FALSE;
+ gboolean has_fin_ack_option = FALSE;
+ guint32 pos = 0;
+
+ // See http://www.freesoft.org/CIE/Course/Section4/8.htm for
+ // parsing the options list.
+ while (pos < len) {
+ guint8 kind = TCP_OPT_EOL;
+ guint8 opt_len;
+
+ if (len < pos + 1)
+ return;
+
+ kind = data[pos];
+ pos++;
+
+ if (kind == TCP_OPT_EOL) {
+ // End of option list.
+ break;
+ } else if (kind == TCP_OPT_NOOP) {
+ // No op.
+ continue;
+ }
+
+ if (len < pos + 1)
+ return;
+
+ // Length of this option.
+ opt_len = data[pos];
+ pos++;
+
+ if (len < pos + opt_len)
+ return;
+
+ // Content of this option.
+ if (opt_len <= len - pos) {
+ apply_option (self, kind, data + pos, opt_len);
+ pos += opt_len;
+ } else {
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "Invalid option length received.");
+ return;
+ }
+
+ if (kind == TCP_OPT_WND_SCALE)
+ has_window_scaling_option = TRUE;
+ else if (kind == TCP_OPT_FIN_ACK)
+ has_fin_ack_option = TRUE;
+ }
+
+ if (!has_window_scaling_option) {
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "Peer doesn't support window scaling");
+ if (priv->rwnd_scale > 0) {
+ // Peer doesn't support TCP options and window scaling.
+ // Revert receive buffer size to default value.
+ resize_receive_buffer (self, DEFAULT_RCV_BUF_SIZE);
+ priv->swnd_scale = 0;
+ }
+ }
+
+ if (!has_fin_ack_option) {
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "Peer doesn't support FIN-ACK");
+ priv->support_fin_ack = FALSE;
+ }
+}
+
+static void
+resize_send_buffer (PseudoTcpSocket *self, guint32 new_size)
+{
+ PseudoTcpSocketPrivate *priv = self->priv;
+
+ priv->sbuf_len = new_size;
+ pseudo_tcp_fifo_set_capacity (&priv->sbuf, new_size);
+}
+
+
+static void
+resize_receive_buffer (PseudoTcpSocket *self, guint32 new_size)
+{
+ PseudoTcpSocketPrivate *priv = self->priv;
+ guint8 scale_factor = 0;
+ gboolean result;
+ gsize available_space;
+
+ if (priv->rbuf_len == new_size)
+ return;
+
+ // Determine the scale factor such that the scaled window size can fit
+ // in a 16-bit unsigned integer.
+ while (new_size > 0xFFFF) {
+ ++scale_factor;
+ new_size >>= 1;
+ }
+
+ // Determine the proper size of the buffer.
+ new_size <<= scale_factor;
+ result = pseudo_tcp_fifo_set_capacity (&priv->rbuf, new_size);
+
+ // Make sure the new buffer is large enough to contain data in the old
+ // buffer. This should always be true because this method is called either
+ // before connection is established or when peers are exchanging connect
+ // messages.
+ g_assert(result);
+ priv->rbuf_len = new_size;
+ priv->rwnd_scale = scale_factor;
+ priv->ssthresh = new_size;
+
+ available_space = pseudo_tcp_fifo_get_write_remaining (&priv->rbuf);
+ priv->rcv_wnd = available_space;
+}
+
+gint
+pseudo_tcp_socket_get_available_bytes (PseudoTcpSocket *self)
+{
+ PseudoTcpSocketPrivate *priv = self->priv;
+
+ return pseudo_tcp_fifo_get_buffered (&priv->rbuf);
+}
+
+gboolean
+pseudo_tcp_socket_can_send (PseudoTcpSocket *self)
+{
+ return (pseudo_tcp_socket_get_available_send_space (self) > 0);
+}
+
+gsize
+pseudo_tcp_socket_get_available_send_space (PseudoTcpSocket *self)
+{
+ PseudoTcpSocketPrivate *priv = self->priv;
+ gsize ret;
+
+ if (!pseudo_tcp_state_has_sent_fin (priv->state)) {
+ ret = pseudo_tcp_fifo_get_write_remaining (&priv->sbuf);
+ } else {
+ ret = 0;
+ }
+
+ if (ret == 0)
+ priv->bWriteEnable = TRUE;
+
+ return ret;
+}
+
+/* State names are capitalised and formatted as in RFC 793. */
+static const gchar *
+pseudo_tcp_state_get_name (PseudoTcpState state)
+{
+ switch (state) {
+ case PSEUDO_TCP_LISTEN: return "LISTEN";
+ case PSEUDO_TCP_SYN_SENT: return "SYN-SENT";
+ case PSEUDO_TCP_SYN_RECEIVED: return "SYN-RECEIVED";
+ case PSEUDO_TCP_ESTABLISHED: return "ESTABLISHED";
+ case PSEUDO_TCP_CLOSED: return "CLOSED";
+ case PSEUDO_TCP_FIN_WAIT_1: return "FIN-WAIT-1";
+ case PSEUDO_TCP_FIN_WAIT_2: return "FIN-WAIT-2";
+ case PSEUDO_TCP_CLOSING: return "CLOSING";
+ case PSEUDO_TCP_TIME_WAIT: return "TIME-WAIT";
+ case PSEUDO_TCP_CLOSE_WAIT: return "CLOSE-WAIT";
+ case PSEUDO_TCP_LAST_ACK: return "LAST-ACK";
+ default: return "UNKNOWN";
+ }
+}
+
+static void
+set_state (PseudoTcpSocket *self, PseudoTcpState new_state)
+{
+ PseudoTcpSocketPrivate *priv = self->priv;
+ PseudoTcpState old_state = priv->state;
+
+ if (new_state == old_state)
+ return;
+
+ DEBUG (PSEUDO_TCP_DEBUG_NORMAL, "State %s → %s.",
+ pseudo_tcp_state_get_name (old_state),
+ pseudo_tcp_state_get_name (new_state));
+
+ /* Check whether it’s a valid state transition. */
+#define TRANSITION(OLD, NEW) \
+ (old_state == PSEUDO_TCP_##OLD && \
+ new_state == PSEUDO_TCP_##NEW)
+
+ /* Valid transitions. See: RFC 793, p23; RFC 1122, §4.2.2.8. */
+ g_assert (/* RFC 793, p23. */
+ TRANSITION (CLOSED, SYN_SENT) ||
+ TRANSITION (SYN_SENT, CLOSED) ||
+ TRANSITION (CLOSED, LISTEN) ||
+ TRANSITION (LISTEN, CLOSED) ||
+ TRANSITION (LISTEN, SYN_SENT) ||
+ TRANSITION (LISTEN, SYN_RECEIVED) ||
+ TRANSITION (SYN_SENT, SYN_RECEIVED) ||
+ TRANSITION (SYN_RECEIVED, ESTABLISHED) ||
+ TRANSITION (SYN_SENT, ESTABLISHED) ||
+ TRANSITION (SYN_RECEIVED, FIN_WAIT_1) ||
+ TRANSITION (ESTABLISHED, FIN_WAIT_1) ||
+ TRANSITION (ESTABLISHED, CLOSE_WAIT) ||
+ TRANSITION (FIN_WAIT_1, FIN_WAIT_2) ||
+ TRANSITION (FIN_WAIT_1, CLOSING) ||
+ TRANSITION (CLOSE_WAIT, LAST_ACK) ||
+ TRANSITION (FIN_WAIT_2, TIME_WAIT) ||
+ TRANSITION (CLOSING, TIME_WAIT) ||
+ TRANSITION (LAST_ACK, CLOSED) ||
+ TRANSITION (TIME_WAIT, CLOSED) ||
+ /* RFC 1122, §4.2.2.8. */
+ TRANSITION (SYN_RECEIVED, LISTEN) ||
+ TRANSITION (FIN_WAIT_1, TIME_WAIT));
+
+#undef TRANSITION
+
+ priv->state = new_state;
+}
+
+static void
+set_state_established (PseudoTcpSocket *self)
+{
+ PseudoTcpSocketPrivate *priv = self->priv;
+
+ set_state (self, PSEUDO_TCP_ESTABLISHED);
+
+ adjustMTU (self);
+ if (priv->callbacks.PseudoTcpOpened)
+ priv->callbacks.PseudoTcpOpened (self, priv->callbacks.user_data);
+}
+
+/* (err == 0) means no error. */
+static void
+set_state_closed (PseudoTcpSocket *self, guint32 err)
+{
+ PseudoTcpSocketPrivate *priv = self->priv;
+
+ set_state (self, PSEUDO_TCP_CLOSED);
+
+ /* Only call the callback if there was an error. */
+ if (priv->callbacks.PseudoTcpClosed && err != 0)
+ priv->callbacks.PseudoTcpClosed (self, err, priv->callbacks.user_data);
+}
+
+gboolean
+pseudo_tcp_socket_is_closed (PseudoTcpSocket *self)
+{
+ PseudoTcpSocketPrivate *priv = self->priv;
+
+ return (priv->state == PSEUDO_TCP_CLOSED);
+}
+
+gboolean
+pseudo_tcp_socket_is_closed_remotely (PseudoTcpSocket *self)
+{
+ PseudoTcpSocketPrivate *priv = self->priv;
+
+ return pseudo_tcp_state_has_received_fin (priv->state);
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2010, 2014 Collabora Ltd.
+ * Contact: Philip Withnall
+
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ * Philip Withnall, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef __LIBNICE_PSEUDOTCP_H__
+#define __LIBNICE_PSEUDOTCP_H__
+
+/**
+ * SECTION:pseudotcp
+ * @short_description: Pseudo TCP implementation
+ * @include: pseudotcp.h
+ * @stability: Stable
+ *
+ * The #PseudoTcpSocket is an object implementing a Pseudo Tcp Socket for use
+ * over UDP.
+ * The socket will implement a subset of the TCP stack to allow for a reliable
+ * transport over non-reliable sockets (such as UDP).
+ *
+ * See the file tests/test-pseudotcp.c in the source package for an example
+ * of how to use the object.
+ *
+ * Since: 0.0.11
+ */
+
+
+
+#include <glib-object.h>
+
+#ifndef __GTK_DOC_IGNORE__
+#ifdef G_OS_WIN32
+# include <winsock2.h>
+
+#ifndef ECONNABORTED
+# define ECONNABORTED WSAECONNABORTED
+#endif
+
+#ifndef ENOTCONN
+# define ENOTCONN WSAENOTCONN
+#endif
+
+#ifndef EWOULDBLOCK
+# define EWOULDBLOCK WSAEWOULDBLOCK
+#endif
+
+#ifndef ECONNRESET
+# define ECONNRESET WSAECONNRESET
+#endif
+
+#ifndef EMSGSIZE
+# define EMSGSIZE WSAEMSGSIZE
+#endif
+
+#ifndef ETIMEDOUT
+# define ETIMEDOUT WSAETIMEDOUT
+#endif
+#endif
+#endif
+
+#include "agent.h"
+
+G_BEGIN_DECLS
+
+/**
+ * PseudoTcpSocket:
+ *
+ * The #PseudoTcpSocket is the GObject implementing the Pseudo TCP Socket
+ *
+ * Since: 0.0.11
+ */
+typedef struct _PseudoTcpSocket PseudoTcpSocket;
+
+typedef struct _PseudoTcpSocketClass PseudoTcpSocketClass;
+
+GType pseudo_tcp_socket_get_type (void);
+
+/* TYPE MACROS */
+#define PSEUDO_TCP_SOCKET_TYPE \
+ (pseudo_tcp_socket_get_type ())
+#define PSEUDO_TCP_SOCKET(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), PSEUDO_TCP_SOCKET_TYPE, \
+ PseudoTcpSocket))
+#define PSEUDO_TCP_SOCKET_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), PSEUDO_TCP_SOCKET_TYPE, \
+ PseudoTcpSocketClass))
+#define IS_PSEUDO_TCP_SOCKET(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), PSEUDO_TCP_SOCKET_TYPE))
+#define IS_PSEUDO_TCP_SOCKET_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), PSEUDO_TCP_SOCKET_TYPE))
+#define PSEUDOTCP_SOCKET_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), PSEUDO_TCP_SOCKET_TYPE, \
+ PseudoTcpSocketClass))
+
+/**
+ * PseudoTcpDebugLevel:
+ * @PSEUDO_TCP_DEBUG_NONE: Disable debug messages
+ * @PSEUDO_TCP_DEBUG_NORMAL: Enable basic debug messages
+ * @PSEUDO_TCP_DEBUG_VERBOSE: Enable verbose debug messages
+ *
+ * Valid values of debug levels to be set.
+ *
+ * Since: 0.0.11
+ */
+typedef enum {
+ PSEUDO_TCP_DEBUG_NONE = 0,
+ PSEUDO_TCP_DEBUG_NORMAL,
+ PSEUDO_TCP_DEBUG_VERBOSE,
+} PseudoTcpDebugLevel;
+
+/**
+ * PseudoTcpState:
+ * @PSEUDO_TCP_LISTEN: The socket's initial state. The socket isn't connected and is
+ * listening for an incoming connection
+ * @PSEUDO_TCP_SYN_SENT: The socket has sent a connection request (SYN) packet and is
+ * waiting for an answer
+ * @PSEUDO_TCP_SYN_RECEIVED: The socket has received a connection request (SYN) packet.
+ * @PSEUDO_TCP_ESTABLISHED: The socket is connected
+ * @PSEUDO_TCP_CLOSED: The socket has been closed
+ * @PSEUDO_TCP_FIN_WAIT_1: The socket has been closed locally but not remotely
+ * (Since: 0.1.8)
+ * @PSEUDO_TCP_FIN_WAIT_2: The socket has been closed locally but not remotely
+ * (Since: 0.1.8)
+ * @PSEUDO_TCP_CLOSING: The socket has been closed locally and remotely
+ * (Since: 0.1.8)
+ * @PSEUDO_TCP_TIME_WAIT: The socket has been closed locally and remotely
+ * (Since: 0.1.8)
+ * @PSEUDO_TCP_CLOSE_WAIT: The socket has been closed remotely but not locally
+ * (Since: 0.1.8)
+ * @PSEUDO_TCP_LAST_ACK: The socket has been closed locally and remotely
+ * (Since: 0.1.8)
+ *
+ * An enum representing the state of the #PseudoTcpSocket. These states
+ * correspond to the TCP states in RFC 793.
+ * <para> See also: #PseudoTcpSocket:state </para>
+ *
+ * Since: 0.0.11
+ */
+typedef enum {
+ PSEUDO_TCP_LISTEN,
+ PSEUDO_TCP_SYN_SENT,
+ PSEUDO_TCP_SYN_RECEIVED,
+ PSEUDO_TCP_ESTABLISHED,
+ PSEUDO_TCP_CLOSED,
+ PSEUDO_TCP_FIN_WAIT_1,
+ PSEUDO_TCP_FIN_WAIT_2,
+ PSEUDO_TCP_CLOSING,
+ PSEUDO_TCP_TIME_WAIT,
+ PSEUDO_TCP_CLOSE_WAIT,
+ PSEUDO_TCP_LAST_ACK,
+} PseudoTcpState;
+
+/**
+ * PseudoTcpWriteResult:
+ * @WR_SUCCESS: The write operation was successful
+ * @WR_TOO_LARGE: The socket type requires that message be sent atomically
+ * and the size of the message to be sent made this impossible.
+ * @WR_FAIL: There was an error sending the message
+ *
+ * An enum representing the result value of the write operation requested by
+ * the #PseudoTcpSocket.
+ * <para> See also: %PseudoTcpCallbacks:WritePacket </para>
+ *
+ * Since: 0.0.11
+ */
+typedef enum {
+ WR_SUCCESS,
+ WR_TOO_LARGE,
+ WR_FAIL
+} PseudoTcpWriteResult;
+
+/**
+ * PseudoTcpShutdown:
+ * @PSEUDO_TCP_SHUTDOWN_RD: Shut down the local reader only
+ * @PSEUDO_TCP_SHUTDOWN_WR: Shut down the local writer only
+ * @PSEUDO_TCP_SHUTDOWN_RDWR: Shut down both reading and writing
+ *
+ * Options for which parts of a connection to shut down when calling
+ * pseudo_tcp_socket_shutdown(). These correspond to the values passed to POSIX
+ * shutdown().
+ *
+ * Since: 0.1.8
+ */
+typedef enum {
+ PSEUDO_TCP_SHUTDOWN_RD,
+ PSEUDO_TCP_SHUTDOWN_WR,
+ PSEUDO_TCP_SHUTDOWN_RDWR,
+} PseudoTcpShutdown;
+
+/**
+ * PseudoTcpCallbacks:
+ * @user_data: A user defined pointer to be passed to the callbacks
+ * @PseudoTcpOpened: The #PseudoTcpSocket is now connected
+ * @PseudoTcpReadable: The socket is readable
+ * @PseudoTcpWritable: The socket is writable
+ * @PseudoTcpClosed: The socket was closed (both sides)
+ * @WritePacket: This callback is called when the socket needs to send data.
+ *
+ * A structure containing callbacks functions that will be called by the
+ * #PseudoTcpSocket when some events happen.
+ * <para> See also: #PseudoTcpWriteResult </para>
+ *
+ * Since: 0.0.11
+ */
+typedef struct {
+ gpointer user_data;
+ void (*PseudoTcpOpened) (PseudoTcpSocket *tcp, gpointer data);
+ void (*PseudoTcpReadable) (PseudoTcpSocket *tcp, gpointer data);
+ void (*PseudoTcpWritable) (PseudoTcpSocket *tcp, gpointer data);
+ void (*PseudoTcpClosed) (PseudoTcpSocket *tcp, guint32 error, gpointer data);
+ PseudoTcpWriteResult (*WritePacket) (PseudoTcpSocket *tcp,
+ const gchar * buffer, guint32 len, gpointer data);
+} PseudoTcpCallbacks;
+
+/**
+ * pseudo_tcp_socket_new:
+ * @conversation: The conversation id for the socket.
+ * @callbacks: A pointer to the #PseudoTcpCallbacks structure for getting
+ * notified of the #PseudoTcpSocket events.
+ *
+ * Creates a new #PseudoTcpSocket for the specified conversation
+ *
+ <note>
+ <para>
+ The @callbacks must be non-NULL, in order to get notified of packets the
+ socket needs to send.
+ </para>
+ <para>
+ If the @callbacks structure was dynamicly allocated, it can be freed
+ after the call @pseudo_tcp_socket_new
+ </para>
+ </note>
+ *
+ * Returns: The new #PseudoTcpSocket object, %NULL on error
+ *
+ * Since: 0.0.11
+ */
+PseudoTcpSocket *pseudo_tcp_socket_new (guint32 conversation,
+ PseudoTcpCallbacks *callbacks);
+
+
+/**
+ * pseudo_tcp_socket_connect:
+ * @self: The #PseudoTcpSocket object.
+ *
+ * Connects the #PseudoTcpSocket to the peer with the same conversation id.
+ * The connection will only be successful after the
+ * %PseudoTcpCallbacks:PseudoTcpOpened callback is called
+ *
+ * Returns: %TRUE on success, %FALSE on failure (not in %TCP_LISTEN state)
+ * <para> See also: pseudo_tcp_socket_get_error() </para>
+ *
+ * Since: 0.0.11
+ */
+gboolean pseudo_tcp_socket_connect(PseudoTcpSocket *self);
+
+
+/**
+ * pseudo_tcp_socket_recv:
+ * @self: The #PseudoTcpSocket object.
+ * @buffer: The buffer to fill with received data
+ * @len: The length of @buffer
+ *
+ * Receive data from the socket.
+ *
+ <note>
+ <para>
+ Only call this on the %PseudoTcpCallbacks:PseudoTcpReadable callback.
+ </para>
+ <para>
+ This function should be called in a loop. If this function does not
+ return -1 with EWOULDBLOCK as the error, the
+ %PseudoTcpCallbacks:PseudoTcpReadable callback will not be called again.
+ </para>
+ </note>
+ *
+ * Returns: The number of bytes received or -1 in case of error
+ * <para> See also: pseudo_tcp_socket_get_error() </para>
+ *
+ * Since: 0.0.11
+ */
+gint pseudo_tcp_socket_recv(PseudoTcpSocket *self, char * buffer, size_t len);
+
+
+/**
+ * pseudo_tcp_socket_send:
+ * @self: The #PseudoTcpSocket object.
+ * @buffer: The buffer with data to send
+ * @len: The length of @buffer
+ *
+ * Send data on the socket.
+ *
+ <note>
+ <para>
+ If this function return -1 with EWOULDBLOCK as the error, or if the return
+ value is lower than @len, then the %PseudoTcpCallbacks:PseudoTcpWritable
+ callback will be called when the socket will become writable.
+ </para>
+ </note>
+ *
+ * Returns: The number of bytes sent or -1 in case of error
+ * <para> See also: pseudo_tcp_socket_get_error() </para>
+ *
+ * Since: 0.0.11
+ */
+gint pseudo_tcp_socket_send(PseudoTcpSocket *self, const char * buffer,
+ guint32 len);
+
+
+/**
+ * pseudo_tcp_socket_close:
+ * @self: The #PseudoTcpSocket object.
+ * @force: %TRUE to close the socket forcefully, %FALSE to close it gracefully
+ *
+ * Close the socket for sending. If @force is set to %FALSE, the socket will
+ * finish sending pending data before closing. If it is set to %TRUE, the socket
+ * will discard pending data and close the connection immediately (sending a TCP
+ * RST segment).
+ *
+ * The socket will be closed in both directions – sending and receiving – and
+ * any pending received data must be read before calling this function, by
+ * calling pseudo_tcp_socket_recv() until it blocks. If any pending data is in
+ * the receive buffer when pseudo_tcp_socket_close() is called, a TCP RST
+ * segment will be sent to the peer to notify it of the data loss.
+ *
+ <note>
+ <para>
+ The %PseudoTcpCallbacks:PseudoTcpClosed callback will not be called once
+ the socket gets closed. It is only used for aborted connection.
+ Instead, the socket gets closed when the pseudo_tcp_socket_get_next_clock()
+ function returns FALSE.
+ </para>
+ </note>
+ *
+ * <para> See also: pseudo_tcp_socket_get_next_clock() </para>
+ *
+ * Since: 0.0.11
+ */
+void pseudo_tcp_socket_close(PseudoTcpSocket *self, gboolean force);
+
+/**
+ * pseudo_tcp_socket_shutdown:
+ * @self: The #PseudoTcpSocket object.
+ * @how: The directions of the connection to shut down.
+ *
+ * Shut down sending, receiving, or both on the socket, depending on the value
+ * of @how. The behaviour of pseudo_tcp_socket_send() and
+ * pseudo_tcp_socket_recv() will immediately change after this function returns
+ * (depending on the value of @how), though the socket may continue to process
+ * network traffic in the background even if sending or receiving data is
+ * forbidden.
+ *
+ * This is equivalent to the POSIX shutdown() function. Setting @how to
+ * %PSEUDO_TCP_SHUTDOWN_RDWR is equivalent to calling pseudo_tcp_socket_close().
+ *
+ * Since: 0.1.8
+ */
+void pseudo_tcp_socket_shutdown (PseudoTcpSocket *self, PseudoTcpShutdown how);
+
+/**
+ * pseudo_tcp_socket_get_error:
+ * @self: The #PseudoTcpSocket object.
+ *
+ * Return the last encountered error.
+ *
+ <note>
+ <para>
+ The return value can be :
+ <para>
+ EINVAL (for pseudo_tcp_socket_connect()).
+ </para>
+ <para>
+ EWOULDBLOCK or ENOTCONN (for pseudo_tcp_socket_recv() and
+ pseudo_tcp_socket_send()).
+ </para>
+ </para>
+ </note>
+ *
+ * Returns: The error code
+ * <para> See also: pseudo_tcp_socket_connect() </para>
+ * <para> See also: pseudo_tcp_socket_recv() </para>
+ * <para> See also: pseudo_tcp_socket_send() </para>
+ *
+ * Since: 0.0.11
+ */
+int pseudo_tcp_socket_get_error(PseudoTcpSocket *self);
+
+
+/**
+ * pseudo_tcp_socket_get_next_clock:
+ * @self: The #PseudoTcpSocket object.
+ * @timeout: A pointer to be filled with the new timeout.
+ *
+ * Call this to determine the timeout needed before the next time call
+ * to pseudo_tcp_socket_notify_clock() should be made.
+ *
+ * Returns: %TRUE if @timeout was filled, %FALSE if the socket is closed and
+ * ready to be destroyed.
+ *
+ * <para> See also: pseudo_tcp_socket_notify_clock() </para>
+ *
+ * Since: 0.0.11
+ */
+gboolean pseudo_tcp_socket_get_next_clock(PseudoTcpSocket *self,
+ guint64 *timeout);
+
+
+/**
+ * pseudo_tcp_socket_notify_clock:
+ * @self: The #PseudoTcpSocket object.
+ *
+ * Start the processing of receiving data, pending data or syn/acks.
+ * Call this based on timeout value returned by
+ * pseudo_tcp_socket_get_next_clock().
+ * It's ok to call this too frequently.
+ *
+ * <para> See also: pseudo_tcp_socket_get_next_clock() </para>
+ *
+ * Since: 0.0.11
+ */
+void pseudo_tcp_socket_notify_clock(PseudoTcpSocket *self);
+
+
+/**
+ * pseudo_tcp_socket_notify_mtu:
+ * @self: The #PseudoTcpSocket object.
+ * @mtu: The new MTU of the socket
+ *
+ * Set the MTU of the socket
+ *
+ * Since: 0.0.11
+ */
+void pseudo_tcp_socket_notify_mtu(PseudoTcpSocket *self, guint16 mtu);
+
+
+/**
+ * pseudo_tcp_socket_notify_packet:
+ * @self: The #PseudoTcpSocket object.
+ * @buffer: The buffer containing the received data
+ * @len: The length of @buffer
+ *
+ * Notify the #PseudoTcpSocket when a new packet arrives
+ *
+ * Returns: %TRUE if the packet was processed successfully, %FALSE otherwise
+ *
+ * Since: 0.0.11
+ */
+gboolean pseudo_tcp_socket_notify_packet(PseudoTcpSocket *self,
+ const gchar * buffer, guint32 len);
+
+
+/**
+ * pseudo_tcp_socket_notify_message:
+ * @self: The #PseudoTcpSocket object.
+ * @message: A #NiceInputMessage containing the received data.
+ *
+ * Notify the #PseudoTcpSocket that a new message has arrived, and enqueue the
+ * data in its buffers to the #PseudoTcpSocket’s receive buffer.
+ *
+ * Returns: %TRUE if the packet was processed successfully, %FALSE otherwise
+ *
+ * Since: 0.1.5
+ */
+gboolean pseudo_tcp_socket_notify_message (PseudoTcpSocket *self,
+ NiceInputMessage *message);
+
+
+/**
+ * pseudo_tcp_set_debug_level:
+ * @level: The level of debug to set
+ *
+ * Sets the debug level to enable/disable normal/verbose debug messages.
+ *
+ * Since: 0.0.11
+ */
+void pseudo_tcp_set_debug_level (PseudoTcpDebugLevel level);
+
+
+/**
+ * pseudo_tcp_socket_get_available_bytes:
+ * @self: The #PseudoTcpSocket object.
+ *
+ * Gets the number of bytes of data in the buffer that can be read without
+ * receiving more packets from the network.
+ *
+ * Returns: The number of bytes or -1 if the connection is not established
+ *
+ * Since: 0.1.5
+ */
+
+gint pseudo_tcp_socket_get_available_bytes (PseudoTcpSocket *self);
+
+/**
+ * pseudo_tcp_socket_can_send:
+ * @self: The #PseudoTcpSocket object.
+ *
+ * Returns if there is space in the send buffer to send any data.
+ *
+ * Returns: %TRUE if data can be sent, %FALSE otherwise
+ *
+ * Since: 0.1.5
+ */
+
+gboolean pseudo_tcp_socket_can_send (PseudoTcpSocket *self);
+
+/**
+ * pseudo_tcp_socket_get_available_send_space:
+ * @self: The #PseudoTcpSocket object.
+ *
+ * Gets the number of bytes of space available in the transmission buffer.
+ *
+ * Returns: The number of bytes, or 0 if the connection is not established.
+ *
+ * Since: 0.1.5
+ */
+gsize pseudo_tcp_socket_get_available_send_space (PseudoTcpSocket *self);
+
+/**
+ * pseudo_tcp_socket_set_time:
+ * @self: The #PseudoTcpSocket object.
+ * @current_time: Current monotonic time, in milliseconds; or zero to use the
+ * system monotonic clock.
+ *
+ * Sets the current monotonic time to be used by the TCP socket when calculating
+ * timeouts and expiry times. If this function is not called, or is called with
+ * @current_time as zero, g_get_monotonic_time() will be used. Otherwise, the
+ * specified @current_time will be used until it is updated by calling this
+ * function again.
+ *
+ * This function is intended for testing only, and should not be used in
+ * production code.
+ *
+ * Since: 0.1.8
+ */
+void pseudo_tcp_socket_set_time (PseudoTcpSocket *self, guint32 current_time);
+
+/**
+ * pseudo_tcp_socket_is_closed:
+ * @self: The #PseudoTcpSocket object.
+ *
+ * Gets whether the socket is closed, with the shutdown handshake completed,
+ * and both peers no longer able to read or write data to the connection.
+ *
+ * Returns: %TRUE if the socket is closed in both directions, %FALSE otherwise
+ * Since: 0.1.8
+ */
+gboolean pseudo_tcp_socket_is_closed (PseudoTcpSocket *self);
+
+/**
+ * pseudo_tcp_socket_is_closed_remotely:
+ * @self: The #PseudoTcpSocket object.
+ *
+ * Gets whether the socket has been closed on the remote peer’s side of the
+ * connection (i.e. whether pseudo_tcp_socket_close() has been called there).
+ * This is guaranteed to return %TRUE if pseudo_tcp_socket_is_closed() returns
+ * %TRUE. It will not return %TRUE after pseudo_tcp_socket_close() is called
+ * until a FIN segment is received from the remote peer.
+ *
+ * Returns: %TRUE if the remote peer has closed its side of the connection,
+ * %FALSE otherwise
+ * Since: 0.1.8
+ */
+gboolean pseudo_tcp_socket_is_closed_remotely (PseudoTcpSocket *self);
+
+G_END_DECLS
+
+#endif /* __LIBNICE_PSEUDOTCP_H__ */
+
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2006-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2006-2009 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Dafydd Harries, Collabora Ltd.
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#include "stream.h"
+
+/* Simple tracking for the number of alive streams. These must be accessed
+ * atomically. */
+static volatile unsigned int n_streams_created = 0;
+static volatile unsigned int n_streams_destroyed = 0;
+
+G_DEFINE_TYPE (NiceStream, nice_stream, G_TYPE_OBJECT);
+
+static void
+nice_stream_finalize (GObject *obj);
+
+/*
+ * @file stream.c
+ * @brief ICE stream functionality
+ */
+NiceStream *
+nice_stream_new (guint stream_id, guint n_components, NiceAgent *agent)
+{
+ NiceStream *stream = NULL;
+ guint n;
+
+ stream = g_object_new (NICE_TYPE_STREAM, NULL);
+
+ stream->id = stream_id;
+
+ /* Create the components. */
+ for (n = 0; n < n_components; n++) {
+ NiceComponent *component = NULL;
+
+ component = nice_component_new (n + 1, agent, stream);
+ stream->components = g_slist_append (stream->components, component);
+ }
+
+ stream->n_components = n_components;
+
+ stream->peer_gathering_done = !agent->use_ice_trickle;
+
+ return stream;
+}
+
+void
+nice_stream_close (NiceAgent *agent, NiceStream *stream)
+{
+ GSList *i;
+
+ for (i = stream->components; i; i = i->next) {
+ NiceComponent *component = i->data;
+ nice_component_close (agent, component);
+ }
+}
+
+NiceComponent *
+nice_stream_find_component_by_id (NiceStream *stream, guint id)
+{
+ GSList *i;
+
+ for (i = stream->components; i; i = i->next) {
+ NiceComponent *component = i->data;
+ if (component && component->id == id)
+ return component;
+ }
+
+ return NULL;
+}
+
+/*
+ * Initialized the local crendentials for the stream.
+ */
+void
+nice_stream_initialize_credentials (NiceStream *stream, NiceRNG *rng)
+{
+ /* note: generate ufrag/pwd for the stream (see ICE 15.4.
+ * '"ice-ufrag" and "ice-pwd" Attributes', ID-19) */
+ nice_rng_generate_bytes_print (rng, NICE_STREAM_DEF_UFRAG - 1, stream->local_ufrag);
+ nice_rng_generate_bytes_print (rng, NICE_STREAM_DEF_PWD - 1, stream->local_password);
+}
+
+/*
+ * Resets the stream state to that of a ICE restarted
+ * session.
+ */
+void
+nice_stream_restart (NiceStream *stream, NiceAgent *agent)
+{
+ GSList *i;
+
+ /* step: clean up all connectivity checks */
+ conn_check_prune_stream (agent, stream);
+
+ stream->initial_binding_request_received = FALSE;
+
+ nice_stream_initialize_credentials (stream, agent->rng);
+
+ for (i = stream->components; i; i = i->next) {
+ NiceComponent *component = i->data;
+
+ nice_component_restart (component);
+ }
+}
+
+static void
+nice_stream_class_init (NiceStreamClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = nice_stream_finalize;
+}
+
+static void
+nice_stream_init (NiceStream *stream)
+{
+ g_atomic_int_inc (&n_streams_created);
+ nice_debug ("Created NiceStream (%u created, %u destroyed)",
+ n_streams_created, n_streams_destroyed);
+
+ stream->n_components = 0;
+ stream->initial_binding_request_received = FALSE;
+}
+
+/* Must be called with the agent lock released as it could dispose of
+ * NiceIOStreams. */
+static void
+nice_stream_finalize (GObject *obj)
+{
+ NiceStream *stream;
+
+ stream = NICE_STREAM (obj);
+
+ g_free (stream->name);
+ g_slist_free_full (stream->components, (GDestroyNotify) g_object_unref);
+
+ g_atomic_int_inc (&n_streams_destroyed);
+ nice_debug ("Destroyed NiceStream (%u created, %u destroyed)",
+ n_streams_created, n_streams_destroyed);
+
+ G_OBJECT_CLASS (nice_stream_parent_class)->finalize (obj);
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2006-2010 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2006-2010 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Dafydd Harries, Collabora Ltd.
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef _NICE_STREAM_H
+#define _NICE_STREAM_H
+
+#include <glib.h>
+
+typedef struct _NiceStream NiceStream;
+
+#include "component.h"
+#include "random.h"
+
+G_BEGIN_DECLS
+
+/* Maximum and default sizes for ICE attributes,
+ * last updated from ICE ID-19
+ * (the below sizes include the terminating NULL): */
+
+#define NICE_STREAM_MAX_UFRAG 256 + 1 /* ufrag + NULL */
+#define NICE_STREAM_MAX_UNAME 256 * 2 + 1 + 1 /* 2*ufrag + colon + NULL */
+#define NICE_STREAM_MAX_PWD 256 + 1 /* pwd + NULL */
+#define NICE_STREAM_DEF_UFRAG 4 + 1 /* ufrag + NULL */
+#define NICE_STREAM_DEF_PWD 22 + 1 /* pwd + NULL */
+
+#define NICE_TYPE_STREAM nice_stream_get_type()
+#define NICE_STREAM(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), NICE_TYPE_STREAM, NiceStream))
+#define NICE_STREAM_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), NICE_TYPE_STREAM, NiceStreamClass))
+#define NICE_IS_STREAM(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NICE_TYPE_STREAM))
+#define NICE_IS_STREAM_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), NICE_TYPE_STREAM))
+#define NICE_STREAM_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), NICE_TYPE_STREAM, NiceStreamClass))
+
+struct _NiceStream {
+ /*< private >*/
+ GObject parent;
+
+ gchar *name;
+ guint id;
+ guint n_components;
+ gboolean initial_binding_request_received;
+ GSList *components; /* list of 'NiceComponent' objects */
+ GSList *conncheck_list; /* list of CandidateCheckPair items */
+ gchar local_ufrag[NICE_STREAM_MAX_UFRAG];
+ gchar local_password[NICE_STREAM_MAX_PWD];
+ gchar remote_ufrag[NICE_STREAM_MAX_UFRAG];
+ gchar remote_password[NICE_STREAM_MAX_PWD];
+ gboolean gathering;
+ gboolean gathering_started;
+ gboolean peer_gathering_done;
+ gint tos;
+ guint tick_counter;
+};
+
+typedef struct {
+ GObjectClass parent_class;
+} NiceStreamClass;
+
+GType nice_stream_get_type (void);
+
+NiceStream *
+nice_stream_new (guint stream_id, guint n_components, NiceAgent *agent);
+
+void
+nice_stream_close (NiceAgent *agent, NiceStream *stream);
+
+NiceComponent *
+nice_stream_find_component_by_id (NiceStream *stream, guint id);
+
+void
+nice_stream_initialize_credentials (NiceStream *stream, NiceRNG *rng);
+
+void
+nice_stream_restart (NiceStream *stream, NiceAgent *agent);
+
+G_END_DECLS
+
+#endif /* _NICE_STREAM_H */
+
--- /dev/null
+#! /bin/sh
+# Wrapper for Microsoft lib.exe
+
+me=ar-lib
+scriptversion=2012-03-01.08; # UTC
+
+# Copyright (C) 2010-2018 Free Software Foundation, Inc.
+# Written by Peter Rosin <peda@lysator.liu.se>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+
+# func_error message
+func_error ()
+{
+ echo "$me: $1" 1>&2
+ exit 1
+}
+
+file_conv=
+
+# func_file_conv build_file
+# Convert a $build file to $host form and store it in $file
+# Currently only supports Windows hosts.
+func_file_conv ()
+{
+ file=$1
+ case $file in
+ / | /[!/]*) # absolute file, and not a UNC file
+ if test -z "$file_conv"; then
+ # lazily determine how to convert abs files
+ case `uname -s` in
+ MINGW*)
+ file_conv=mingw
+ ;;
+ CYGWIN*)
+ file_conv=cygwin
+ ;;
+ *)
+ file_conv=wine
+ ;;
+ esac
+ fi
+ case $file_conv in
+ mingw)
+ file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
+ ;;
+ cygwin)
+ file=`cygpath -m "$file" || echo "$file"`
+ ;;
+ wine)
+ file=`winepath -w "$file" || echo "$file"`
+ ;;
+ esac
+ ;;
+ esac
+}
+
+# func_at_file at_file operation archive
+# Iterate over all members in AT_FILE performing OPERATION on ARCHIVE
+# for each of them.
+# When interpreting the content of the @FILE, do NOT use func_file_conv,
+# since the user would need to supply preconverted file names to
+# binutils ar, at least for MinGW.
+func_at_file ()
+{
+ operation=$2
+ archive=$3
+ at_file_contents=`cat "$1"`
+ eval set x "$at_file_contents"
+ shift
+
+ for member
+ do
+ $AR -NOLOGO $operation:"$member" "$archive" || exit $?
+ done
+}
+
+case $1 in
+ '')
+ func_error "no command. Try '$0 --help' for more information."
+ ;;
+ -h | --h*)
+ cat <<EOF
+Usage: $me [--help] [--version] PROGRAM ACTION ARCHIVE [MEMBER...]
+
+Members may be specified in a file named with @FILE.
+EOF
+ exit $?
+ ;;
+ -v | --v*)
+ echo "$me, version $scriptversion"
+ exit $?
+ ;;
+esac
+
+if test $# -lt 3; then
+ func_error "you must specify a program, an action and an archive"
+fi
+
+AR=$1
+shift
+while :
+do
+ if test $# -lt 2; then
+ func_error "you must specify a program, an action and an archive"
+ fi
+ case $1 in
+ -lib | -LIB \
+ | -ltcg | -LTCG \
+ | -machine* | -MACHINE* \
+ | -subsystem* | -SUBSYSTEM* \
+ | -verbose | -VERBOSE \
+ | -wx* | -WX* )
+ AR="$AR $1"
+ shift
+ ;;
+ *)
+ action=$1
+ shift
+ break
+ ;;
+ esac
+done
+orig_archive=$1
+shift
+func_file_conv "$orig_archive"
+archive=$file
+
+# strip leading dash in $action
+action=${action#-}
+
+delete=
+extract=
+list=
+quick=
+replace=
+index=
+create=
+
+while test -n "$action"
+do
+ case $action in
+ d*) delete=yes ;;
+ x*) extract=yes ;;
+ t*) list=yes ;;
+ q*) quick=yes ;;
+ r*) replace=yes ;;
+ s*) index=yes ;;
+ S*) ;; # the index is always updated implicitly
+ c*) create=yes ;;
+ u*) ;; # TODO: don't ignore the update modifier
+ v*) ;; # TODO: don't ignore the verbose modifier
+ *)
+ func_error "unknown action specified"
+ ;;
+ esac
+ action=${action#?}
+done
+
+case $delete$extract$list$quick$replace,$index in
+ yes,* | ,yes)
+ ;;
+ yesyes*)
+ func_error "more than one action specified"
+ ;;
+ *)
+ func_error "no action specified"
+ ;;
+esac
+
+if test -n "$delete"; then
+ if test ! -f "$orig_archive"; then
+ func_error "archive not found"
+ fi
+ for member
+ do
+ case $1 in
+ @*)
+ func_at_file "${1#@}" -REMOVE "$archive"
+ ;;
+ *)
+ func_file_conv "$1"
+ $AR -NOLOGO -REMOVE:"$file" "$archive" || exit $?
+ ;;
+ esac
+ done
+
+elif test -n "$extract"; then
+ if test ! -f "$orig_archive"; then
+ func_error "archive not found"
+ fi
+ if test $# -gt 0; then
+ for member
+ do
+ case $1 in
+ @*)
+ func_at_file "${1#@}" -EXTRACT "$archive"
+ ;;
+ *)
+ func_file_conv "$1"
+ $AR -NOLOGO -EXTRACT:"$file" "$archive" || exit $?
+ ;;
+ esac
+ done
+ else
+ $AR -NOLOGO -LIST "$archive" | sed -e 's/\\/\\\\/g' | while read member
+ do
+ $AR -NOLOGO -EXTRACT:"$member" "$archive" || exit $?
+ done
+ fi
+
+elif test -n "$quick$replace"; then
+ if test ! -f "$orig_archive"; then
+ if test -z "$create"; then
+ echo "$me: creating $orig_archive"
+ fi
+ orig_archive=
+ else
+ orig_archive=$archive
+ fi
+
+ for member
+ do
+ case $1 in
+ @*)
+ func_file_conv "${1#@}"
+ set x "$@" "@$file"
+ ;;
+ *)
+ func_file_conv "$1"
+ set x "$@" "$file"
+ ;;
+ esac
+ shift
+ shift
+ done
+
+ if test -n "$orig_archive"; then
+ $AR -NOLOGO -OUT:"$archive" "$orig_archive" "$@" || exit $?
+ else
+ $AR -NOLOGO -OUT:"$archive" "$@" || exit $?
+ fi
+
+elif test -n "$list"; then
+ if test ! -f "$orig_archive"; then
+ func_error "archive not found"
+ fi
+ $AR -NOLOGO -LIST "$archive" || exit $?
+fi
--- /dev/null
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+test -n "$srcdir" || srcdir=$(dirname "$0")
+test -n "$srcdir" || srcdir=.
+
+olddir=$(pwd)
+
+cd $srcdir
+
+(test -f configure.ac) || {
+ echo "*** ERROR: Directory '$srcdir' does not look like the top-level project directory ***"
+ exit 1
+}
+
+# shellcheck disable=SC2016
+PKG_NAME=$(autoconf --trace 'AC_INIT:$1' configure.ac)
+
+if [ "$#" = 0 -a "x$NOCONFIGURE" = "x" ]; then
+ echo "*** WARNING: I am going to run 'configure' with no arguments." >&2
+ echo "*** If you wish to pass any to it, please specify them on the" >&2
+ echo "*** '$0' command line." >&2
+ echo "" >&2
+fi
+
+aclocal --install || exit 1
+gtkdocize --copy || exit 1
+autoreconf --verbose --force --install || exit 1
+
+cd "$olddir"
+if [ "$NOCONFIGURE" = "" ]; then
+ $srcdir/configure "$@" || exit 1
+
+ if [ "$1" = "--help" ]; then exit 0 else
+ echo "Now type 'make' to compile $PKG_NAME" || exit 1
+ fi
+else
+ echo "Skipping configure process."
+fi
--- /dev/null
+CLEANFILES = *.gcno *.gcda
+
+pkgincludedir = $(includedir)/nice
+
+
+check-valgrind:
+ $(MAKE) TESTS_ENVIRONMENT="USE_VALGRIND=1 " check
+
+LOG_DRIVER=$(top_srcdir)/scripts/valgrind-test-driver
+
+.PHONY: check-valgrind
--- /dev/null
+#! /bin/sh
+# Wrapper for compilers which do not understand '-c -o'.
+
+scriptversion=2018-03-07.03; # UTC
+
+# Copyright (C) 1999-2018 Free Software Foundation, Inc.
+# Written by Tom Tromey <tromey@cygnus.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+nl='
+'
+
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent tools from complaining about whitespace usage.
+IFS=" "" $nl"
+
+file_conv=
+
+# func_file_conv build_file lazy
+# Convert a $build file to $host form and store it in $file
+# Currently only supports Windows hosts. If the determined conversion
+# type is listed in (the comma separated) LAZY, no conversion will
+# take place.
+func_file_conv ()
+{
+ file=$1
+ case $file in
+ / | /[!/]*) # absolute file, and not a UNC file
+ if test -z "$file_conv"; then
+ # lazily determine how to convert abs files
+ case `uname -s` in
+ MINGW*)
+ file_conv=mingw
+ ;;
+ CYGWIN*)
+ file_conv=cygwin
+ ;;
+ *)
+ file_conv=wine
+ ;;
+ esac
+ fi
+ case $file_conv/,$2, in
+ *,$file_conv,*)
+ ;;
+ mingw/*)
+ file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
+ ;;
+ cygwin/*)
+ file=`cygpath -m "$file" || echo "$file"`
+ ;;
+ wine/*)
+ file=`winepath -w "$file" || echo "$file"`
+ ;;
+ esac
+ ;;
+ esac
+}
+
+# func_cl_dashL linkdir
+# Make cl look for libraries in LINKDIR
+func_cl_dashL ()
+{
+ func_file_conv "$1"
+ if test -z "$lib_path"; then
+ lib_path=$file
+ else
+ lib_path="$lib_path;$file"
+ fi
+ linker_opts="$linker_opts -LIBPATH:$file"
+}
+
+# func_cl_dashl library
+# Do a library search-path lookup for cl
+func_cl_dashl ()
+{
+ lib=$1
+ found=no
+ save_IFS=$IFS
+ IFS=';'
+ for dir in $lib_path $LIB
+ do
+ IFS=$save_IFS
+ if $shared && test -f "$dir/$lib.dll.lib"; then
+ found=yes
+ lib=$dir/$lib.dll.lib
+ break
+ fi
+ if test -f "$dir/$lib.lib"; then
+ found=yes
+ lib=$dir/$lib.lib
+ break
+ fi
+ if test -f "$dir/lib$lib.a"; then
+ found=yes
+ lib=$dir/lib$lib.a
+ break
+ fi
+ done
+ IFS=$save_IFS
+
+ if test "$found" != yes; then
+ lib=$lib.lib
+ fi
+}
+
+# func_cl_wrapper cl arg...
+# Adjust compile command to suit cl
+func_cl_wrapper ()
+{
+ # Assume a capable shell
+ lib_path=
+ shared=:
+ linker_opts=
+ for arg
+ do
+ if test -n "$eat"; then
+ eat=
+ else
+ case $1 in
+ -o)
+ # configure might choose to run compile as 'compile cc -o foo foo.c'.
+ eat=1
+ case $2 in
+ *.o | *.[oO][bB][jJ])
+ func_file_conv "$2"
+ set x "$@" -Fo"$file"
+ shift
+ ;;
+ *)
+ func_file_conv "$2"
+ set x "$@" -Fe"$file"
+ shift
+ ;;
+ esac
+ ;;
+ -I)
+ eat=1
+ func_file_conv "$2" mingw
+ set x "$@" -I"$file"
+ shift
+ ;;
+ -I*)
+ func_file_conv "${1#-I}" mingw
+ set x "$@" -I"$file"
+ shift
+ ;;
+ -l)
+ eat=1
+ func_cl_dashl "$2"
+ set x "$@" "$lib"
+ shift
+ ;;
+ -l*)
+ func_cl_dashl "${1#-l}"
+ set x "$@" "$lib"
+ shift
+ ;;
+ -L)
+ eat=1
+ func_cl_dashL "$2"
+ ;;
+ -L*)
+ func_cl_dashL "${1#-L}"
+ ;;
+ -static)
+ shared=false
+ ;;
+ -Wl,*)
+ arg=${1#-Wl,}
+ save_ifs="$IFS"; IFS=','
+ for flag in $arg; do
+ IFS="$save_ifs"
+ linker_opts="$linker_opts $flag"
+ done
+ IFS="$save_ifs"
+ ;;
+ -Xlinker)
+ eat=1
+ linker_opts="$linker_opts $2"
+ ;;
+ -*)
+ set x "$@" "$1"
+ shift
+ ;;
+ *.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
+ func_file_conv "$1"
+ set x "$@" -Tp"$file"
+ shift
+ ;;
+ *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
+ func_file_conv "$1" mingw
+ set x "$@" "$file"
+ shift
+ ;;
+ *)
+ set x "$@" "$1"
+ shift
+ ;;
+ esac
+ fi
+ shift
+ done
+ if test -n "$linker_opts"; then
+ linker_opts="-link$linker_opts"
+ fi
+ exec "$@" $linker_opts
+ exit 1
+}
+
+eat=
+
+case $1 in
+ '')
+ echo "$0: No command. Try '$0 --help' for more information." 1>&2
+ exit 1;
+ ;;
+ -h | --h*)
+ cat <<\EOF
+Usage: compile [--help] [--version] PROGRAM [ARGS]
+
+Wrapper for compilers which do not understand '-c -o'.
+Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
+arguments, and rename the output as expected.
+
+If you are trying to build a whole package this is not the
+right script to run: please start by reading the file 'INSTALL'.
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+ exit $?
+ ;;
+ -v | --v*)
+ echo "compile $scriptversion"
+ exit $?
+ ;;
+ cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \
+ icl | *[/\\]icl | icl.exe | *[/\\]icl.exe )
+ func_cl_wrapper "$@" # Doesn't return...
+ ;;
+esac
+
+ofile=
+cfile=
+
+for arg
+do
+ if test -n "$eat"; then
+ eat=
+ else
+ case $1 in
+ -o)
+ # configure might choose to run compile as 'compile cc -o foo foo.c'.
+ # So we strip '-o arg' only if arg is an object.
+ eat=1
+ case $2 in
+ *.o | *.obj)
+ ofile=$2
+ ;;
+ *)
+ set x "$@" -o "$2"
+ shift
+ ;;
+ esac
+ ;;
+ *.c)
+ cfile=$1
+ set x "$@" "$1"
+ shift
+ ;;
+ *)
+ set x "$@" "$1"
+ shift
+ ;;
+ esac
+ fi
+ shift
+done
+
+if test -z "$ofile" || test -z "$cfile"; then
+ # If no '-o' option was seen then we might have been invoked from a
+ # pattern rule where we don't need one. That is ok -- this is a
+ # normal compilation that the losing compiler can handle. If no
+ # '.c' file was seen then we are probably linking. That is also
+ # ok.
+ exec "$@"
+fi
+
+# Name of file we expect compiler to create.
+cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
+
+# Create the lock directory.
+# Note: use '[/\\:.-]' here to ensure that we don't use the same name
+# that we are using for the .o file. Also, base the name on the expected
+# object file name, since that is what matters with a parallel build.
+lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
+while true; do
+ if mkdir "$lockdir" >/dev/null 2>&1; then
+ break
+ fi
+ sleep 1
+done
+# FIXME: race condition here if user kills between mkdir and trap.
+trap "rmdir '$lockdir'; exit 1" 1 2 15
+
+# Run the compile.
+"$@"
+ret=$?
+
+if test -f "$cofile"; then
+ test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
+elif test -f "${cofile}bj"; then
+ test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
+fi
+
+rmdir "$lockdir"
+exit $ret
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC0"
+# time-stamp-end: "; # UTC"
+# End:
--- /dev/null
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright 1992-2018 Free Software Foundation, Inc.
+
+timestamp='2018-03-08'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that
+# program. This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+#
+# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
+#
+# You can get the latest version of this script from:
+# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
+#
+# Please send patches to <config-patches@gnu.org>.
+
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Options:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright 1992-2018 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int x;" > "$dummy.c" ;
+ for c in cc gcc c89 c99 ; do
+ if ($c -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+case "$UNAME_SYSTEM" in
+Linux|GNU|GNU/*)
+ # If the system lacks a compiler, then just pick glibc.
+ # We could probably try harder.
+ LIBC=gnu
+
+ eval "$set_cc_for_build"
+ cat <<-EOF > "$dummy.c"
+ #include <features.h>
+ #if defined(__UCLIBC__)
+ LIBC=uclibc
+ #elif defined(__dietlibc__)
+ LIBC=dietlibc
+ #else
+ LIBC=gnu
+ #endif
+ EOF
+ eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`"
+
+ # If ldd exists, use it to detect musl libc.
+ if command -v ldd >/dev/null && \
+ ldd --version 2>&1 | grep -q ^musl
+ then
+ LIBC=musl
+ fi
+ ;;
+esac
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ sysctl="sysctl -n hw.machine_arch"
+ UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
+ "/sbin/$sysctl" 2>/dev/null || \
+ "/usr/sbin/$sysctl" 2>/dev/null || \
+ echo unknown)`
+ case "$UNAME_MACHINE_ARCH" in
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ sh5el) machine=sh5le-unknown ;;
+ earmv*)
+ arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
+ endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'`
+ machine="${arch}${endian}"-unknown
+ ;;
+ *) machine="$UNAME_MACHINE_ARCH"-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently (or will in the future) and ABI.
+ case "$UNAME_MACHINE_ARCH" in
+ earm*)
+ os=netbsdelf
+ ;;
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval "$set_cc_for_build"
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ELF__
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # Determine ABI tags.
+ case "$UNAME_MACHINE_ARCH" in
+ earm*)
+ expr='s/^earmv[0-9]/-eabi/;s/eb$//'
+ abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"`
+ ;;
+ esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case "$UNAME_VERSION" in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2`
+ ;;
+ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "$machine-${os}${release}${abi}"
+ exit ;;
+ *:Bitrig:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
+ echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE"
+ exit ;;
+ *:OpenBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+ echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE"
+ exit ;;
+ *:LibertyBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
+ echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE"
+ exit ;;
+ *:MidnightBSD:*:*)
+ echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE"
+ exit ;;
+ *:ekkoBSD:*:*)
+ echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE"
+ exit ;;
+ *:SolidBSD:*:*)
+ echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE"
+ exit ;;
+ macppc:MirBSD:*:*)
+ echo powerpc-unknown-mirbsd"$UNAME_RELEASE"
+ exit ;;
+ *:MirBSD:*:*)
+ echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE"
+ exit ;;
+ *:Sortix:*:*)
+ echo "$UNAME_MACHINE"-unknown-sortix
+ exit ;;
+ *:Redox:*:*)
+ echo "$UNAME_MACHINE"-unknown-redox
+ exit ;;
+ mips:OSF1:*.*)
+ echo mips-dec-osf1
+ exit ;;
+ alpha:OSF1:*:*)
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case "$ALPHA_CPU_TYPE" in
+ "EV4 (21064)")
+ UNAME_MACHINE=alpha ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE=alpha ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE=alpha ;;
+ "EV5 (21164)")
+ UNAME_MACHINE=alphaev5 ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE=alphaev56 ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE=alphapca56 ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE=alphapca57 ;;
+ "EV6 (21264)")
+ UNAME_MACHINE=alphaev6 ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE=alphaev67 ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE=alphaev68 ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE=alphaev68 ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE=alphaev68 ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE=alphaev69 ;;
+ "EV7 (21364)")
+ UNAME_MACHINE=alphaev7 ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE=alphaev79 ;;
+ esac
+ # A Pn.n version is a patched version.
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`"
+ # Reset EXIT trap before exiting to avoid spurious non-zero exit code.
+ exitcode=$?
+ trap '' 0
+ exit $exitcode ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo "$UNAME_MACHINE"-unknown-amigaos
+ exit ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo "$UNAME_MACHINE"-unknown-morphos
+ exit ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit ;;
+ *:z/VM:*:*)
+ echo s390-ibm-zvmoe
+ exit ;;
+ *:OS400:*:*)
+ echo powerpc-ibm-os400
+ exit ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix"$UNAME_RELEASE"
+ exit ;;
+ arm*:riscos:*:*|arm*:RISCOS:*:*)
+ echo arm-unknown-riscos
+ exit ;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit ;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit ;;
+ DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7; exit ;;
+ esac ;;
+ s390x:SunOS:*:*)
+ echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`"
+ exit ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
+ exit ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`"
+ exit ;;
+ i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
+ echo i386-pc-auroraux"$UNAME_RELEASE"
+ exit ;;
+ i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+ eval "$set_cc_for_build"
+ SUN_ARCH=i386
+ # If there is a compiler, see if it is configured for 64-bit objects.
+ # Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
+ # This test works for both compilers.
+ if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
+ if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ SUN_ARCH=x86_64
+ fi
+ fi
+ echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
+ exit ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
+ exit ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`"
+ exit ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos"$UNAME_RELEASE"
+ exit ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos"$UNAME_RELEASE"
+ ;;
+ sun4)
+ echo sparc-sun-sunos"$UNAME_RELEASE"
+ ;;
+ esac
+ exit ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos"$UNAME_RELEASE"
+ exit ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint"$UNAME_RELEASE"
+ exit ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint"$UNAME_RELEASE"
+ exit ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint"$UNAME_RELEASE"
+ exit ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint"$UNAME_RELEASE"
+ exit ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint"$UNAME_RELEASE"
+ exit ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint"$UNAME_RELEASE"
+ exit ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten"$UNAME_RELEASE"
+ exit ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten"$UNAME_RELEASE"
+ exit ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix"$UNAME_RELEASE"
+ exit ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix"$UNAME_RELEASE"
+ exit ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix"$UNAME_RELEASE"
+ exit ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval "$set_cc_for_build"
+ sed 's/^ //' << EOF > "$dummy.c"
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o "$dummy" "$dummy.c" &&
+ dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+ SYSTEM_NAME=`"$dummy" "$dummyarg"` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo mips-mips-riscos"$UNAME_RELEASE"
+ exit ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ]
+ then
+ if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \
+ [ "$TARGET_BINARY_INTERFACE"x = x ]
+ then
+ echo m88k-dg-dgux"$UNAME_RELEASE"
+ else
+ echo m88k-dg-dguxbcs"$UNAME_RELEASE"
+ fi
+ else
+ echo i586-dg-dgux"$UNAME_RELEASE"
+ fi
+ exit ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`"
+ exit ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
+ fi
+ echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV"
+ exit ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval "$set_cc_for_build"
+ sed 's/^ //' << EOF > "$dummy.c"
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"`
+ then
+ echo "$SYSTEM_NAME"
+ else
+ echo rs6000-ibm-aix3.2.5
+ fi
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit ;;
+ *:AIX:*:[4567])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/lslpp ] ; then
+ IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
+ awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
+ else
+ IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
+ fi
+ echo "$IBM_ARCH"-ibm-aix"$IBM_REV"
+ exit ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit ;;
+ ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*)
+ echo romp-ibm-bsd4.4
+ exit ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to
+ exit ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'`
+ case "$UNAME_MACHINE" in
+ 9000/31?) HP_ARCH=m68000 ;;
+ 9000/[34]??) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "$sc_cpu_version" in
+ 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "$sc_kernel_bits" in
+ 32) HP_ARCH=hppa2.0n ;;
+ 64) HP_ARCH=hppa2.0w ;;
+ '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "$HP_ARCH" = "" ]; then
+ eval "$set_cc_for_build"
+ sed 's/^ //' << EOF > "$dummy.c"
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if [ "$HP_ARCH" = hppa2.0w ]
+ then
+ eval "$set_cc_for_build"
+
+ # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+ # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
+ # generating 64-bit code. GNU and HP use different nomenclature:
+ #
+ # $ CC_FOR_BUILD=cc ./config.guess
+ # => hppa2.0w-hp-hpux11.23
+ # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+ # => hppa64-hp-hpux11.23
+
+ if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) |
+ grep -q __LP64__
+ then
+ HP_ARCH=hppa2.0w
+ else
+ HP_ARCH=hppa64
+ fi
+ fi
+ echo "$HP_ARCH"-hp-hpux"$HPUX_REV"
+ exit ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux"$HPUX_REV"
+ exit ;;
+ 3050*:HI-UX:*:*)
+ eval "$set_cc_for_build"
+ sed 's/^ //' << EOF > "$dummy.c"
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo unknown-hitachi-hiuxwe2
+ exit ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*)
+ echo hppa1.1-hp-bsd
+ exit ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*)
+ echo hppa1.1-hp-osf
+ exit ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo "$UNAME_MACHINE"-unknown-osf1mk
+ else
+ echo "$UNAME_MACHINE"-unknown-osf1
+ fi
+ exit ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ *:UNICOS/mp:*:*)
+ echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+ FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+ FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+ FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE"
+ exit ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi"$UNAME_RELEASE"
+ exit ;;
+ *:BSD/OS:*:*)
+ echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE"
+ exit ;;
+ *:FreeBSD:*:*)
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ case "$UNAME_PROCESSOR" in
+ amd64)
+ UNAME_PROCESSOR=x86_64 ;;
+ i386)
+ UNAME_PROCESSOR=i586 ;;
+ esac
+ echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`"
+ exit ;;
+ i*:CYGWIN*:*)
+ echo "$UNAME_MACHINE"-pc-cygwin
+ exit ;;
+ *:MINGW64*:*)
+ echo "$UNAME_MACHINE"-pc-mingw64
+ exit ;;
+ *:MINGW*:*)
+ echo "$UNAME_MACHINE"-pc-mingw32
+ exit ;;
+ *:MSYS*:*)
+ echo "$UNAME_MACHINE"-pc-msys
+ exit ;;
+ i*:PW*:*)
+ echo "$UNAME_MACHINE"-pc-pw32
+ exit ;;
+ *:Interix*:*)
+ case "$UNAME_MACHINE" in
+ x86)
+ echo i586-pc-interix"$UNAME_RELEASE"
+ exit ;;
+ authenticamd | genuineintel | EM64T)
+ echo x86_64-unknown-interix"$UNAME_RELEASE"
+ exit ;;
+ IA64)
+ echo ia64-unknown-interix"$UNAME_RELEASE"
+ exit ;;
+ esac ;;
+ i*:UWIN*:*)
+ echo "$UNAME_MACHINE"-pc-uwin
+ exit ;;
+ amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+ echo x86_64-unknown-cygwin
+ exit ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
+ exit ;;
+ *:GNU:*:*)
+ # the GNU system
+ echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`"
+ exit ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC"
+ exit ;;
+ i*86:Minix:*:*)
+ echo "$UNAME_MACHINE"-pc-minix
+ exit ;;
+ aarch64:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ aarch64_be:Linux:*:*)
+ UNAME_MACHINE=aarch64_be
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep -q ld.so.1
+ if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ arc:Linux:*:* | arceb:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ arm*:Linux:*:*)
+ eval "$set_cc_for_build"
+ if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_EABI__
+ then
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ else
+ if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_PCS_VFP
+ then
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi
+ else
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf
+ fi
+ fi
+ exit ;;
+ avr32*:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ cris:Linux:*:*)
+ echo "$UNAME_MACHINE"-axis-linux-"$LIBC"
+ exit ;;
+ crisv32:Linux:*:*)
+ echo "$UNAME_MACHINE"-axis-linux-"$LIBC"
+ exit ;;
+ e2k:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ frv:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ hexagon:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ i*86:Linux:*:*)
+ echo "$UNAME_MACHINE"-pc-linux-"$LIBC"
+ exit ;;
+ ia64:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ k1om:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ m32r*:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ m68*:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ mips:Linux:*:* | mips64:Linux:*:*)
+ eval "$set_cc_for_build"
+ sed 's/^ //' << EOF > "$dummy.c"
+ #undef CPU
+ #undef ${UNAME_MACHINE}
+ #undef ${UNAME_MACHINE}el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=${UNAME_MACHINE}el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=${UNAME_MACHINE}
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU'`"
+ test "x$CPU" != x && { echo "$CPU-unknown-linux-$LIBC"; exit; }
+ ;;
+ mips64el:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ openrisc*:Linux:*:*)
+ echo or1k-unknown-linux-"$LIBC"
+ exit ;;
+ or32:Linux:*:* | or1k*:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ padre:Linux:*:*)
+ echo sparc-unknown-linux-"$LIBC"
+ exit ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-"$LIBC"
+ exit ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;;
+ PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;;
+ *) echo hppa-unknown-linux-"$LIBC" ;;
+ esac
+ exit ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-"$LIBC"
+ exit ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-"$LIBC"
+ exit ;;
+ ppc64le:Linux:*:*)
+ echo powerpc64le-unknown-linux-"$LIBC"
+ exit ;;
+ ppcle:Linux:*:*)
+ echo powerpcle-unknown-linux-"$LIBC"
+ exit ;;
+ riscv32:Linux:*:* | riscv64:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo "$UNAME_MACHINE"-ibm-linux-"$LIBC"
+ exit ;;
+ sh64*:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ sh*:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ tile*:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ vax:Linux:*:*)
+ echo "$UNAME_MACHINE"-dec-linux-"$LIBC"
+ exit ;;
+ x86_64:Linux:*:*)
+ echo "$UNAME_MACHINE"-pc-linux-"$LIBC"
+ exit ;;
+ xtensa*:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION"
+ exit ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo "$UNAME_MACHINE"-pc-os2-emx
+ exit ;;
+ i*86:XTS-300:*:STOP)
+ echo "$UNAME_MACHINE"-unknown-stop
+ exit ;;
+ i*86:atheos:*:*)
+ echo "$UNAME_MACHINE"-unknown-atheos
+ exit ;;
+ i*86:syllable:*:*)
+ echo "$UNAME_MACHINE"-pc-syllable
+ exit ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
+ echo i386-unknown-lynxos"$UNAME_RELEASE"
+ exit ;;
+ i*86:*DOS:*:*)
+ echo "$UNAME_MACHINE"-pc-msdosdjgpp
+ exit ;;
+ i*86:*:4.*:*)
+ UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL"
+ else
+ echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL"
+ fi
+ exit ;;
+ i*86:*:5:[678]*)
+ # UnixWare 7.x, OpenUNIX and OpenServer 6.
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}{$UNAME_VERSION}"
+ exit ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo "$UNAME_MACHINE"-pc-isc"$UNAME_REL"
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL"
+ else
+ echo "$UNAME_MACHINE"-pc-sysv32
+ fi
+ exit ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i586.
+ # Note: whatever this is, it MUST be the same as what config.sub
+ # prints for the "djgpp" host, or else GDB configure will decide that
+ # this is a cross-build.
+ echo i586-pc-msdosdjgpp
+ exit ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4
+ fi
+ exit ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4; exit; } ;;
+ NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+ OS_REL='.3'
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
+ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos"$UNAME_RELEASE"
+ exit ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos"$UNAME_RELEASE"
+ exit ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos"$UNAME_RELEASE"
+ exit ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
+ echo powerpc-unknown-lynxos"$UNAME_RELEASE"
+ exit ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv"$UNAME_RELEASE"
+ exit ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo "$UNAME_MACHINE"-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit ;;
+ i*86:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo "$UNAME_MACHINE"-stratus-vos
+ exit ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo hppa1.1-stratus-vos
+ exit ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux"$UNAME_RELEASE"
+ exit ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv"$UNAME_RELEASE"
+ else
+ echo mips-unknown-sysv"$UNAME_RELEASE"
+ fi
+ exit ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit ;;
+ BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
+ echo i586-pc-haiku
+ exit ;;
+ x86_64:Haiku:*:*)
+ echo x86_64-unknown-haiku
+ exit ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux"$UNAME_RELEASE"
+ exit ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux"$UNAME_RELEASE"
+ exit ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux"$UNAME_RELEASE"
+ exit ;;
+ SX-7:SUPER-UX:*:*)
+ echo sx7-nec-superux"$UNAME_RELEASE"
+ exit ;;
+ SX-8:SUPER-UX:*:*)
+ echo sx8-nec-superux"$UNAME_RELEASE"
+ exit ;;
+ SX-8R:SUPER-UX:*:*)
+ echo sx8r-nec-superux"$UNAME_RELEASE"
+ exit ;;
+ SX-ACE:SUPER-UX:*:*)
+ echo sxace-nec-superux"$UNAME_RELEASE"
+ exit ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody"$UNAME_RELEASE"
+ exit ;;
+ *:Rhapsody:*:*)
+ echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE"
+ exit ;;
+ *:Darwin:*:*)
+ UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+ eval "$set_cc_for_build"
+ if test "$UNAME_PROCESSOR" = unknown ; then
+ UNAME_PROCESSOR=powerpc
+ fi
+ if test "`echo "$UNAME_RELEASE" | sed -e 's/\..*//'`" -le 10 ; then
+ if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
+ if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ case $UNAME_PROCESSOR in
+ i386) UNAME_PROCESSOR=x86_64 ;;
+ powerpc) UNAME_PROCESSOR=powerpc64 ;;
+ esac
+ fi
+ # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc
+ if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_PPC >/dev/null
+ then
+ UNAME_PROCESSOR=powerpc
+ fi
+ fi
+ elif test "$UNAME_PROCESSOR" = i386 ; then
+ # Avoid executing cc on OS X 10.9, as it ships with a stub
+ # that puts up a graphical alert prompting to install
+ # developer tools. Any system running Mac OS X 10.7 or
+ # later (Darwin 11 and later) is required to have a 64-bit
+ # processor. This is not true of the ARM version of Darwin
+ # that Apple uses in portable devices.
+ UNAME_PROCESSOR=x86_64
+ fi
+ echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE"
+ exit ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = x86; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE"
+ exit ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit ;;
+ NEO-*:NONSTOP_KERNEL:*:*)
+ echo neo-tandem-nsk"$UNAME_RELEASE"
+ exit ;;
+ NSE-*:NONSTOP_KERNEL:*:*)
+ echo nse-tandem-nsk"$UNAME_RELEASE"
+ exit ;;
+ NSR-*:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk"$UNAME_RELEASE"
+ exit ;;
+ NSV-*:NONSTOP_KERNEL:*:*)
+ echo nsv-tandem-nsk"$UNAME_RELEASE"
+ exit ;;
+ NSX-*:NONSTOP_KERNEL:*:*)
+ echo nsx-tandem-nsk"$UNAME_RELEASE"
+ exit ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit ;;
+ DS/*:UNIX_System_V:*:*)
+ echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE"
+ exit ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = 386; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo "$UNAME_MACHINE"-unknown-plan9
+ exit ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux"$UNAME_RELEASE"
+ exit ;;
+ *:DragonFly:*:*)
+ echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`"
+ exit ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case "$UNAME_MACHINE" in
+ A*) echo alpha-dec-vms ; exit ;;
+ I*) echo ia64-dec-vms ; exit ;;
+ V*) echo vax-dec-vms ; exit ;;
+ esac ;;
+ *:XENIX:*:SysV)
+ echo i386-pc-xenix
+ exit ;;
+ i*86:skyos:*:*)
+ echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`"
+ exit ;;
+ i*86:rdos:*:*)
+ echo "$UNAME_MACHINE"-pc-rdos
+ exit ;;
+ i*86:AROS:*:*)
+ echo "$UNAME_MACHINE"-pc-aros
+ exit ;;
+ x86_64:VMkernel:*:*)
+ echo "$UNAME_MACHINE"-unknown-esx
+ exit ;;
+ amd64:Isilon\ OneFS:*:*)
+ echo x86_64-unknown-onefs
+ exit ;;
+esac
+
+echo "$0: unable to guess system type" >&2
+
+case "$UNAME_MACHINE:$UNAME_SYSTEM" in
+ mips:Linux | mips64:Linux)
+ # If we got here on MIPS GNU/Linux, output extra information.
+ cat >&2 <<EOF
+
+NOTE: MIPS GNU/Linux systems require a C compiler to fully recognize
+the system type. Please install a C compiler and try again.
+EOF
+ ;;
+esac
+
+cat >&2 <<EOF
+
+This script (version $timestamp), has failed to recognize the
+operating system you are using. If your script is old, overwrite *all*
+copies of config.guess and config.sub with the latest versions from:
+
+ https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
+and
+ https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
+
+If $0 has already been updated, send the following data and any
+information you think might be pertinent to config-patches@gnu.org to
+provide the necessary information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = "$UNAME_MACHINE"
+UNAME_RELEASE = "$UNAME_RELEASE"
+UNAME_SYSTEM = "$UNAME_SYSTEM"
+UNAME_VERSION = "$UNAME_VERSION"
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
--- /dev/null
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define if static plugins should be built */
+#undef GST_PLUGIN_BUILD_STATIC
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#undef HAVE_ARPA_INET_H
+
+/* Define to 1 if C supports variable-length arrays. */
+#undef HAVE_C_VARARRAYS
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Whether getifaddrs() is available on the system */
+#undef HAVE_GETIFADDRS
+
+/* Use GnuTLS */
+#undef HAVE_GNUTLS
+
+/* Have the GUPnP IGD library */
+#undef HAVE_GUPNP
+
+/* Define to 1 if you have the <ifaddrs.h> header file. */
+#undef HAVE_IFADDRS_H
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#undef HAVE_NETDB_H
+
+/* Define to 1 if you have the <net/in.h> header file. */
+#undef HAVE_NET_IN_H
+
+/* Use OpenSSL */
+#undef HAVE_OPENSSL
+
+/* Define to 1 if you have the `poll' function. */
+#undef HAVE_POLL
+
+/* Define to 1 if the system has the type `size_t'. */
+#undef HAVE_SIZE_T
+
+/* Define to 1 if the system has the type `ssize_t'. */
+#undef HAVE_SSIZE_T
+
+/* Define to 1 if stdbool.h conforms to C99. */
+#undef HAVE_STDBOOL_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if the system has the type `_Bool'. */
+#undef HAVE__BOOL
+
+/* Ignore this network interface prefix from the connection check */
+#undef IGNORED_IFACE_PREFIX
+
+/* Define to the sub-directory where libtool stores uninstalled libraries. */
+#undef LT_OBJDIR
+
+/* Define to 1 if assertions should be disabled. */
+#undef NDEBUG
+
+/* Public library function implementation */
+#undef NICEAPI_EXPORT
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Enable extensions on AIX 3, Interix. */
+#ifndef _ALL_SOURCE
+# undef _ALL_SOURCE
+#endif
+/* Enable GNU extensions on systems that have them. */
+#ifndef _GNU_SOURCE
+# undef _GNU_SOURCE
+#endif
+/* Enable threading extensions on Solaris. */
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# undef _POSIX_PTHREAD_SEMANTICS
+#endif
+/* Enable extensions on HP NonStop. */
+#ifndef _TANDEM_SOURCE
+# undef _TANDEM_SOURCE
+#endif
+/* Enable general extensions on Solaris. */
+#ifndef __EXTENSIONS__
+# undef __EXTENSIONS__
+#endif
+
+
+/* Version number of package */
+#undef VERSION
+
+/* Define to `2' to get GNU/libc warnings. */
+/* Only define if -O1 or more is enabled */
+#if defined __OPTIMIZE__ && __OPTIMIZE__ > 0
+# define _FORTIFY_SOURCE 2
+#endif
+
+/* Define to 1 if on MINIX. */
+#undef _MINIX
+
+/* Define to 2 if the system does not provide POSIX.1 features except with
+ this defined. */
+#undef _POSIX_1_SOURCE
+
+/* Define to 1 if you need to in order for `stat' and other things to work. */
+#undef _POSIX_SOURCE
+
+/* Needed to get declarations for msg_control and msg_controllen on Solaris */
+#undef _XOPEN_SOURCE
+
+/* Needed to get declarations for msg_control and msg_controllen on Solaris */
+#undef __EXTENSIONS__
+
+/* Define to the equivalent of the C99 'restrict' keyword, or to
+ nothing if this is not supported. Do not define if restrict is
+ supported directly. */
+#undef restrict
+/* Work around a bug in Sun C++: it does not support _Restrict or
+ __restrict__, even though the corresponding Sun C compiler ends up with
+ "#define restrict _Restrict" or "#define restrict __restrict__" in the
+ previous line. Perhaps some future version of Sun C++ will work with
+ restrict; if so, hopefully it defines __RESTRICT like Sun C does. */
+#if defined __SUNPRO_CC && !defined __RESTRICT
+# define _Restrict
+# define __restrict__
+#endif
--- /dev/null
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright 1992-2018 Free Software Foundation, Inc.
+
+timestamp='2018-05-05'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that
+# program. This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+
+
+# Please send patches to <config-patches@gnu.org>.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# You can get the latest version of this script from:
+# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
+
+Canonicalize a configuration name.
+
+Options:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright 1992-2018 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help"
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo "$1"
+ exit ;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Spilt fields of configuration type
+IFS="-" read -r field1 field2 field3 field4 <<EOF
+$1
+EOF
+
+# Separate into logical components for further validation
+case $1 in
+ *-*-*-*)
+ basic_machine=$field1-$field2
+ os=-$field3-$field4
+ ;;
+ *-*-*)
+ # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two
+ # parts
+ maybe_os=$field2-$field3
+ case $maybe_os in
+ nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc \
+ | linux-newlib* | linux-musl* | linux-uclibc* | uclinux-uclibc* \
+ | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \
+ | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \
+ | storm-chaos* | os2-emx* | rtmk-nova*)
+ basic_machine=$field1
+ os=-$maybe_os
+ ;;
+ android-linux)
+ basic_machine=$field1-unknown
+ os=-linux-android
+ ;;
+ *)
+ basic_machine=$field1-$field2
+ os=-$field3
+ ;;
+ esac
+ ;;
+ *-*)
+ basic_machine=$field1
+ os=-$field2
+ ;;
+ *)
+ basic_machine=$1
+ os=
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple | -axis | -knuth | -cray | -microblaze*)
+ os=
+ basic_machine=$1
+ ;;
+ -bluegene*)
+ os=-cnk
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond)
+ os=
+ basic_machine=$1
+ ;;
+ -scout)
+ ;;
+ -wrs)
+ os=-vxworks
+ basic_machine=$1
+ ;;
+ -chorusos*)
+ os=-chorusos
+ basic_machine=$1
+ ;;
+ -chorusrdb)
+ os=-chorusrdb
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco6)
+ os=-sco5v6
+ basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco5)
+ os=-sco3.2v5
+ basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco5v6*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -udk*)
+ basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*178)
+ os=-lynxos178
+ ;;
+ -lynx*5)
+ os=-lynxos5
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo "$1" | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+ -mint | -mint[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ 1750a | 580 \
+ | a29k \
+ | aarch64 | aarch64_be \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | am33_2.0 \
+ | arc | arceb \
+ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv6m | armv[78][arm] \
+ | avr | avr32 \
+ | ba \
+ | be32 | be64 \
+ | bfin \
+ | c4x | c8051 | clipper | csky \
+ | d10v | d30v | dlx | dsp16xx \
+ | e2k | epiphany \
+ | fido | fr30 | frv | ft32 \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | hexagon \
+ | i370 | i860 | i960 | ia16 | ia64 \
+ | ip2k | iq2000 \
+ | k1om \
+ | le32 | le64 \
+ | lm32 \
+ | m32c | m32r | m32rle | m68000 | m68k | m88k \
+ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64octeon | mips64octeonel \
+ | mips64orion | mips64orionel \
+ | mips64r5900 | mips64r5900el \
+ | mips64vr | mips64vrel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mips64vr5900 | mips64vr5900el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa32r6 | mipsisa32r6el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64r6 | mipsisa64r6el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipsr5900 | mipsr5900el \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | moxie \
+ | mt \
+ | msp430 \
+ | nds32 | nds32le | nds32be \
+ | nfp \
+ | nios | nios2 | nios2eb | nios2el \
+ | ns16k | ns32k \
+ | open8 | or1k | or1knd | or32 \
+ | pdp10 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle \
+ | pru \
+ | pyramid \
+ | riscv32 | riscv64 \
+ | rl78 | rx \
+ | score \
+ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+ | spu \
+ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
+ | ubicom32 \
+ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
+ | visium \
+ | wasm32 \
+ | x86 | xc16x | xstormy16 | xtensa \
+ | z8k | z80)
+ basic_machine=$basic_machine-unknown
+ ;;
+ c54x)
+ basic_machine=tic54x-unknown
+ ;;
+ c55x)
+ basic_machine=tic55x-unknown
+ ;;
+ c6x)
+ basic_machine=tic6x-unknown
+ ;;
+ leon|leon[3-9])
+ basic_machine=sparc-$basic_machine
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65)
+ ;;
+ m9s12z | m68hcs12z | hcs12z | s12z)
+ basic_machine=s12z-unknown
+ os=-none
+ ;;
+ ms1)
+ basic_machine=mt-unknown
+ ;;
+
+ strongarm | thumb | xscale)
+ basic_machine=arm-unknown
+ ;;
+ xgate)
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ xscaleeb)
+ basic_machine=armeb-unknown
+ ;;
+
+ xscaleel)
+ basic_machine=armel-unknown
+ ;;
+
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ 580-* \
+ | a29k-* \
+ | aarch64-* | aarch64_be-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+ | avr-* | avr32-* \
+ | ba-* \
+ | be32-* | be64-* \
+ | bfin-* | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* \
+ | c8051-* | clipper-* | craynv-* | csky-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | e2k-* | elxsi-* \
+ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | hexagon-* \
+ | i*86-* | i860-* | i960-* | ia16-* | ia64-* \
+ | ip2k-* | iq2000-* \
+ | k1om-* \
+ | le32-* | le64-* \
+ | lm32-* \
+ | m32c-* | m32r-* | m32rle-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
+ | microblaze-* | microblazeel-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64octeon-* | mips64octeonel-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64r5900-* | mips64r5900el-* \
+ | mips64vr-* | mips64vrel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mips64vr5900-* | mips64vr5900el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa32r6-* | mipsisa32r6el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
+ | mipsisa64r6-* | mipsisa64r6el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipsr5900-* | mipsr5900el-* \
+ | mipstx39-* | mipstx39el-* \
+ | mmix-* \
+ | mt-* \
+ | msp430-* \
+ | nds32-* | nds32le-* | nds32be-* \
+ | nfp-* \
+ | nios-* | nios2-* | nios2eb-* | nios2el-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | open8-* \
+ | or1k*-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
+ | pru-* \
+ | pyramid-* \
+ | riscv32-* | riscv64-* \
+ | rl78-* | romp-* | rs6000-* | rx-* \
+ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+ | sparclite-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \
+ | tahoe-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tile*-* \
+ | tron-* \
+ | ubicom32-* \
+ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
+ | vax-* \
+ | visium-* \
+ | wasm32-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xc16x-* | xps100-* \
+ | xstormy16-* | xtensa*-* \
+ | ymp-* \
+ | z8k-* | z80-*)
+ ;;
+ # Recognize the basic CPU types without company name, with glob match.
+ xtensa*)
+ basic_machine=$basic_machine-unknown
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 386bsd)
+ basic_machine=i386-pc
+ os=-bsd
+ ;;
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ abacus)
+ basic_machine=abacus-unknown
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amd64)
+ basic_machine=x86_64-pc
+ ;;
+ amd64-*)
+ basic_machine=x86_64-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-unknown
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
+ aros)
+ basic_machine=i386-pc
+ os=-aros
+ ;;
+ asmjs)
+ basic_machine=asmjs-unknown
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ blackfin)
+ basic_machine=bfin-unknown
+ os=-linux
+ ;;
+ blackfin-*)
+ basic_machine=bfin-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ bluegene*)
+ basic_machine=powerpc-ibm
+ os=-cnk
+ ;;
+ c54x-*)
+ basic_machine=tic54x-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ ;;
+ c55x-*)
+ basic_machine=tic55x-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ ;;
+ c6x-*)
+ basic_machine=tic6x-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ cegcc)
+ basic_machine=arm-unknown
+ os=-cegcc
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | j90)
+ basic_machine=j90-cray
+ os=-unicos
+ ;;
+ craynv)
+ basic_machine=craynv-cray
+ os=-unicosmp
+ ;;
+ cr16 | cr16-*)
+ basic_machine=cr16-unknown
+ os=-elf
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ crisv32 | crisv32-* | etraxfs*)
+ basic_machine=crisv32-axis
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ crx)
+ basic_machine=crx-unknown
+ os=-elf
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ decsystem10* | dec10*)
+ basic_machine=pdp10-dec
+ os=-tops10
+ ;;
+ decsystem20* | dec20*)
+ basic_machine=pdp10-dec
+ os=-tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ dicos)
+ basic_machine=i686-pc
+ os=-dicos
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ os=-msdosdjgpp
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2*)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ e500v[12])
+ basic_machine=powerpc-unknown
+ os=$os"spe"
+ ;;
+ e500v[12]-*)
+ basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ os=$os"spe"
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=-go32
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+ i*86v32)
+ basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i*86v4*)
+ basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i*86v)
+ basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i*86sol2)
+ basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ vsta)
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ leon-*|leon[3-9]-*)
+ basic_machine=sparc-`echo "$basic_machine" | sed 's/-.*//'`
+ ;;
+ m68knommu)
+ basic_machine=m68k-unknown
+ os=-linux
+ ;;
+ m68knommu-*)
+ basic_machine=m68k-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ microblaze*)
+ basic_machine=microblaze-xilinx
+ ;;
+ mingw64)
+ basic_machine=x86_64-pc
+ os=-mingw64
+ ;;
+ mingw32)
+ basic_machine=i686-pc
+ os=-mingw32
+ ;;
+ mingw32ce)
+ basic_machine=arm-unknown
+ os=-mingw32ce
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+ mips3*-*)
+ basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
+ moxiebox)
+ basic_machine=moxie-unknown
+ os=-moxiebox
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ ms1-*)
+ basic_machine=`echo "$basic_machine" | sed -e 's/ms1-/mt-/'`
+ ;;
+ msys)
+ basic_machine=i686-pc
+ os=-msys
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ nacl)
+ basic_machine=le32-unknown
+ os=-nacl
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=-netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=-linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
+ next | m*-next)
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=-mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=-nonstopux
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ neo-tandem)
+ basic_machine=neo-tandem
+ ;;
+ nse-tandem)
+ basic_machine=nse-tandem
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ nsv-tandem)
+ basic_machine=nsv-tandem
+ ;;
+ nsx-tandem)
+ basic_machine=nsx-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ openrisc | openrisc-*)
+ basic_machine=or32-unknown
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ os=-os400
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ parisc)
+ basic_machine=hppa-unknown
+ os=-linux
+ ;;
+ parisc-*)
+ basic_machine=hppa-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ os=-linux
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pc98)
+ basic_machine=i386-pc
+ ;;
+ pc98-*)
+ basic_machine=i386-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ ;;
+ pentium | p5 | k5 | k6 | nexgen | viac3)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon | athlon_*)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2 | pentiumiii | pentium3)
+ basic_machine=i686-pc
+ ;;
+ pentium4)
+ basic_machine=i786-pc
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ basic_machine=i586-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-*)
+ basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+ basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ ;;
+ pentium4-*)
+ basic_machine=i786-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc | ppcbe) basic_machine=powerpc-unknown
+ ;;
+ ppc-* | ppcbe-*)
+ basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+ ppc64-*) basic_machine=powerpc64-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little)
+ basic_machine=powerpc64le-unknown
+ ;;
+ ppc64le-* | powerpc64little-*)
+ basic_machine=powerpc64le-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=-pw32
+ ;;
+ rdos | rdos64)
+ basic_machine=x86_64-pc
+ os=-rdos
+ ;;
+ rdos32)
+ basic_machine=i386-pc
+ os=-rdos
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ s390 | s390-*)
+ basic_machine=s390-ibm
+ ;;
+ s390x | s390x-*)
+ basic_machine=s390x-ibm
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ sb1)
+ basic_machine=mipsisa64sb1-unknown
+ ;;
+ sb1el)
+ basic_machine=mipsisa64sb1el-unknown
+ ;;
+ sde)
+ basic_machine=mipsisa32-sde
+ os=-elf
+ ;;
+ sei)
+ basic_machine=mips-sei
+ os=-seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh5el)
+ basic_machine=sh5le-unknown
+ ;;
+ simso-wrs)
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
+ strongarm-* | thumb-*)
+ basic_machine=arm-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=-unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=-unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=-unicos
+ ;;
+ tile*)
+ basic_machine=$basic_machine-unknown
+ os=-linux-gnu
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=-tops20
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ os=-tpf
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=-none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ w65*)
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ x64)
+ basic_machine=x86_64-pc
+ ;;
+ xbox)
+ basic_machine=i686-pc
+ os=-mingw32
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ xscale-* | xscalee[bl]-*)
+ basic_machine=`echo "$basic_machine" | sed 's/^xscale/arm/'`
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n)
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ mmix)
+ basic_machine=mmix-knuth
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
+ basic_machine=sh-unknown
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+ *-unknown)
+ # Make sure to match an already-canonicalized machine name.
+ ;;
+ *)
+ echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo "$basic_machine" | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo "$basic_machine" | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x$os != x ]
+then
+case $os in
+ # First match some system type aliases that might get confused
+ # with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -auroraux)
+ os=-auroraux
+ ;;
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # es1800 is here to avoid being matched by es* (a different OS)
+ -es1800*)
+ os=-ose
+ ;;
+ # Now accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST end in a * to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
+ | -sym* | -kopensolaris* | -plan9* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* | -aros* | -cloudabi* | -sortix* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -knetbsd* | -mirbsd* | -netbsd* \
+ | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \
+ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* | -hcos* \
+ | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \
+ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
+ | -linux-newlib* | -linux-musl* | -linux-uclibc* \
+ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
+ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+ | -morphos* | -superux* | -rtmk* | -windiss* \
+ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \
+ | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox* | -bme* \
+ | -midnightbsd*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+ case $basic_machine in
+ x86-* | i*86-*)
+ ;;
+ *)
+ os=-nto$os
+ ;;
+ esac
+ ;;
+ -nto-qnx*)
+ ;;
+ -nto*)
+ os=`echo $os | sed -e 's|nto|nto-qnx|'`
+ ;;
+ -sim | -xray | -os68k* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo "$os" | sed -e 's|mac|macos|'`
+ ;;
+ -linux-dietlibc)
+ os=-linux-dietlibc
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo "$os" | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo "$os" | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -opened*)
+ os=-openedition
+ ;;
+ -os400*)
+ os=-os400
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -syllable*)
+ os=-syllable
+ ;;
+ -386bsd)
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -nova*)
+ os=-rtmk-nova
+ ;;
+ -ns2)
+ os=-nextstep2
+ ;;
+ -nsk*)
+ os=-nsk
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -tpf*)
+ os=-tpf
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -ose*)
+ os=-ose
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ os=-mint
+ ;;
+ -zvmoe)
+ os=-zvmoe
+ ;;
+ -dicos*)
+ os=-dicos
+ ;;
+ -pikeos*)
+ # Until real need of OS specific support for
+ # particular features comes up, bare metal
+ # configurations are quite functional.
+ case $basic_machine in
+ arm*)
+ os=-eabi
+ ;;
+ *)
+ os=-elf
+ ;;
+ esac
+ ;;
+ -nacl*)
+ ;;
+ -ios)
+ ;;
+ -none)
+ ;;
+ -*-eabi)
+ case $basic_machine in
+ arm*)
+ ;;
+ esac
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ score-*)
+ os=-elf
+ ;;
+ spu-*)
+ os=-elf
+ ;;
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ c4x-* | tic4x-*)
+ os=-coff
+ ;;
+ c8051-*)
+ os=-elf
+ ;;
+ hexagon-*)
+ os=-elf
+ ;;
+ tic54x-*)
+ os=-coff
+ ;;
+ tic55x-*)
+ os=-coff
+ ;;
+ tic6x-*)
+ os=-coff
+ ;;
+ # This must come before the *-dec entry.
+ pdp10-*)
+ os=-tops20
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mep-*)
+ os=-elf
+ ;;
+ mips*-cisco)
+ os=-elf
+ ;;
+ mips*-*)
+ os=-elf
+ ;;
+ or32-*)
+ os=-coff
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ pru-*)
+ os=-elf
+ ;;
+ *-be)
+ os=-beos
+ ;;
+ *-ibm)
+ os=-aix
+ ;;
+ *-knuth)
+ os=-mmixware
+ ;;
+ *-wec)
+ os=-proelf
+ ;;
+ *-winbond)
+ os=-proelf
+ ;;
+ *-oki)
+ os=-proelf
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next)
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=-uxpv
+ ;;
+ *-rom68k)
+ os=-coff
+ ;;
+ *-*bug)
+ os=-coff
+ ;;
+ *-apple)
+ os=-macos
+ ;;
+ *-atari*)
+ os=-mint
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -cnk*|-aix*)
+ vendor=ibm
+ ;;
+ -beos*)
+ vendor=be
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -mpeix*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs* | -opened*)
+ vendor=ibm
+ ;;
+ -os400*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -tpf*)
+ vendor=ibm
+ ;;
+ -vxsim* | -vxworks* | -windiss*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ -hms*)
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*)
+ vendor=apple
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ vendor=atari
+ ;;
+ -vos*)
+ vendor=stratus
+ ;;
+ esac
+ basic_machine=`echo "$basic_machine" | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo "$basic_machine$os"
+exit
+
+# Local variables:
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
--- /dev/null
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69 for libnice 0.1.16.
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+ # into an infinite loop, continuously re-executing ourselves.
+ if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+ _as_can_reexec=no; export _as_can_reexec;
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+ fi
+ # We don't want this to propagate to other subprocesses.
+ { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+ as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+"
+ as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+ exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1
+
+ test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || (
+ ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+ ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO
+ ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO
+ PATH=/empty FPATH=/empty; export PATH FPATH
+ test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\
+ || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1"
+ if (eval "$as_required") 2>/dev/null; then :
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ as_found=:
+ case $as_dir in #(
+ /*)
+ for as_base in sh bash ksh sh5; do
+ # Try only shells that exist, to save several forks.
+ as_shell=$as_dir/$as_base
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ CONFIG_SHELL=$as_shell as_have_required=yes
+ if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ break 2
+fi
+fi
+ done;;
+ esac
+ as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+ if test "x$CONFIG_SHELL" != x; then :
+ export CONFIG_SHELL
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+ if test x$as_have_required = xno; then :
+ $as_echo "$0: This script requires a shell more modern than all"
+ $as_echo "$0: the shells that I found on your system."
+ if test x${ZSH_VERSION+set} = xset ; then
+ $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ else
+ $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+ fi
+ exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+ as_lineno_1=$LINENO as_lineno_1a=$LINENO
+ as_lineno_2=$LINENO as_lineno_2a=$LINENO
+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+ # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+ # already done that, so ensure we don't try to do so again and fall
+ # in an infinite loop. This has already happened in practice.
+ _as_can_reexec=no; export _as_can_reexec
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='libnice'
+PACKAGE_TARNAME='libnice'
+PACKAGE_VERSION='0.1.16'
+PACKAGE_STRING='libnice 0.1.16'
+PACKAGE_BUGREPORT=''
+PACKAGE_URL=''
+
+ac_unique_file="agent/agent.c"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='am__EXEEXT_FALSE
+am__EXEEXT_TRUE
+LTLIBOBJS
+LIBOBJS
+HAVE_INTROSPECTION_FALSE
+HAVE_INTROSPECTION_TRUE
+INTROSPECTION_MAKEFILE
+INTROSPECTION_LIBS
+INTROSPECTION_CFLAGS
+INTROSPECTION_TYPELIBDIR
+INTROSPECTION_GIRDIR
+INTROSPECTION_GENERATE
+INTROSPECTION_COMPILER
+INTROSPECTION_SCANNER
+GTK_DOC_USE_REBASE_FALSE
+GTK_DOC_USE_REBASE_TRUE
+GTK_DOC_USE_LIBTOOL_FALSE
+GTK_DOC_USE_LIBTOOL_TRUE
+GTK_DOC_BUILD_PDF_FALSE
+GTK_DOC_BUILD_PDF_TRUE
+GTK_DOC_BUILD_HTML_FALSE
+GTK_DOC_BUILD_HTML_TRUE
+ENABLE_GTK_DOC_FALSE
+ENABLE_GTK_DOC_TRUE
+HAVE_GTK_DOC_FALSE
+HAVE_GTK_DOC_TRUE
+GTKDOC_DEPS_LIBS
+GTKDOC_DEPS_CFLAGS
+HTML_DIR
+GTKDOC_MKPDF
+GTKDOC_REBASE
+GTKDOC_CHECK_PATH
+GTKDOC_CHECK
+GST_PLUGIN_BUILD_STATIC_FALSE
+GST_PLUGIN_BUILD_STATIC_TRUE
+CCACHE_DISABLE
+UPNP_ENABLED
+HAVE_GUPNP
+GUPNP_PACKAGES
+GUPNP_PACKAGES_PRIVATE
+GUPNP_PACKAGES_PUBLIC
+GUPNP_LIBS
+GUPNP_CFLAGS
+WITH_GSTREAMER010_FALSE
+WITH_GSTREAMER010_TRUE
+HAVE_GST_CHECK_FALSE
+HAVE_GST_CHECK_TRUE
+WITH_GSTREAMER_FALSE
+WITH_GSTREAMER_TRUE
+gstplugin010dir
+gstplugindir
+GST010_LIBS
+GST010_CFLAGS
+GST_CHECK_LIBS
+GST_CHECK_CFLAGS
+GST_LIBS
+GST_CFLAGS
+NICE_PACKAGES_PRIVATE
+NICE_PACKAGES_PUBLIC
+OPENSSL_LDFLAGS
+OPENSSL_LIBS
+OPENSSL_INCLUDES
+GNUTLS_LIBS
+GNUTLS_CFLAGS
+GLIB_LIBS
+GLIB_CFLAGS
+PKG_CONFIG_LIBDIR
+PKG_CONFIG_PATH
+PKG_CONFIG
+LIBRT
+LIBNICE_CFLAGS
+WINDOWS_FALSE
+WINDOWS_TRUE
+GLIB_MKENUMS
+LT_SYS_LIBRARY_PATH
+OTOOL64
+OTOOL
+LIPO
+NMEDIT
+DSYMUTIL
+MANIFEST_TOOL
+RANLIB
+LN_S
+NM
+ac_ct_DUMPBIN
+DUMPBIN
+LD
+FGREP
+SED
+LIBTOOL
+OBJDUMP
+DLLTOOL
+AS
+ac_ct_AR
+AR
+EGREP
+GREP
+CPP
+am__fastdepCC_FALSE
+am__fastdepCC_TRUE
+CCDEPMODE
+am__nodep
+AMDEPBACKSLASH
+AMDEP_FALSE
+AMDEP_TRUE
+am__include
+DEPDIR
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+LIBNICE_LT_LDFLAGS
+AM_BACKSLASH
+AM_DEFAULT_VERBOSITY
+AM_DEFAULT_V
+AM_V
+am__untar
+am__tar
+AMTAR
+am__leading_dot
+SET_MAKE
+AWK
+mkdir_p
+MKDIR_P
+INSTALL_STRIP_PROGRAM
+STRIP
+install_sh
+MAKEINFO
+AUTOHEADER
+AUTOMAKE
+AUTOCONF
+ACLOCAL
+VERSION
+PACKAGE
+CYGPATH_W
+am__isrc
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+target_os
+target_vendor
+target_cpu
+target
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL
+am__quote'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+enable_silent_rules
+enable_dependency_tracking
+enable_static
+enable_shared
+with_pic
+enable_fast_install
+with_aix_soname
+with_gnu_ld
+with_sysroot
+enable_libtool_lock
+enable_assert
+enable_compile_warnings
+with_crypto_library
+with_openssl
+with_gstreamer
+with_gstreamer_0_10
+enable_gupnp
+enable_coverage
+enable_static_plugins
+with_html_dir
+enable_gtk_doc
+enable_gtk_doc_html
+enable_gtk_doc_pdf
+enable_introspection
+with_ignored_network_interface_prefix
+'
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP
+LT_SYS_LIBRARY_PATH
+PKG_CONFIG
+PKG_CONFIG_PATH
+PKG_CONFIG_LIBDIR
+GLIB_CFLAGS
+GLIB_LIBS
+GNUTLS_CFLAGS
+GNUTLS_LIBS
+GST_CFLAGS
+GST_LIBS
+GST_CHECK_CFLAGS
+GST_CHECK_LIBS
+GST010_CFLAGS
+GST010_LIBS
+GUPNP_CFLAGS
+GUPNP_LIBS
+GTKDOC_DEPS_CFLAGS
+GTKDOC_DEPS_LIBS'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *=) ac_optarg= ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ case $ac_envvar in #(
+ '' | [0-9]* | *[!_$as_cr_alnum]* )
+ as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+ esac
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+ case $enable_option_checking in
+ no) ;;
+ fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+ *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir
+do
+ eval ac_val=\$$ac_var
+ # Remove trailing slashes.
+ case $ac_val in
+ */ )
+ ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+ eval $ac_var=\$ac_val;;
+ esac
+ # Be sure to have absolute directory names.
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_myself" : 'X\(//\)[^/]' \| \
+ X"$as_myself" : 'X\(//\)$' \| \
+ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures libnice 0.1.16 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking ...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/libnice]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+
+Program names:
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM run sed PROGRAM on installed program names
+
+System types:
+ --build=BUILD configure for building on BUILD [guessed]
+ --host=HOST cross-compile to build programs to run on HOST [BUILD]
+ --target=TARGET configure for building compilers for TARGET [HOST]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+ case $ac_init_help in
+ short | recursive ) echo "Configuration of libnice 0.1.16:";;
+ esac
+ cat <<\_ACEOF
+
+Optional Features:
+ --disable-option-checking ignore unrecognized --enable/--with options
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --enable-silent-rules less verbose build output (undo: "make V=1")
+ --disable-silent-rules verbose build output (undo: "make V=0")
+ --enable-dependency-tracking
+ do not reject slow dependency extractors
+ --disable-dependency-tracking
+ speeds up one-time build
+ --enable-static[=PKGS] build static libraries [default=no]
+ --enable-shared[=PKGS] build shared libraries [default=yes]
+ --enable-fast-install[=PKGS]
+ optimize for fast installation [default=yes]
+ --disable-libtool-lock avoid locking (might break parallel builds)
+ --disable-assert turn off assertions
+ --enable-compile-warnings=[no/minimum/yes/maximum/error]
+ Enable different levels of compiler warnings
+ --disable-gupnp Disable GUPnP IGD support
+ --enable-coverage build for test coverage (default disabled)
+ --enable-static-plugins build static plugins [default=no]
+ --enable-gtk-doc use gtk-doc to build documentation [[default=no]]
+ --enable-gtk-doc-html build documentation in html format [[default=yes]]
+ --enable-gtk-doc-pdf build documentation in pdf format [[default=no]]
+ --enable-introspection=[no/auto/yes]
+ Enable introspection for this build
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use
+ both]
+ --with-aix-soname=aix|svr4|both
+ shared library versioning (aka "SONAME") variant to
+ provide on AIX, [default=aix].
+ --with-gnu-ld assume the C compiler uses GNU ld [default=no]
+ --with-sysroot[=DIR] Search for dependent libraries within DIR (or the
+ compiler's sysroot if not specified).
+ --with-crypto-library=\{gnutls,openssl,auto\}
+ select Crypto library (gnutls or openssl)
+ --with-openssl=DIR root of the OpenSSL directory
+ --with-gstreamer build GStreamer plugin
+ --with-gstreamer-0.10 build GStreamer 0.10 plugin
+ --with-html-dir=PATH path to installed docs
+ --with-ignored-network-interface-prefix=string
+ Ignore network interfaces whose name starts with
+ "string" from the ICE connection check algorithm.
+ For example, interfaces "virbr" in the case of the
+ virtual bridge handled by libvirtd, do not help in
+ finding connectivity.
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ CPP C preprocessor
+ LT_SYS_LIBRARY_PATH
+ User-defined run-time library search path.
+ PKG_CONFIG path to pkg-config utility
+ PKG_CONFIG_PATH
+ directories to add to pkg-config's search path
+ PKG_CONFIG_LIBDIR
+ path overriding pkg-config's built-in search path
+ GLIB_CFLAGS C compiler flags for GLIB, overriding pkg-config
+ GLIB_LIBS linker flags for GLIB, overriding pkg-config
+ GNUTLS_CFLAGS
+ C compiler flags for GNUTLS, overriding pkg-config
+ GNUTLS_LIBS linker flags for GNUTLS, overriding pkg-config
+ GST_CFLAGS C compiler flags for GST, overriding pkg-config
+ GST_LIBS linker flags for GST, overriding pkg-config
+ GST_CHECK_CFLAGS
+ C compiler flags for GST_CHECK, overriding pkg-config
+ GST_CHECK_LIBS
+ linker flags for GST_CHECK, overriding pkg-config
+ GST010_CFLAGS
+ C compiler flags for GST010, overriding pkg-config
+ GST010_LIBS linker flags for GST010, overriding pkg-config
+ GUPNP_CFLAGS
+ C compiler flags for GUPNP, overriding pkg-config
+ GUPNP_LIBS linker flags for GUPNP, overriding pkg-config
+ GTKDOC_DEPS_CFLAGS
+ C compiler flags for GTKDOC_DEPS, overriding pkg-config
+ GTKDOC_DEPS_LIBS
+ linker flags for GTKDOC_DEPS, overriding pkg-config
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to the package provider.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" ||
+ { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+ continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+libnice configure 0.1.16
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } > conftest.i && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_c_check_header_mongrel ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if eval \${$3+:} false; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_header_compiler=yes
+else
+ ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ ac_header_preproc=yes
+else
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
+ yes:no: )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+ ;;
+ no:yes:* )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+ ;;
+esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_mongrel
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: program exited with status $ac_status" >&5
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=$ac_status
+fi
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext && {
+ test "$cross_compiling" = yes ||
+ test -x conftest$ac_exeext
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+ # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+ # interfere with the next link command; also delete a directory that is
+ # left behind by Apple's compiler. We do this before executing the actions.
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $2 (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_func
+
+# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
+# -------------------------------------------
+# Tests whether TYPE exists after having included INCLUDES, setting cache
+# variable VAR accordingly.
+ac_fn_c_check_type ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ eval "$3=no"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+if (sizeof ($2))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+if (sizeof (($2)))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ eval "$3=yes"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_type
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by libnice $as_me 0.1.16, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ $as_echo "PATH: $as_dir"
+ done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+ 2)
+ as_fn_append ac_configure_args1 " '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ as_fn_append ac_configure_args " '$ac_arg'"
+ ;;
+ esac
+ done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ $as_echo "$as_me: caught signal $ac_signal"
+ $as_echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+ # We do not want a PATH search for config.site.
+ case $CONFIG_SITE in #((
+ -*) ac_site_file1=./$CONFIG_SITE;;
+ */*) ac_site_file1=$CONFIG_SITE;;
+ *) ac_site_file1=./$CONFIG_SITE;;
+ esac
+elif test "x$prefix" != xNONE; then
+ ac_site_file1=$prefix/share/config.site
+ ac_site_file2=$prefix/etc/config.site
+else
+ ac_site_file1=$ac_default_prefix/share/config.site
+ ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+ test "x$ac_site_file" = xNONE && continue
+ if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file" \
+ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special files
+ # actually), so we avoid doing that. DJGPP emulates it as a regular file.
+ if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ # differences in whitespace do not lead to failure.
+ ac_old_val_w=`echo x $ac_old_val`
+ ac_new_val_w=`echo x $ac_new_val`
+ if test "$ac_old_val_w" != "$ac_new_val_w"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ ac_cache_corrupted=:
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ eval $ac_var=\$ac_old_val
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+LIBNICE_RELEASE="yes"
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+ if test -f "$ac_dir/install-sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f "$ac_dir/install.sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ elif test -f "$ac_dir/shtool"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/shtool install -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
+
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+ as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+$as_echo_n "checking build system type... " >&6; }
+if ${ac_cv_build+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+ ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+ as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+ as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+$as_echo "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+$as_echo_n "checking host system type... " >&6; }
+if ${ac_cv_host+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "x$host_alias" = x; then
+ ac_cv_host=$ac_cv_build
+else
+ ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+ as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+$as_echo "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5
+$as_echo_n "checking target system type... " >&6; }
+if ${ac_cv_target+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "x$target_alias" = x; then
+ ac_cv_target=$ac_cv_host
+else
+ ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` ||
+ as_fn_error $? "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5
+$as_echo "$ac_cv_target" >&6; }
+case $ac_cv_target in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;;
+esac
+target=$ac_cv_target
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_target
+shift
+target_cpu=$1
+target_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+target_os=$*
+IFS=$ac_save_IFS
+case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
+
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+test -n "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+
+ac_config_headers="$ac_config_headers config.h"
+
+am__api_version='1.16'
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if ${ac_cv_path_install+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+ ./ | .// | /[cC]/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ rm -rf conftest.one conftest.two conftest.dir
+ echo one > conftest.one
+ echo two > conftest.two
+ mkdir conftest.dir
+ if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+ test -s conftest.one && test -s conftest.two &&
+ test -s conftest.dir/conftest.one &&
+ test -s conftest.dir/conftest.two
+ then
+ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+
+ done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL=$ac_cv_path_install
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ INSTALL=$ac_install_sh
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5
+$as_echo_n "checking whether build environment is sane... " >&6; }
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name. Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+ *[\\\"\#\$\&\'\`$am_lf]*)
+ as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;;
+esac
+case $srcdir in
+ *[\\\"\#\$\&\'\`$am_lf\ \ ]*)
+ as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;;
+esac
+
+# Do 'set' in a subshell so we don't clobber the current shell's
+# arguments. Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+ am_has_slept=no
+ for am_try in 1 2; do
+ echo "timestamp, slept: $am_has_slept" > conftest.file
+ set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+ if test "$*" = "X"; then
+ # -L didn't work.
+ set X `ls -t "$srcdir/configure" conftest.file`
+ fi
+ if test "$*" != "X $srcdir/configure conftest.file" \
+ && test "$*" != "X conftest.file $srcdir/configure"; then
+
+ # If neither matched, then we have a broken ls. This can happen
+ # if, for instance, CONFIG_SHELL is bash and it inherits a
+ # broken ls alias from the environment. This has actually
+ # happened. Such a system could not be considered "sane".
+ as_fn_error $? "ls -t appears to fail. Make sure there is not a broken
+ alias in your environment" "$LINENO" 5
+ fi
+ if test "$2" = conftest.file || test $am_try -eq 2; then
+ break
+ fi
+ # Just in case.
+ sleep 1
+ am_has_slept=yes
+ done
+ test "$2" = conftest.file
+ )
+then
+ # Ok.
+ :
+else
+ as_fn_error $? "newly created file is older than distributed files!
+Check your system clock" "$LINENO" 5
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+# If we didn't sleep, we still need to ensure time stamps of config.status and
+# generated files are strictly newer.
+am_sleep_pid=
+if grep 'slept: no' conftest.file >/dev/null 2>&1; then
+ ( sleep 1 ) &
+ am_sleep_pid=$!
+fi
+
+rm -f conftest.file
+
+test "$program_prefix" != NONE &&
+ program_transform_name="s&^&$program_prefix&;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+ program_transform_name="s&\$&$program_suffix&;$program_transform_name"
+# Double any \ or $.
+# By default was `s,x,x', remove it if useless.
+ac_script='s/[\\$]/&&/g;s/;s,x,x,$//'
+program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
+
+# Expand $ac_aux_dir to an absolute path.
+am_aux_dir=`cd "$ac_aux_dir" && pwd`
+
+if test x"${MISSING+set}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+ *)
+ MISSING="\${SHELL} $am_aux_dir/missing" ;;
+ esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --is-lightweight"; then
+ am_missing_run="$MISSING "
+else
+ am_missing_run=
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5
+$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;}
+fi
+
+if test x"${install_sh+set}" != xset; then
+ case $am_aux_dir in
+ *\ * | *\ *)
+ install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+ *)
+ install_sh="\${SHELL} $am_aux_dir/install-sh"
+ esac
+fi
+
+# Installed binaries are usually stripped using 'strip' when the user
+# run "make install-strip". However 'strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the 'STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_STRIP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$STRIP"; then
+ ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+ ac_ct_STRIP=$STRIP
+ # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_STRIP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_STRIP"; then
+ ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_STRIP="strip"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+$as_echo "$ac_ct_STRIP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_STRIP" = x; then
+ STRIP=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ STRIP=$ac_ct_STRIP
+ fi
+else
+ STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5
+$as_echo_n "checking for a thread-safe mkdir -p... " >&6; }
+if test -z "$MKDIR_P"; then
+ if ${ac_cv_path_mkdir+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in mkdir gmkdir; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue
+ case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
+ 'mkdir (GNU coreutils) '* | \
+ 'mkdir (coreutils) '* | \
+ 'mkdir (fileutils) '4.1*)
+ ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext
+ break 3;;
+ esac
+ done
+ done
+ done
+IFS=$as_save_IFS
+
+fi
+
+ test -d ./--version && rmdir ./--version
+ if test "${ac_cv_path_mkdir+set}" = set; then
+ MKDIR_P="$ac_cv_path_mkdir -p"
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for MKDIR_P within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ MKDIR_P="$ac_install_sh -d"
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5
+$as_echo "$MKDIR_P" >&6; }
+
+for ac_prog in gawk mawk nawk awk
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AWK+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$AWK"; then
+ ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AWK="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5
+$as_echo "$AWK" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$AWK" && break
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+ @echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+ *@@@%%%=?*=@@@%%%*)
+ eval ac_cv_prog_make_${ac_make}_set=yes;;
+ *)
+ eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ SET_MAKE=
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+ am__leading_dot=.
+else
+ am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+
+# Check whether --enable-silent-rules was given.
+if test "${enable_silent_rules+set}" = set; then :
+ enableval=$enable_silent_rules;
+fi
+
+case $enable_silent_rules in # (((
+ yes) AM_DEFAULT_VERBOSITY=0;;
+ no) AM_DEFAULT_VERBOSITY=1;;
+ *) AM_DEFAULT_VERBOSITY=1;;
+esac
+am_make=${MAKE-make}
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5
+$as_echo_n "checking whether $am_make supports nested variables... " >&6; }
+if ${am_cv_make_support_nested_variables+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if $as_echo 'TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+ @$(TRUE)
+.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then
+ am_cv_make_support_nested_variables=yes
+else
+ am_cv_make_support_nested_variables=no
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5
+$as_echo "$am_cv_make_support_nested_variables" >&6; }
+if test $am_cv_make_support_nested_variables = yes; then
+ AM_V='$(V)'
+ AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+ AM_V=$AM_DEFAULT_VERBOSITY
+ AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
+fi
+AM_BACKSLASH='\'
+
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+ # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+ # is not polluted with repeated "-I."
+ am__isrc=' -I$(srcdir)'
+ # test to see if srcdir already configured
+ if test -f $srcdir/config.status; then
+ as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5
+ fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+ if (cygpath --version) >/dev/null 2>/dev/null; then
+ CYGPATH_W='cygpath -w'
+ else
+ CYGPATH_W=echo
+ fi
+fi
+
+
+# Define the identity of the package.
+ PACKAGE='libnice'
+ VERSION='0.1.16'
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE "$PACKAGE"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define VERSION "$VERSION"
+_ACEOF
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+# For better backward compatibility. To be removed once Automake 1.9.x
+# dies out for good. For more background, see:
+# <https://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
+# <https://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
+mkdir_p='$(MKDIR_P)'
+
+# We need awk for the "check" target (and possibly the TAP driver). The
+# system "awk" is bad on some platforms.
+# Always define AMTAR for backward compatibility. Yes, it's still used
+# in the wild :-( We should find a proper way to deprecate it ...
+AMTAR='$${TAR-tar}'
+
+
+# We'll loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar pax cpio none'
+
+am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'
+
+
+
+
+
+
+# POSIX will say in a future version that running "rm -f" with no argument
+# is OK; and we want to be able to make that assumption in our Makefile
+# recipes. So use an aggressive probe to check that the usage we want is
+# actually supported "in the wild" to an acceptable degree.
+# See automake bug#10828.
+# To make any issue more visible, cause the running configure to be aborted
+# by default if the 'rm' program in use doesn't match our expectations; the
+# user can still override this though.
+if rm -f && rm -fr && rm -rf; then : OK; else
+ cat >&2 <<'END'
+Oops!
+
+Your 'rm' program seems unable to run without file operands specified
+on the command line, even when the '-f' option is present. This is contrary
+to the behaviour of most rm programs out there, and not conforming with
+the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>
+
+Please tell bug-automake@gnu.org about your system, including the value
+of your $PATH and any error possibly output before this message. This
+can help us improve future automake versions.
+
+END
+ if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
+ echo 'Configuration will proceed anyway, since you have set the' >&2
+ echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
+ echo >&2
+ else
+ cat >&2 <<'END'
+Aborting the configuration process, to ensure you take notice of the issue.
+
+You can download and install GNU coreutils to get an 'rm' implementation
+that behaves properly: <https://www.gnu.org/software/coreutils/>.
+
+If you want to complete the configuration process using your problematic
+'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
+to "yes", and re-run configure.
+
+END
+ as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5
+ fi
+fi
+
+
+ac_config_files="$ac_config_files Makefile agent/Makefile stun/Makefile stun/tests/Makefile stun/tools/Makefile socket/Makefile nice/Makefile nice/nice.pc random/Makefile gst/Makefile docs/Makefile docs/reference/Makefile docs/reference/libnice/Makefile tests/Makefile examples/Makefile"
+
+
+# Set the libtool C/A/R version info
+# If the source code was changed, but there were no interface changes:
+# Increment REVISION.
+# If there was a compatible interface change:
+# Increment CURRENT and AGE. Set REVISION to 0
+# If there was an incompatible interface change:
+# Increment CURRENT. Set AGE and REVISION to 0
+LIBNICE_CURRENT=19
+LIBNICE_REVISION=0
+LIBNICE_AGE=9
+LIBNICE_LIBVERSION=${LIBNICE_CURRENT}:${LIBNICE_REVISION}:${LIBNICE_AGE}
+LIBNICE_LT_LDFLAGS="-version-info ${LIBNICE_LIBVERSION} -no-undefined"
+
+
+# Check whether --enable-silent-rules was given.
+if test "${enable_silent_rules+set}" = set; then :
+ enableval=$enable_silent_rules;
+fi
+
+case $enable_silent_rules in # (((
+ yes) AM_DEFAULT_VERBOSITY=0;;
+ no) AM_DEFAULT_VERBOSITY=1;;
+ *) AM_DEFAULT_VERBOSITY=0;;
+esac
+am_make=${MAKE-make}
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5
+$as_echo_n "checking whether $am_make supports nested variables... " >&6; }
+if ${am_cv_make_support_nested_variables+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if $as_echo 'TRUE=$(BAR$(V))
+BAR0=false
+BAR1=true
+V=1
+am__doit:
+ @$(TRUE)
+.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then
+ am_cv_make_support_nested_variables=yes
+else
+ am_cv_make_support_nested_variables=no
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5
+$as_echo "$am_cv_make_support_nested_variables" >&6; }
+if test $am_cv_make_support_nested_variables = yes; then
+ AM_V='$(V)'
+ AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)'
+else
+ AM_V=$AM_DEFAULT_VERBOSITY
+ AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY
+fi
+AM_BACKSLASH='\'
+
+
+
+# Checks for programs.
+
+DEPDIR="${am__leading_dot}deps"
+
+ac_config_commands="$ac_config_commands depfiles"
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5
+$as_echo_n "checking whether ${MAKE-make} supports the include directive... " >&6; }
+cat > confinc.mk << 'END'
+am__doit:
+ @echo this is the am__doit target >confinc.out
+.PHONY: am__doit
+END
+am__include="#"
+am__quote=
+# BSD make does it like this.
+echo '.include "confinc.mk" # ignored' > confmf.BSD
+# Other make implementations (GNU, Solaris 10, AIX) do it like this.
+echo 'include confinc.mk # ignored' > confmf.GNU
+_am_result=no
+for s in GNU BSD; do
+ { echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5
+ (${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+ case $?:`cat confinc.out 2>/dev/null` in #(
+ '0:this is the am__doit target') :
+ case $s in #(
+ BSD) :
+ am__include='.include' am__quote='"' ;; #(
+ *) :
+ am__include='include' am__quote='' ;;
+esac ;; #(
+ *) :
+ ;;
+esac
+ if test "$am__include" != "#"; then
+ _am_result="yes ($s style)"
+ break
+ fi
+done
+rm -f confinc.* confmf.*
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5
+$as_echo "${_am_result}" >&6; }
+
+# Check whether --enable-dependency-tracking was given.
+if test "${enable_dependency_tracking+set}" = set; then :
+ enableval=$enable_dependency_tracking;
+fi
+
+if test "x$enable_dependency_tracking" != xno; then
+ am_depcomp="$ac_aux_dir/depcomp"
+ AMDEPBACKSLASH='\'
+ am__nodep='_no'
+fi
+ if test "x$enable_dependency_tracking" != xno; then
+ AMDEP_TRUE=
+ AMDEP_FALSE='#'
+else
+ AMDEP_TRUE='#'
+ AMDEP_FALSE=
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+if test -z "$ac_file"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+ { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if { ac_try='./conftest$ac_cv_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+else
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
+$as_echo_n "checking whether $CC understands -c and -o together... " >&6; }
+if ${am_cv_prog_cc_c_o+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ # Make sure it works both with $CC and with simple cc.
+ # Following AC_PROG_CC_C_O, we do the test twice because some
+ # compilers refuse to overwrite an existing .o file with -o,
+ # though they will create one.
+ am_cv_prog_cc_c_o=yes
+ for am_i in 1 2; do
+ if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5
+ ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } \
+ && test -f conftest2.$ac_objext; then
+ : OK
+ else
+ am_cv_prog_cc_c_o=no
+ break
+ fi
+ done
+ rm -f core conftest*
+ unset am_i
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
+$as_echo "$am_cv_prog_cc_c_o" >&6; }
+if test "$am_cv_prog_cc_c_o" != yes; then
+ # Losing compiler, so override with the script.
+ # FIXME: It is wrong to rewrite CC.
+ # But if we don't then we get into trouble of one sort or another.
+ # A longer-term fix would be to have automake use am__CC in this case,
+ # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+ CC="$am_aux_dir/compile $CC"
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+depcc="$CC" am_compiler_list=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if ${am_cv_CC_dependencies_compiler_type+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named 'D' -- because '-MD' means "put the output
+ # in D".
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_CC_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+ fi
+ am__universal=false
+ case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac
+
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
+ # Solaris 10 /bin/sh.
+ echo '/* dummy */' > sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ # We check with '-c' and '-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle '-M -o', and we need to detect this. Also, some Intel
+ # versions had trouble with output in subdirs.
+ am__obj=sub/conftest.${OBJEXT-o}
+ am__minus_obj="-o $am__obj"
+ case $depmode in
+ gcc)
+ # This depmode causes a compiler race in universal mode.
+ test "$am__universal" = false || continue
+ ;;
+ nosideeffect)
+ # After this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested.
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+ # This compiler won't grok '-c -o', but also, the minuso test has
+ # not run yet. These depmodes are late enough in the game, and
+ # so weak that their functioning should not be impacted.
+ am__obj=conftest.${OBJEXT-o}
+ am__minus_obj=
+ ;;
+ none) break ;;
+ esac
+ if depmode=$depmode \
+ source=sub/conftest.c object=$am__obj \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_CC_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+ am__fastdepCC_TRUE=
+ am__fastdepCC_FALSE='#'
+else
+ am__fastdepCC_TRUE='#'
+ am__fastdepCC_FALSE=
+fi
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if ${ac_cv_prog_CPP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$GREP"; then
+ ac_path_GREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in grep ggrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_GREP" || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_GREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_GREP"; then
+ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ if test -z "$EGREP"; then
+ ac_path_EGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in egrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_EGREP" || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_EGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_EGREP"; then
+ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_header_stdc=yes
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then :
+ :
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ return 2;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+ ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default"
+if test "x$ac_cv_header_minix_config_h" = xyes; then :
+ MINIX=yes
+else
+ MINIX=
+fi
+
+
+ if test "$MINIX" = yes; then
+
+$as_echo "#define _POSIX_SOURCE 1" >>confdefs.h
+
+
+$as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h
+
+
+$as_echo "#define _MINIX 1" >>confdefs.h
+
+ fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5
+$as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; }
+if ${ac_cv_safe_to_define___extensions__+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+# define __EXTENSIONS__ 1
+ $ac_includes_default
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_safe_to_define___extensions__=yes
+else
+ ac_cv_safe_to_define___extensions__=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5
+$as_echo "$ac_cv_safe_to_define___extensions__" >&6; }
+ test $ac_cv_safe_to_define___extensions__ = yes &&
+ $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h
+
+ $as_echo "#define _ALL_SOURCE 1" >>confdefs.h
+
+ $as_echo "#define _GNU_SOURCE 1" >>confdefs.h
+
+ $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h
+
+ $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+else
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
+$as_echo_n "checking whether $CC understands -c and -o together... " >&6; }
+if ${am_cv_prog_cc_c_o+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ # Make sure it works both with $CC and with simple cc.
+ # Following AC_PROG_CC_C_O, we do the test twice because some
+ # compilers refuse to overwrite an existing .o file with -o,
+ # though they will create one.
+ am_cv_prog_cc_c_o=yes
+ for am_i in 1 2; do
+ if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5
+ ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } \
+ && test -f conftest2.$ac_objext; then
+ : OK
+ else
+ am_cv_prog_cc_c_o=no
+ break
+ fi
+ done
+ rm -f core conftest*
+ unset am_i
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
+$as_echo "$am_cv_prog_cc_c_o" >&6; }
+if test "$am_cv_prog_cc_c_o" != yes; then
+ # Losing compiler, so override with the script.
+ # FIXME: It is wrong to rewrite CC.
+ # But if we don't then we get into trouble of one sort or another.
+ # A longer-term fix would be to have automake use am__CC in this case,
+ # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+ CC="$am_aux_dir/compile $CC"
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+depcc="$CC" am_compiler_list=
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if ${am_cv_CC_dependencies_compiler_type+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+ # We make a subdir and do the tests there. Otherwise we can end up
+ # making bogus files that we don't know about and never remove. For
+ # instance it was reported that on HP-UX the gcc test will end up
+ # making a dummy file named 'D' -- because '-MD' means "put the output
+ # in D".
+ rm -rf conftest.dir
+ mkdir conftest.dir
+ # Copy depcomp to subdir because otherwise we won't find it if we're
+ # using a relative directory.
+ cp "$am_depcomp" conftest.dir
+ cd conftest.dir
+ # We will build objects and dependencies in a subdirectory because
+ # it helps to detect inapplicable dependency modes. For instance
+ # both Tru64's cc and ICC support -MD to output dependencies as a
+ # side effect of compilation, but ICC will put the dependencies in
+ # the current directory while Tru64 will put them in the object
+ # directory.
+ mkdir sub
+
+ am_cv_CC_dependencies_compiler_type=none
+ if test "$am_compiler_list" = ""; then
+ am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+ fi
+ am__universal=false
+ case " $depcc " in #(
+ *\ -arch\ *\ -arch\ *) am__universal=true ;;
+ esac
+
+ for depmode in $am_compiler_list; do
+ # Setup a source with many dependencies, because some compilers
+ # like to wrap large dependency lists on column 80 (with \), and
+ # we should not choose a depcomp mode which is confused by this.
+ #
+ # We need to recreate these files for each test, as the compiler may
+ # overwrite some of them when testing with obscure command lines.
+ # This happens at least with the AIX C compiler.
+ : > sub/conftest.c
+ for i in 1 2 3 4 5 6; do
+ echo '#include "conftst'$i'.h"' >> sub/conftest.c
+ # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with
+ # Solaris 10 /bin/sh.
+ echo '/* dummy */' > sub/conftst$i.h
+ done
+ echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+ # We check with '-c' and '-o' for the sake of the "dashmstdout"
+ # mode. It turns out that the SunPro C++ compiler does not properly
+ # handle '-M -o', and we need to detect this. Also, some Intel
+ # versions had trouble with output in subdirs.
+ am__obj=sub/conftest.${OBJEXT-o}
+ am__minus_obj="-o $am__obj"
+ case $depmode in
+ gcc)
+ # This depmode causes a compiler race in universal mode.
+ test "$am__universal" = false || continue
+ ;;
+ nosideeffect)
+ # After this tag, mechanisms are not by side-effect, so they'll
+ # only be used when explicitly requested.
+ if test "x$enable_dependency_tracking" = xyes; then
+ continue
+ else
+ break
+ fi
+ ;;
+ msvc7 | msvc7msys | msvisualcpp | msvcmsys)
+ # This compiler won't grok '-c -o', but also, the minuso test has
+ # not run yet. These depmodes are late enough in the game, and
+ # so weak that their functioning should not be impacted.
+ am__obj=conftest.${OBJEXT-o}
+ am__minus_obj=
+ ;;
+ none) break ;;
+ esac
+ if depmode=$depmode \
+ source=sub/conftest.c object=$am__obj \
+ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+ >/dev/null 2>conftest.err &&
+ grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+ grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+ ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+ # icc doesn't choke on unknown options, it will just issue warnings
+ # or remarks (even with -Werror). So we grep stderr for any message
+ # that says an option was ignored or not supported.
+ # When given -MP, icc 7.0 and 7.1 complain thusly:
+ # icc: Command line warning: ignoring option '-M'; no argument required
+ # The diagnosis changed in icc 8.0:
+ # icc: Command line remark: option '-MP' not supported
+ if (grep 'ignoring option' conftest.err ||
+ grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+ am_cv_CC_dependencies_compiler_type=$depmode
+ break
+ fi
+ fi
+ done
+
+ cd ..
+ rm -rf conftest.dir
+else
+ am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+ test "x$enable_dependency_tracking" != xno \
+ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+ am__fastdepCC_TRUE=
+ am__fastdepCC_FALSE='#'
+else
+ am__fastdepCC_TRUE='#'
+ am__fastdepCC_FALSE=
+fi
+
+
+if test -n "$ac_tool_prefix"; then
+ for ac_prog in ar lib "link -lib"
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AR="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+$as_echo "$AR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$AR" && break
+ done
+fi
+if test -z "$AR"; then
+ ac_ct_AR=$AR
+ for ac_prog in ar lib "link -lib"
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_AR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_AR"; then
+ ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_AR="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+$as_echo "$ac_ct_AR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_AR" && break
+done
+
+ if test "x$ac_ct_AR" = x; then
+ AR="false"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ AR=$ac_ct_AR
+ fi
+fi
+
+: ${AR=ar}
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the archiver ($AR) interface" >&5
+$as_echo_n "checking the archiver ($AR) interface... " >&6; }
+if ${am_cv_ar_interface+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ am_cv_ar_interface=ar
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+int some_variable = 0;
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ am_ar_try='$AR cru libconftest.a conftest.$ac_objext >&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5
+ (eval $am_ar_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if test "$ac_status" -eq 0; then
+ am_cv_ar_interface=ar
+ else
+ am_ar_try='$AR -NOLOGO -OUT:conftest.lib conftest.$ac_objext >&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5
+ (eval $am_ar_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if test "$ac_status" -eq 0; then
+ am_cv_ar_interface=lib
+ else
+ am_cv_ar_interface=unknown
+ fi
+ fi
+ rm -f conftest.lib libconftest.a
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_ar_interface" >&5
+$as_echo "$am_cv_ar_interface" >&6; }
+
+case $am_cv_ar_interface in
+ar)
+ ;;
+lib)
+ # Microsoft lib, so override with the ar-lib wrapper script.
+ # FIXME: It is wrong to rewrite AR.
+ # But if we don't then we get into trouble of one sort or another.
+ # A longer-term fix would be to have automake use am__AR in this case,
+ # and then we could set am__AR="$am_aux_dir/ar-lib \$(AR)" or something
+ # similar.
+ AR="$am_aux_dir/ar-lib $AR"
+ ;;
+unknown)
+ as_fn_error $? "could not determine $AR interface" "$LINENO" 5
+ ;;
+esac
+
+
+case `pwd` in
+ *\ * | *\ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5
+$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;;
+esac
+
+
+
+macro_version='2.4.6'
+macro_revision='2.4.6'
+
+
+
+
+
+
+
+
+
+
+
+
+
+ltmain=$ac_aux_dir/ltmain.sh
+
+# Backslashify metacharacters that are still active within
+# double-quoted strings.
+sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\(["`\\]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to delay expansion of an escaped single quote.
+delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5
+$as_echo_n "checking how to print strings... " >&6; }
+# Test print first, because it will be a builtin if present.
+if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \
+ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
+ ECHO='print -r --'
+elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
+ ECHO='printf %s\n'
+else
+ # Use this function as a fallback that always works.
+ func_fallback_echo ()
+ {
+ eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+ }
+ ECHO='func_fallback_echo'
+fi
+
+# func_echo_all arg...
+# Invoke $ECHO with all args, space-separated.
+func_echo_all ()
+{
+ $ECHO ""
+}
+
+case $ECHO in
+ printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5
+$as_echo "printf" >&6; } ;;
+ print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5
+$as_echo "print -r" >&6; } ;;
+ *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5
+$as_echo "cat" >&6; } ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
+$as_echo_n "checking for a sed that does not truncate output... " >&6; }
+if ${ac_cv_path_SED+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
+ for ac_i in 1 2 3 4 5 6 7; do
+ ac_script="$ac_script$as_nl$ac_script"
+ done
+ echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed
+ { ac_script=; unset ac_script;}
+ if test -z "$SED"; then
+ ac_path_SED_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in sed gsed; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_SED="$as_dir/$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_SED" || continue
+# Check for GNU ac_path_SED and select it if it is found.
+ # Check for GNU $ac_path_SED
+case `"$ac_path_SED" --version 2>&1` in
+*GNU*)
+ ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo '' >> "conftest.nl"
+ "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_SED_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_SED="$ac_path_SED"
+ ac_path_SED_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_SED_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_SED"; then
+ as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5
+ fi
+else
+ ac_cv_path_SED=$SED
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5
+$as_echo "$ac_cv_path_SED" >&6; }
+ SED="$ac_cv_path_SED"
+ rm -f conftest.sed
+
+test -z "$SED" && SED=sed
+Xsed="$SED -e 1s/^X//"
+
+
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5
+$as_echo_n "checking for fgrep... " >&6; }
+if ${ac_cv_path_FGREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1
+ then ac_cv_path_FGREP="$GREP -F"
+ else
+ if test -z "$FGREP"; then
+ ac_path_FGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in fgrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_FGREP" || continue
+# Check for GNU ac_path_FGREP and select it if it is found.
+ # Check for GNU $ac_path_FGREP
+case `"$ac_path_FGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'FGREP' >> "conftest.nl"
+ "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_FGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_FGREP="$ac_path_FGREP"
+ ac_path_FGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_FGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_FGREP"; then
+ as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_FGREP=$FGREP
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5
+$as_echo "$ac_cv_path_FGREP" >&6; }
+ FGREP="$ac_cv_path_FGREP"
+
+
+test -z "$GREP" && GREP=grep
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Check whether --with-gnu-ld was given.
+if test "${with_gnu_ld+set}" = set; then :
+ withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes
+else
+ with_gnu_ld=no
+fi
+
+ac_prog=ld
+if test yes = "$GCC"; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5
+$as_echo_n "checking for ld used by $CC... " >&6; }
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return, which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [\\/]* | ?:[\\/]*)
+ re_direlt='/[^/][^/]*/\.\./'
+ # Canonicalize the pathname of ld
+ ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
+ while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD=$ac_prog
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test yes = "$with_gnu_ld"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5
+$as_echo_n "checking for GNU ld... " >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5
+$as_echo_n "checking for non-GNU ld... " >&6; }
+fi
+if ${lt_cv_path_LD+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$LD"; then
+ lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH; do
+ IFS=$lt_save_ifs
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ lt_cv_path_LD=$ac_dir/$ac_prog
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some variants of GNU ld only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+ *GNU* | *'with BFD'*)
+ test no != "$with_gnu_ld" && break
+ ;;
+ *)
+ test yes != "$with_gnu_ld" && break
+ ;;
+ esac
+ fi
+ done
+ IFS=$lt_save_ifs
+else
+ lt_cv_path_LD=$LD # Let the user override the test with a path.
+fi
+fi
+
+LD=$lt_cv_path_LD
+if test -n "$LD"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LD" >&5
+$as_echo "$LD" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5
+$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; }
+if ${lt_cv_prog_gnu_ld+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ lt_cv_prog_gnu_ld=yes
+ ;;
+*)
+ lt_cv_prog_gnu_ld=no
+ ;;
+esac
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_gnu_ld" >&5
+$as_echo "$lt_cv_prog_gnu_ld" >&6; }
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5
+$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; }
+if ${lt_cv_path_NM+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$NM"; then
+ # Let the user override the test.
+ lt_cv_path_NM=$NM
+else
+ lt_nm_to_check=${ac_tool_prefix}nm
+ if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+ lt_nm_to_check="$lt_nm_to_check nm"
+ fi
+ for lt_tmp_nm in $lt_nm_to_check; do
+ lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+ IFS=$lt_save_ifs
+ test -z "$ac_dir" && ac_dir=.
+ tmp_nm=$ac_dir/$lt_tmp_nm
+ if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then
+ # Check to see if the nm accepts a BSD-compat flag.
+ # Adding the 'sed 1q' prevents false positives on HP-UX, which says:
+ # nm: unknown option "B" ignored
+ # Tru64's nm complains that /dev/null is an invalid object file
+ # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty
+ case $build_os in
+ mingw*) lt_bad_file=conftest.nm/nofile ;;
+ *) lt_bad_file=/dev/null ;;
+ esac
+ case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in
+ *$lt_bad_file* | *'Invalid file or object type'*)
+ lt_cv_path_NM="$tmp_nm -B"
+ break 2
+ ;;
+ *)
+ case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+ */dev/null*)
+ lt_cv_path_NM="$tmp_nm -p"
+ break 2
+ ;;
+ *)
+ lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+ continue # so that we can try to find one that supports BSD flags
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ done
+ IFS=$lt_save_ifs
+ done
+ : ${lt_cv_path_NM=no}
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5
+$as_echo "$lt_cv_path_NM" >&6; }
+if test no != "$lt_cv_path_NM"; then
+ NM=$lt_cv_path_NM
+else
+ # Didn't find any BSD compatible name lister, look for dumpbin.
+ if test -n "$DUMPBIN"; then :
+ # Let the user override the test.
+ else
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in dumpbin "link -dump"
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_DUMPBIN+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$DUMPBIN"; then
+ ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+DUMPBIN=$ac_cv_prog_DUMPBIN
+if test -n "$DUMPBIN"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5
+$as_echo "$DUMPBIN" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$DUMPBIN" && break
+ done
+fi
+if test -z "$DUMPBIN"; then
+ ac_ct_DUMPBIN=$DUMPBIN
+ for ac_prog in dumpbin "link -dump"
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_DUMPBIN"; then
+ ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_DUMPBIN="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN
+if test -n "$ac_ct_DUMPBIN"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5
+$as_echo "$ac_ct_DUMPBIN" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_DUMPBIN" && break
+done
+
+ if test "x$ac_ct_DUMPBIN" = x; then
+ DUMPBIN=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ DUMPBIN=$ac_ct_DUMPBIN
+ fi
+fi
+
+ case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in
+ *COFF*)
+ DUMPBIN="$DUMPBIN -symbols -headers"
+ ;;
+ *)
+ DUMPBIN=:
+ ;;
+ esac
+ fi
+
+ if test : != "$DUMPBIN"; then
+ NM=$DUMPBIN
+ fi
+fi
+test -z "$NM" && NM=nm
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5
+$as_echo_n "checking the name lister ($NM) interface... " >&6; }
+if ${lt_cv_nm_interface+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_nm_interface="BSD nm"
+ echo "int some_variable = 0;" > conftest.$ac_ext
+ (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5)
+ (eval "$ac_compile" 2>conftest.err)
+ cat conftest.err >&5
+ (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+ (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
+ cat conftest.err >&5
+ (eval echo "\"\$as_me:$LINENO: output\"" >&5)
+ cat conftest.out >&5
+ if $GREP 'External.*some_variable' conftest.out > /dev/null; then
+ lt_cv_nm_interface="MS dumpbin"
+ fi
+ rm -f conftest*
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5
+$as_echo "$lt_cv_nm_interface" >&6; }
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
+$as_echo_n "checking whether ln -s works... " >&6; }
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
+$as_echo "no, using $LN_S" >&6; }
+fi
+
+# find the maximum length of command line arguments
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5
+$as_echo_n "checking the maximum length of command line arguments... " >&6; }
+if ${lt_cv_sys_max_cmd_len+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ i=0
+ teststring=ABCD
+
+ case $build_os in
+ msdosdjgpp*)
+ # On DJGPP, this test can blow up pretty badly due to problems in libc
+ # (any single argument exceeding 2000 bytes causes a buffer overrun
+ # during glob expansion). Even if it were fixed, the result of this
+ # check would be larger than it should be.
+ lt_cv_sys_max_cmd_len=12288; # 12K is about right
+ ;;
+
+ gnu*)
+ # Under GNU Hurd, this test is not required because there is
+ # no limit to the length of command line arguments.
+ # Libtool will interpret -1 as no limit whatsoever
+ lt_cv_sys_max_cmd_len=-1;
+ ;;
+
+ cygwin* | mingw* | cegcc*)
+ # On Win9x/ME, this test blows up -- it succeeds, but takes
+ # about 5 minutes as the teststring grows exponentially.
+ # Worse, since 9x/ME are not pre-emptively multitasking,
+ # you end up with a "frozen" computer, even though with patience
+ # the test eventually succeeds (with a max line length of 256k).
+ # Instead, let's just punt: use the minimum linelength reported by
+ # all of the supported platforms: 8192 (on NT/2K/XP).
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ mint*)
+ # On MiNT this can take a long time and run out of memory.
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ amigaos*)
+ # On AmigaOS with pdksh, this test takes hours, literally.
+ # So we just punt and use a minimum line length of 8192.
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*)
+ # This has been around since 386BSD, at least. Likely further.
+ if test -x /sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+ elif test -x /usr/sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+ else
+ lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs
+ fi
+ # And add a safety zone
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+ ;;
+
+ interix*)
+ # We know the value 262144 and hardcode it with a safety zone (like BSD)
+ lt_cv_sys_max_cmd_len=196608
+ ;;
+
+ os2*)
+ # The test takes a long time on OS/2.
+ lt_cv_sys_max_cmd_len=8192
+ ;;
+
+ osf*)
+ # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+ # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+ # nice to cause kernel panics so lets avoid the loop below.
+ # First set a reasonable default.
+ lt_cv_sys_max_cmd_len=16384
+ #
+ if test -x /sbin/sysconfig; then
+ case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+ *1*) lt_cv_sys_max_cmd_len=-1 ;;
+ esac
+ fi
+ ;;
+ sco3.2v5*)
+ lt_cv_sys_max_cmd_len=102400
+ ;;
+ sysv5* | sco5v6* | sysv4.2uw2*)
+ kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+ if test -n "$kargmax"; then
+ lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'`
+ else
+ lt_cv_sys_max_cmd_len=32768
+ fi
+ ;;
+ *)
+ lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
+ if test -n "$lt_cv_sys_max_cmd_len" && \
+ test undefined != "$lt_cv_sys_max_cmd_len"; then
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+ else
+ # Make teststring a little bigger before we do anything with it.
+ # a 1K string should be a reasonable start.
+ for i in 1 2 3 4 5 6 7 8; do
+ teststring=$teststring$teststring
+ done
+ SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+ # If test is not a shell built-in, we'll probably end up computing a
+ # maximum length that is only half of the actual maximum length, but
+ # we can't tell.
+ while { test X`env echo "$teststring$teststring" 2>/dev/null` \
+ = "X$teststring$teststring"; } >/dev/null 2>&1 &&
+ test 17 != "$i" # 1/2 MB should be enough
+ do
+ i=`expr $i + 1`
+ teststring=$teststring$teststring
+ done
+ # Only check the string length outside the loop.
+ lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
+ teststring=
+ # Add a significant safety factor because C++ compilers can tack on
+ # massive amounts of additional arguments before passing them to the
+ # linker. It appears as though 1/2 is a usable value.
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+ fi
+ ;;
+ esac
+
+fi
+
+if test -n "$lt_cv_sys_max_cmd_len"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5
+$as_echo "$lt_cv_sys_max_cmd_len" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5
+$as_echo "none" >&6; }
+fi
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+
+
+
+
+
+: ${CP="cp -f"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ lt_unset=unset
+else
+ lt_unset=false
+fi
+
+
+
+
+
+# test EBCDIC or ASCII
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+ # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+ lt_SP2NL='tr \040 \012'
+ lt_NL2SP='tr \015\012 \040\040'
+ ;;
+ *) # EBCDIC based system
+ lt_SP2NL='tr \100 \n'
+ lt_NL2SP='tr \r\n \100\100'
+ ;;
+esac
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5
+$as_echo_n "checking how to convert $build file names to $host format... " >&6; }
+if ${lt_cv_to_host_file_cmd+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $host in
+ *-*-mingw* )
+ case $build in
+ *-*-mingw* ) # actually msys
+ lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32
+ ;;
+ *-*-cygwin* )
+ lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32
+ ;;
+ * ) # otherwise, assume *nix
+ lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32
+ ;;
+ esac
+ ;;
+ *-*-cygwin* )
+ case $build in
+ *-*-mingw* ) # actually msys
+ lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin
+ ;;
+ *-*-cygwin* )
+ lt_cv_to_host_file_cmd=func_convert_file_noop
+ ;;
+ * ) # otherwise, assume *nix
+ lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin
+ ;;
+ esac
+ ;;
+ * ) # unhandled hosts (and "normal" native builds)
+ lt_cv_to_host_file_cmd=func_convert_file_noop
+ ;;
+esac
+
+fi
+
+to_host_file_cmd=$lt_cv_to_host_file_cmd
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5
+$as_echo "$lt_cv_to_host_file_cmd" >&6; }
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5
+$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; }
+if ${lt_cv_to_tool_file_cmd+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ #assume ordinary cross tools, or native build.
+lt_cv_to_tool_file_cmd=func_convert_file_noop
+case $host in
+ *-*-mingw* )
+ case $build in
+ *-*-mingw* ) # actually msys
+ lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32
+ ;;
+ esac
+ ;;
+esac
+
+fi
+
+to_tool_file_cmd=$lt_cv_to_tool_file_cmd
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5
+$as_echo "$lt_cv_to_tool_file_cmd" >&6; }
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5
+$as_echo_n "checking for $LD option to reload object files... " >&6; }
+if ${lt_cv_ld_reload_flag+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_ld_reload_flag='-r'
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5
+$as_echo "$lt_cv_ld_reload_flag" >&6; }
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+ cygwin* | mingw* | pw32* | cegcc*)
+ if test yes != "$GCC"; then
+ reload_cmds=false
+ fi
+ ;;
+ darwin*)
+ if test yes = "$GCC"; then
+ reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs'
+ else
+ reload_cmds='$LD$reload_flag -o $output$reload_objs'
+ fi
+ ;;
+esac
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args.
+set dummy ${ac_tool_prefix}objdump; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_OBJDUMP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$OBJDUMP"; then
+ ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+OBJDUMP=$ac_cv_prog_OBJDUMP
+if test -n "$OBJDUMP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5
+$as_echo "$OBJDUMP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OBJDUMP"; then
+ ac_ct_OBJDUMP=$OBJDUMP
+ # Extract the first word of "objdump", so it can be a program name with args.
+set dummy objdump; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_OBJDUMP"; then
+ ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_OBJDUMP="objdump"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP
+if test -n "$ac_ct_OBJDUMP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5
+$as_echo "$ac_ct_OBJDUMP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_OBJDUMP" = x; then
+ OBJDUMP="false"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ OBJDUMP=$ac_ct_OBJDUMP
+ fi
+else
+ OBJDUMP="$ac_cv_prog_OBJDUMP"
+fi
+
+test -z "$OBJDUMP" && OBJDUMP=objdump
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5
+$as_echo_n "checking how to recognize dependent libraries... " >&6; }
+if ${lt_cv_deplibs_check_method+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# 'unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# that responds to the $file_magic_cmd with a given extended regex.
+# If you have 'file' or equivalent on your system and you're not sure
+# whether 'pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix[4-9]*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+beos*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+bsdi[45]*)
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)'
+ lt_cv_file_magic_cmd='/usr/bin/file -L'
+ lt_cv_file_magic_test_file=/shlib/libc.so
+ ;;
+
+cygwin*)
+ # func_win32_libid is a shell function defined in ltmain.sh
+ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+ lt_cv_file_magic_cmd='func_win32_libid'
+ ;;
+
+mingw* | pw32*)
+ # Base MSYS/MinGW do not provide the 'file' command needed by
+ # func_win32_libid shell function, so use a weaker test based on 'objdump',
+ # unless we find 'file', for example because we are cross-compiling.
+ if ( file / ) >/dev/null 2>&1; then
+ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+ lt_cv_file_magic_cmd='func_win32_libid'
+ else
+ # Keep this pattern in sync with the one in func_win32_libid.
+ lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)'
+ lt_cv_file_magic_cmd='$OBJDUMP -f'
+ fi
+ ;;
+
+cegcc*)
+ # use the weaker test based on 'objdump'. See mingw*.
+ lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
+ lt_cv_file_magic_cmd='$OBJDUMP -f'
+ ;;
+
+darwin* | rhapsody*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+freebsd* | dragonfly*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+ case $host_cpu in
+ i*86 )
+ # Not sure whether the presence of OpenBSD here was a mistake.
+ # Let's accept both of them until this is cleared up.
+ lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+ ;;
+ esac
+ else
+ lt_cv_deplibs_check_method=pass_all
+ fi
+ ;;
+
+haiku*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+hpux10.20* | hpux11*)
+ lt_cv_file_magic_cmd=/usr/bin/file
+ case $host_cpu in
+ ia64*)
+ lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64'
+ lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+ ;;
+ hppa*64*)
+ lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'
+ lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+ ;;
+ *)
+ lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library'
+ lt_cv_file_magic_test_file=/usr/lib/libc.sl
+ ;;
+ esac
+ ;;
+
+interix[3-9]*)
+ # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$'
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $LD in
+ *-32|*"-32 ") libmagic=32-bit;;
+ *-n32|*"-n32 ") libmagic=N32;;
+ *-64|*"-64 ") libmagic=64-bit;;
+ *) libmagic=never-match;;
+ esac
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+# This must be glibc/ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+netbsd*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$'
+ fi
+ ;;
+
+newos6*)
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=/usr/lib/libnls.so
+ ;;
+
+*nto* | *qnx*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+openbsd* | bitrig*)
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
+ fi
+ ;;
+
+osf3* | osf4* | osf5*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+rdos*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+solaris*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+sysv4 | sysv4.3*)
+ case $host_vendor in
+ motorola)
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]'
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+ ;;
+ ncr)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ sequent)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )'
+ ;;
+ sni)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib"
+ lt_cv_file_magic_test_file=/lib/libc.so
+ ;;
+ siemens)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ pc)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ esac
+ ;;
+
+tpf*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+os2*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+esac
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5
+$as_echo "$lt_cv_deplibs_check_method" >&6; }
+
+file_magic_glob=
+want_nocaseglob=no
+if test "$build" = "$host"; then
+ case $host_os in
+ mingw* | pw32*)
+ if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then
+ want_nocaseglob=yes
+ else
+ file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"`
+ fi
+ ;;
+ esac
+fi
+
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args.
+set dummy ${ac_tool_prefix}dlltool; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_DLLTOOL+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$DLLTOOL"; then
+ ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+DLLTOOL=$ac_cv_prog_DLLTOOL
+if test -n "$DLLTOOL"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5
+$as_echo "$DLLTOOL" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_DLLTOOL"; then
+ ac_ct_DLLTOOL=$DLLTOOL
+ # Extract the first word of "dlltool", so it can be a program name with args.
+set dummy dlltool; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_DLLTOOL"; then
+ ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_DLLTOOL="dlltool"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL
+if test -n "$ac_ct_DLLTOOL"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5
+$as_echo "$ac_ct_DLLTOOL" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_DLLTOOL" = x; then
+ DLLTOOL="false"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ DLLTOOL=$ac_ct_DLLTOOL
+ fi
+else
+ DLLTOOL="$ac_cv_prog_DLLTOOL"
+fi
+
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5
+$as_echo_n "checking how to associate runtime and link libraries... " >&6; }
+if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_sharedlib_from_linklib_cmd='unknown'
+
+case $host_os in
+cygwin* | mingw* | pw32* | cegcc*)
+ # two different shell functions defined in ltmain.sh;
+ # decide which one to use based on capabilities of $DLLTOOL
+ case `$DLLTOOL --help 2>&1` in
+ *--identify-strict*)
+ lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib
+ ;;
+ *)
+ lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback
+ ;;
+ esac
+ ;;
+*)
+ # fallback: assume linklib IS sharedlib
+ lt_cv_sharedlib_from_linklib_cmd=$ECHO
+ ;;
+esac
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5
+$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; }
+sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd
+test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+ for ac_prog in ar
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AR="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+$as_echo "$AR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$AR" && break
+ done
+fi
+if test -z "$AR"; then
+ ac_ct_AR=$AR
+ for ac_prog in ar
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_AR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_AR"; then
+ ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_AR="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+$as_echo "$ac_ct_AR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_AR" && break
+done
+
+ if test "x$ac_ct_AR" = x; then
+ AR="false"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ AR=$ac_ct_AR
+ fi
+fi
+
+: ${AR=ar}
+: ${AR_FLAGS=cru}
+
+
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5
+$as_echo_n "checking for archiver @FILE support... " >&6; }
+if ${lt_cv_ar_at_file+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_ar_at_file=no
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ echo conftest.$ac_objext > conftest.lst
+ lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5
+ (eval $lt_ar_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if test 0 -eq "$ac_status"; then
+ # Ensure the archiver fails upon bogus file names.
+ rm -f conftest.$ac_objext libconftest.a
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5
+ (eval $lt_ar_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if test 0 -ne "$ac_status"; then
+ lt_cv_ar_at_file=@
+ fi
+ fi
+ rm -f conftest.* libconftest.a
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5
+$as_echo "$lt_cv_ar_at_file" >&6; }
+
+if test no = "$lt_cv_ar_at_file"; then
+ archiver_list_spec=
+else
+ archiver_list_spec=$lt_cv_ar_at_file
+fi
+
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_STRIP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$STRIP"; then
+ ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+ ac_ct_STRIP=$STRIP
+ # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_STRIP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_STRIP"; then
+ ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_STRIP="strip"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5
+$as_echo "$ac_ct_STRIP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_STRIP" = x; then
+ STRIP=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ STRIP=$ac_ct_STRIP
+ fi
+else
+ STRIP="$ac_cv_prog_STRIP"
+fi
+
+test -z "$STRIP" && STRIP=:
+
+
+
+
+
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_RANLIB+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+ ac_ct_RANLIB=$RANLIB
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_RANLIB"; then
+ ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_RANLIB="ranlib"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_RANLIB" = x; then
+ RANLIB=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ RANLIB=$ac_ct_RANLIB
+ fi
+else
+ RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+test -z "$RANLIB" && RANLIB=:
+
+
+
+
+
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+ case $host_os in
+ bitrig* | openbsd*)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib"
+ ;;
+ *)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib"
+ ;;
+ esac
+ old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib"
+fi
+
+case $host_os in
+ darwin*)
+ lock_old_archive_extraction=yes ;;
+ *)
+ lock_old_archive_extraction=no ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5
+$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; }
+if ${lt_cv_sys_global_symbol_pipe+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix. What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[BCDEGRST]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([_A-Za-z][_A-Za-z0-9]*\)'
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+ symcode='[BCDT]'
+ ;;
+cygwin* | mingw* | pw32* | cegcc*)
+ symcode='[ABCDGISTW]'
+ ;;
+hpux*)
+ if test ia64 = "$host_cpu"; then
+ symcode='[ABCDEGRST]'
+ fi
+ ;;
+irix* | nonstopux*)
+ symcode='[BCDEGRST]'
+ ;;
+osf*)
+ symcode='[BCDEGQRST]'
+ ;;
+solaris*)
+ symcode='[BDRT]'
+ ;;
+sco3.2v5*)
+ symcode='[DT]'
+ ;;
+sysv4.2uw2*)
+ symcode='[DT]'
+ ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+ symcode='[ABDT]'
+ ;;
+sysv4)
+ symcode='[DFNSTU]'
+ ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+ symcode='[ABCDGIRSTW]' ;;
+esac
+
+if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+ # Gets list of data symbols to import.
+ lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'"
+ # Adjust the below global symbol transforms to fixup imported variables.
+ lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'"
+ lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'"
+ lt_c_name_lib_hook="\
+ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\
+ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'"
+else
+ # Disable hooks by default.
+ lt_cv_sys_global_symbol_to_import=
+ lt_cdecl_hook=
+ lt_c_name_hook=
+ lt_c_name_lib_hook=
+fi
+
+# Transform an extracted symbol line into a proper C declaration.
+# Some systems (esp. on ia64) link data and code symbols differently,
+# so use this general approach.
+lt_cv_sys_global_symbol_to_cdecl="sed -n"\
+$lt_cdecl_hook\
+" -e 's/^T .* \(.*\)$/extern int \1();/p'"\
+" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n"\
+$lt_c_name_hook\
+" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\
+" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'"
+
+# Transform an extracted symbol line into symbol name with lib prefix and
+# symbol address.
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\
+$lt_c_name_lib_hook\
+" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\
+" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\
+" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'"
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+ opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+ ;;
+esac
+
+# Try without a prefix underscore, then with it.
+for ac_symprfx in "" "_"; do
+
+ # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+ symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+ # Write the raw and C identifiers.
+ if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+ # Fake it for dumpbin and say T for any non-static function,
+ # D for any global variable and I for any imported variable.
+ # Also find C++ and __fastcall symbols from MSVC++,
+ # which start with @ or ?.
+ lt_cv_sys_global_symbol_pipe="$AWK '"\
+" {last_section=section; section=\$ 3};"\
+" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\
+" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
+" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\
+" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\
+" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\
+" \$ 0!~/External *\|/{next};"\
+" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
+" {if(hide[section]) next};"\
+" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\
+" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\
+" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\
+" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\
+" ' prfx=^$ac_symprfx"
+ else
+ lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+ fi
+ lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'"
+
+ # Check to see that the pipe works correctly.
+ pipe_works=no
+
+ rm -f conftest*
+ cat > conftest.$ac_ext <<_LT_EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(void);
+void nm_test_func(void){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+_LT_EOF
+
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ # Now try to grab the symbols.
+ nlist=conftest.nm
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5
+ (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && test -s "$nlist"; then
+ # Try sorting and uniquifying the output.
+ if sort "$nlist" | uniq > "$nlist"T; then
+ mv -f "$nlist"T "$nlist"
+ else
+ rm -f "$nlist"T
+ fi
+
+ # Make sure that we snagged all the symbols we need.
+ if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
+ if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
+ cat <<_LT_EOF > conftest.$ac_ext
+/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */
+#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE
+/* DATA imports from DLLs on WIN32 can't be const, because runtime
+ relocations are performed -- see ld's documentation on pseudo-relocs. */
+# define LT_DLSYM_CONST
+#elif defined __osf__
+/* This system does not cope well with relocations in const data. */
+# define LT_DLSYM_CONST
+#else
+# define LT_DLSYM_CONST const
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+_LT_EOF
+ # Now generate the symbol file.
+ eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
+
+ cat <<_LT_EOF >> conftest.$ac_ext
+
+/* The mapping between symbol names and symbols. */
+LT_DLSYM_CONST struct {
+ const char *name;
+ void *address;
+}
+lt__PROGRAM__LTX_preloaded_symbols[] =
+{
+ { "@PROGRAM@", (void *) 0 },
+_LT_EOF
+ $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
+ cat <<\_LT_EOF >> conftest.$ac_ext
+ {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+ return lt__PROGRAM__LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+_LT_EOF
+ # Now try linking the two files.
+ mv conftest.$ac_objext conftstm.$ac_objext
+ lt_globsym_save_LIBS=$LIBS
+ lt_globsym_save_CFLAGS=$CFLAGS
+ LIBS=conftstm.$ac_objext
+ CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag"
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && test -s conftest$ac_exeext; then
+ pipe_works=yes
+ fi
+ LIBS=$lt_globsym_save_LIBS
+ CFLAGS=$lt_globsym_save_CFLAGS
+ else
+ echo "cannot find nm_test_func in $nlist" >&5
+ fi
+ else
+ echo "cannot find nm_test_var in $nlist" >&5
+ fi
+ else
+ echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5
+ fi
+ else
+ echo "$progname: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ fi
+ rm -rf conftest* conftst*
+
+ # Do not use the global_symbol_pipe unless it works.
+ if test yes = "$pipe_works"; then
+ break
+ else
+ lt_cv_sys_global_symbol_pipe=
+ fi
+done
+
+fi
+
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+ lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5
+$as_echo "failed" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
+$as_echo "ok" >&6; }
+fi
+
+# Response file support.
+if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+ nm_file_list_spec='@'
+elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then
+ nm_file_list_spec='@'
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5
+$as_echo_n "checking for sysroot... " >&6; }
+
+# Check whether --with-sysroot was given.
+if test "${with_sysroot+set}" = set; then :
+ withval=$with_sysroot;
+else
+ with_sysroot=no
+fi
+
+
+lt_sysroot=
+case $with_sysroot in #(
+ yes)
+ if test yes = "$GCC"; then
+ lt_sysroot=`$CC --print-sysroot 2>/dev/null`
+ fi
+ ;; #(
+ /*)
+ lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"`
+ ;; #(
+ no|'')
+ ;; #(
+ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5
+$as_echo "$with_sysroot" >&6; }
+ as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5
+ ;;
+esac
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5
+$as_echo "${lt_sysroot:-no}" >&6; }
+
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5
+$as_echo_n "checking for a working dd... " >&6; }
+if ${ac_cv_path_lt_DD+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ printf 0123456789abcdef0123456789abcdef >conftest.i
+cat conftest.i conftest.i >conftest2.i
+: ${lt_DD:=$DD}
+if test -z "$lt_DD"; then
+ ac_path_lt_DD_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in dd; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_lt_DD="$as_dir/$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_lt_DD" || continue
+if "$ac_path_lt_DD" bs=32 count=1 <conftest2.i >conftest.out 2>/dev/null; then
+ cmp -s conftest.i conftest.out \
+ && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=:
+fi
+ $ac_path_lt_DD_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_lt_DD"; then
+ :
+ fi
+else
+ ac_cv_path_lt_DD=$lt_DD
+fi
+
+rm -f conftest.i conftest2.i conftest.out
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5
+$as_echo "$ac_cv_path_lt_DD" >&6; }
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5
+$as_echo_n "checking how to truncate binary pipes... " >&6; }
+if ${lt_cv_truncate_bin+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ printf 0123456789abcdef0123456789abcdef >conftest.i
+cat conftest.i conftest.i >conftest2.i
+lt_cv_truncate_bin=
+if "$ac_cv_path_lt_DD" bs=32 count=1 <conftest2.i >conftest.out 2>/dev/null; then
+ cmp -s conftest.i conftest.out \
+ && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1"
+fi
+rm -f conftest.i conftest2.i conftest.out
+test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5
+$as_echo "$lt_cv_truncate_bin" >&6; }
+
+
+
+
+
+
+
+# Calculate cc_basename. Skip known compiler wrappers and cross-prefix.
+func_cc_basename ()
+{
+ for cc_temp in $*""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+ done
+ func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+}
+
+# Check whether --enable-libtool-lock was given.
+if test "${enable_libtool_lock+set}" = set; then :
+ enableval=$enable_libtool_lock;
+fi
+
+test no = "$enable_libtool_lock" || enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+ # Find out what ABI is being produced by ac_compile, and set mode
+ # options accordingly.
+ echo 'int i;' > conftest.$ac_ext
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *ELF-32*)
+ HPUX_IA64_MODE=32
+ ;;
+ *ELF-64*)
+ HPUX_IA64_MODE=64
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+*-*-irix6*)
+ # Find out what ABI is being produced by ac_compile, and set linker
+ # options accordingly.
+ echo '#line '$LINENO' "configure"' > conftest.$ac_ext
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ if test yes = "$lt_cv_prog_gnu_ld"; then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -melf32bsmip"
+ ;;
+ *N32*)
+ LD="${LD-ld} -melf32bmipn32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -melf64bmip"
+ ;;
+ esac
+ else
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -32"
+ ;;
+ *N32*)
+ LD="${LD-ld} -n32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -64"
+ ;;
+ esac
+ fi
+ fi
+ rm -rf conftest*
+ ;;
+
+mips64*-*linux*)
+ # Find out what ABI is being produced by ac_compile, and set linker
+ # options accordingly.
+ echo '#line '$LINENO' "configure"' > conftest.$ac_ext
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ emul=elf
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ emul="${emul}32"
+ ;;
+ *64-bit*)
+ emul="${emul}64"
+ ;;
+ esac
+ case `/usr/bin/file conftest.$ac_objext` in
+ *MSB*)
+ emul="${emul}btsmip"
+ ;;
+ *LSB*)
+ emul="${emul}ltsmip"
+ ;;
+ esac
+ case `/usr/bin/file conftest.$ac_objext` in
+ *N32*)
+ emul="${emul}n32"
+ ;;
+ esac
+ LD="${LD-ld} -m $emul"
+ fi
+ rm -rf conftest*
+ ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
+s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
+ # Find out what ABI is being produced by ac_compile, and set linker
+ # options accordingly. Note that the listed cases only cover the
+ # situations where additional linker options are needed (such as when
+ # doing 32-bit compilation for a host where ld defaults to 64-bit, or
+ # vice versa); the common cases where no linker options are needed do
+ # not appear in the list.
+ echo 'int i;' > conftest.$ac_ext
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ case `/usr/bin/file conftest.o` in
+ *32-bit*)
+ case $host in
+ x86_64-*kfreebsd*-gnu)
+ LD="${LD-ld} -m elf_i386_fbsd"
+ ;;
+ x86_64-*linux*)
+ case `/usr/bin/file conftest.o` in
+ *x86-64*)
+ LD="${LD-ld} -m elf32_x86_64"
+ ;;
+ *)
+ LD="${LD-ld} -m elf_i386"
+ ;;
+ esac
+ ;;
+ powerpc64le-*linux*)
+ LD="${LD-ld} -m elf32lppclinux"
+ ;;
+ powerpc64-*linux*)
+ LD="${LD-ld} -m elf32ppclinux"
+ ;;
+ s390x-*linux*)
+ LD="${LD-ld} -m elf_s390"
+ ;;
+ sparc64-*linux*)
+ LD="${LD-ld} -m elf32_sparc"
+ ;;
+ esac
+ ;;
+ *64-bit*)
+ case $host in
+ x86_64-*kfreebsd*-gnu)
+ LD="${LD-ld} -m elf_x86_64_fbsd"
+ ;;
+ x86_64-*linux*)
+ LD="${LD-ld} -m elf_x86_64"
+ ;;
+ powerpcle-*linux*)
+ LD="${LD-ld} -m elf64lppc"
+ ;;
+ powerpc-*linux*)
+ LD="${LD-ld} -m elf64ppc"
+ ;;
+ s390*-*linux*|s390*-*tpf*)
+ LD="${LD-ld} -m elf64_s390"
+ ;;
+ sparc*-*linux*)
+ LD="${LD-ld} -m elf64_sparc"
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+
+*-*-sco3.2v5*)
+ # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+ SAVE_CFLAGS=$CFLAGS
+ CFLAGS="$CFLAGS -belf"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5
+$as_echo_n "checking whether the C compiler needs -belf... " >&6; }
+if ${lt_cv_cc_needs_belf+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ lt_cv_cc_needs_belf=yes
+else
+ lt_cv_cc_needs_belf=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5
+$as_echo "$lt_cv_cc_needs_belf" >&6; }
+ if test yes != "$lt_cv_cc_needs_belf"; then
+ # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+ CFLAGS=$SAVE_CFLAGS
+ fi
+ ;;
+*-*solaris*)
+ # Find out what ABI is being produced by ac_compile, and set linker
+ # options accordingly.
+ echo 'int i;' > conftest.$ac_ext
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ case `/usr/bin/file conftest.o` in
+ *64-bit*)
+ case $lt_cv_prog_gnu_ld in
+ yes*)
+ case $host in
+ i?86-*-solaris*|x86_64-*-solaris*)
+ LD="${LD-ld} -m elf_x86_64"
+ ;;
+ sparc*-*-solaris*)
+ LD="${LD-ld} -m elf64_sparc"
+ ;;
+ esac
+ # GNU ld 2.21 introduced _sol2 emulations. Use them if available.
+ if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then
+ LD=${LD-ld}_sol2
+ fi
+ ;;
+ *)
+ if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
+ LD="${LD-ld} -64"
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+esac
+
+need_locks=$enable_libtool_lock
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args.
+set dummy ${ac_tool_prefix}mt; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_MANIFEST_TOOL+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$MANIFEST_TOOL"; then
+ ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL
+if test -n "$MANIFEST_TOOL"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5
+$as_echo "$MANIFEST_TOOL" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_MANIFEST_TOOL"; then
+ ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL
+ # Extract the first word of "mt", so it can be a program name with args.
+set dummy mt; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_MANIFEST_TOOL"; then
+ ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_MANIFEST_TOOL="mt"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL
+if test -n "$ac_ct_MANIFEST_TOOL"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5
+$as_echo "$ac_ct_MANIFEST_TOOL" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_MANIFEST_TOOL" = x; then
+ MANIFEST_TOOL=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL
+ fi
+else
+ MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL"
+fi
+
+test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5
+$as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; }
+if ${lt_cv_path_mainfest_tool+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_path_mainfest_tool=no
+ echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5
+ $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out
+ cat conftest.err >&5
+ if $GREP 'Manifest Tool' conftest.out > /dev/null; then
+ lt_cv_path_mainfest_tool=yes
+ fi
+ rm -f conftest*
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5
+$as_echo "$lt_cv_path_mainfest_tool" >&6; }
+if test yes != "$lt_cv_path_mainfest_tool"; then
+ MANIFEST_TOOL=:
+fi
+
+
+
+
+
+
+ case $host_os in
+ rhapsody* | darwin*)
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args.
+set dummy ${ac_tool_prefix}dsymutil; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_DSYMUTIL+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$DSYMUTIL"; then
+ ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+DSYMUTIL=$ac_cv_prog_DSYMUTIL
+if test -n "$DSYMUTIL"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5
+$as_echo "$DSYMUTIL" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_DSYMUTIL"; then
+ ac_ct_DSYMUTIL=$DSYMUTIL
+ # Extract the first word of "dsymutil", so it can be a program name with args.
+set dummy dsymutil; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_DSYMUTIL"; then
+ ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_DSYMUTIL="dsymutil"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL
+if test -n "$ac_ct_DSYMUTIL"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5
+$as_echo "$ac_ct_DSYMUTIL" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_DSYMUTIL" = x; then
+ DSYMUTIL=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ DSYMUTIL=$ac_ct_DSYMUTIL
+ fi
+else
+ DSYMUTIL="$ac_cv_prog_DSYMUTIL"
+fi
+
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args.
+set dummy ${ac_tool_prefix}nmedit; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_NMEDIT+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$NMEDIT"; then
+ ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+NMEDIT=$ac_cv_prog_NMEDIT
+if test -n "$NMEDIT"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5
+$as_echo "$NMEDIT" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_NMEDIT"; then
+ ac_ct_NMEDIT=$NMEDIT
+ # Extract the first word of "nmedit", so it can be a program name with args.
+set dummy nmedit; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_NMEDIT"; then
+ ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_NMEDIT="nmedit"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT
+if test -n "$ac_ct_NMEDIT"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5
+$as_echo "$ac_ct_NMEDIT" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_NMEDIT" = x; then
+ NMEDIT=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ NMEDIT=$ac_ct_NMEDIT
+ fi
+else
+ NMEDIT="$ac_cv_prog_NMEDIT"
+fi
+
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args.
+set dummy ${ac_tool_prefix}lipo; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_LIPO+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$LIPO"; then
+ ac_cv_prog_LIPO="$LIPO" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_LIPO="${ac_tool_prefix}lipo"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+LIPO=$ac_cv_prog_LIPO
+if test -n "$LIPO"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5
+$as_echo "$LIPO" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_LIPO"; then
+ ac_ct_LIPO=$LIPO
+ # Extract the first word of "lipo", so it can be a program name with args.
+set dummy lipo; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_LIPO+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_LIPO"; then
+ ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_LIPO="lipo"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO
+if test -n "$ac_ct_LIPO"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5
+$as_echo "$ac_ct_LIPO" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_LIPO" = x; then
+ LIPO=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ LIPO=$ac_ct_LIPO
+ fi
+else
+ LIPO="$ac_cv_prog_LIPO"
+fi
+
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args.
+set dummy ${ac_tool_prefix}otool; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_OTOOL+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$OTOOL"; then
+ ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_OTOOL="${ac_tool_prefix}otool"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+OTOOL=$ac_cv_prog_OTOOL
+if test -n "$OTOOL"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5
+$as_echo "$OTOOL" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OTOOL"; then
+ ac_ct_OTOOL=$OTOOL
+ # Extract the first word of "otool", so it can be a program name with args.
+set dummy otool; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_OTOOL+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_OTOOL"; then
+ ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_OTOOL="otool"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL
+if test -n "$ac_ct_OTOOL"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5
+$as_echo "$ac_ct_OTOOL" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_OTOOL" = x; then
+ OTOOL=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ OTOOL=$ac_ct_OTOOL
+ fi
+else
+ OTOOL="$ac_cv_prog_OTOOL"
+fi
+
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args.
+set dummy ${ac_tool_prefix}otool64; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_OTOOL64+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$OTOOL64"; then
+ ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+OTOOL64=$ac_cv_prog_OTOOL64
+if test -n "$OTOOL64"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5
+$as_echo "$OTOOL64" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OTOOL64"; then
+ ac_ct_OTOOL64=$OTOOL64
+ # Extract the first word of "otool64", so it can be a program name with args.
+set dummy otool64; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_OTOOL64"; then
+ ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_OTOOL64="otool64"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64
+if test -n "$ac_ct_OTOOL64"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5
+$as_echo "$ac_ct_OTOOL64" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_OTOOL64" = x; then
+ OTOOL64=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ OTOOL64=$ac_ct_OTOOL64
+ fi
+else
+ OTOOL64="$ac_cv_prog_OTOOL64"
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5
+$as_echo_n "checking for -single_module linker flag... " >&6; }
+if ${lt_cv_apple_cc_single_mod+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_apple_cc_single_mod=no
+ if test -z "$LT_MULTI_MODULE"; then
+ # By default we will add the -single_module flag. You can override
+ # by either setting the environment variable LT_MULTI_MODULE
+ # non-empty at configure time, or by adding -multi_module to the
+ # link flags.
+ rm -rf libconftest.dylib*
+ echo "int foo(void){return 1;}" > conftest.c
+ echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+-dynamiclib -Wl,-single_module conftest.c" >&5
+ $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
+ _lt_result=$?
+ # If there is a non-empty error log, and "single_module"
+ # appears in it, assume the flag caused a linker warning
+ if test -s conftest.err && $GREP single_module conftest.err; then
+ cat conftest.err >&5
+ # Otherwise, if the output was created with a 0 exit code from
+ # the compiler, it worked.
+ elif test -f libconftest.dylib && test 0 = "$_lt_result"; then
+ lt_cv_apple_cc_single_mod=yes
+ else
+ cat conftest.err >&5
+ fi
+ rm -rf libconftest.dylib*
+ rm -f conftest.*
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5
+$as_echo "$lt_cv_apple_cc_single_mod" >&6; }
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5
+$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; }
+if ${lt_cv_ld_exported_symbols_list+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_ld_exported_symbols_list=no
+ save_LDFLAGS=$LDFLAGS
+ echo "_main" > conftest.sym
+ LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ lt_cv_ld_exported_symbols_list=yes
+else
+ lt_cv_ld_exported_symbols_list=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$save_LDFLAGS
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5
+$as_echo "$lt_cv_ld_exported_symbols_list" >&6; }
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5
+$as_echo_n "checking for -force_load linker flag... " >&6; }
+if ${lt_cv_ld_force_load+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_ld_force_load=no
+ cat > conftest.c << _LT_EOF
+int forced_loaded() { return 2;}
+_LT_EOF
+ echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5
+ $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5
+ echo "$AR cru libconftest.a conftest.o" >&5
+ $AR cru libconftest.a conftest.o 2>&5
+ echo "$RANLIB libconftest.a" >&5
+ $RANLIB libconftest.a 2>&5
+ cat > conftest.c << _LT_EOF
+int main() { return 0;}
+_LT_EOF
+ echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5
+ $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err
+ _lt_result=$?
+ if test -s conftest.err && $GREP force_load conftest.err; then
+ cat conftest.err >&5
+ elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then
+ lt_cv_ld_force_load=yes
+ else
+ cat conftest.err >&5
+ fi
+ rm -f conftest.err libconftest.a conftest conftest.c
+ rm -rf conftest.dSYM
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5
+$as_echo "$lt_cv_ld_force_load" >&6; }
+ case $host_os in
+ rhapsody* | darwin1.[012])
+ _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;;
+ darwin1.*)
+ _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
+ darwin*) # darwin 5.x on
+ # if running on 10.5 or later, the deployment target defaults
+ # to the OS version, if on x86, and 10.4, the deployment
+ # target defaults to 10.4. Don't you love it?
+ case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
+ 10.0,*86*-darwin8*|10.0,*-darwin[91]*)
+ _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
+ 10.[012][,.]*)
+ _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
+ 10.*)
+ _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
+ esac
+ ;;
+ esac
+ if test yes = "$lt_cv_apple_cc_single_mod"; then
+ _lt_dar_single_mod='$single_module'
+ fi
+ if test yes = "$lt_cv_ld_exported_symbols_list"; then
+ _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym'
+ else
+ _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib'
+ fi
+ if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then
+ _lt_dsymutil='~$DSYMUTIL $lib || :'
+ else
+ _lt_dsymutil=
+ fi
+ ;;
+ esac
+
+# func_munge_path_list VARIABLE PATH
+# -----------------------------------
+# VARIABLE is name of variable containing _space_ separated list of
+# directories to be munged by the contents of PATH, which is string
+# having a format:
+# "DIR[:DIR]:"
+# string "DIR[ DIR]" will be prepended to VARIABLE
+# ":DIR[:DIR]"
+# string "DIR[ DIR]" will be appended to VARIABLE
+# "DIRP[:DIRP]::[DIRA:]DIRA"
+# string "DIRP[ DIRP]" will be prepended to VARIABLE and string
+# "DIRA[ DIRA]" will be appended to VARIABLE
+# "DIR[:DIR]"
+# VARIABLE will be replaced by "DIR[ DIR]"
+func_munge_path_list ()
+{
+ case x$2 in
+ x)
+ ;;
+ *:)
+ eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\"
+ ;;
+ x:*)
+ eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\"
+ ;;
+ *::*)
+ eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\"
+ eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\"
+ ;;
+ *)
+ eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\"
+ ;;
+ esac
+}
+
+for ac_header in dlfcn.h
+do :
+ ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default
+"
+if test "x$ac_cv_header_dlfcn_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_DLFCN_H 1
+_ACEOF
+
+fi
+
+done
+
+
+
+
+
+# Set options
+enable_dlopen=yes
+enable_win32_dll=yes
+
+case $host in
+*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*)
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args.
+set dummy ${ac_tool_prefix}as; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AS+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$AS"; then
+ ac_cv_prog_AS="$AS" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AS="${ac_tool_prefix}as"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+AS=$ac_cv_prog_AS
+if test -n "$AS"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AS" >&5
+$as_echo "$AS" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_AS"; then
+ ac_ct_AS=$AS
+ # Extract the first word of "as", so it can be a program name with args.
+set dummy as; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_AS+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_AS"; then
+ ac_cv_prog_ac_ct_AS="$ac_ct_AS" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_AS="as"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AS=$ac_cv_prog_ac_ct_AS
+if test -n "$ac_ct_AS"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AS" >&5
+$as_echo "$ac_ct_AS" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_AS" = x; then
+ AS="false"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ AS=$ac_ct_AS
+ fi
+else
+ AS="$ac_cv_prog_AS"
+fi
+
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args.
+set dummy ${ac_tool_prefix}dlltool; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_DLLTOOL+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$DLLTOOL"; then
+ ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+DLLTOOL=$ac_cv_prog_DLLTOOL
+if test -n "$DLLTOOL"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5
+$as_echo "$DLLTOOL" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_DLLTOOL"; then
+ ac_ct_DLLTOOL=$DLLTOOL
+ # Extract the first word of "dlltool", so it can be a program name with args.
+set dummy dlltool; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_DLLTOOL"; then
+ ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_DLLTOOL="dlltool"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL
+if test -n "$ac_ct_DLLTOOL"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5
+$as_echo "$ac_ct_DLLTOOL" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_DLLTOOL" = x; then
+ DLLTOOL="false"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ DLLTOOL=$ac_ct_DLLTOOL
+ fi
+else
+ DLLTOOL="$ac_cv_prog_DLLTOOL"
+fi
+
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args.
+set dummy ${ac_tool_prefix}objdump; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_OBJDUMP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$OBJDUMP"; then
+ ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+OBJDUMP=$ac_cv_prog_OBJDUMP
+if test -n "$OBJDUMP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5
+$as_echo "$OBJDUMP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_OBJDUMP"; then
+ ac_ct_OBJDUMP=$OBJDUMP
+ # Extract the first word of "objdump", so it can be a program name with args.
+set dummy objdump; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_OBJDUMP"; then
+ ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_OBJDUMP="objdump"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP
+if test -n "$ac_ct_OBJDUMP"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5
+$as_echo "$ac_ct_OBJDUMP" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_OBJDUMP" = x; then
+ OBJDUMP="false"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ OBJDUMP=$ac_ct_OBJDUMP
+ fi
+else
+ OBJDUMP="$ac_cv_prog_OBJDUMP"
+fi
+
+ ;;
+esac
+
+test -z "$AS" && AS=as
+
+
+
+
+
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+
+
+
+
+
+test -z "$OBJDUMP" && OBJDUMP=objdump
+
+
+
+
+# Check whether --enable-static was given.
+if test "${enable_static+set}" = set; then :
+ enableval=$enable_static; p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_static=yes ;;
+ no) enable_static=no ;;
+ *)
+ enable_static=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+ for pkg in $enableval; do
+ IFS=$lt_save_ifs
+ if test "X$pkg" = "X$p"; then
+ enable_static=yes
+ fi
+ done
+ IFS=$lt_save_ifs
+ ;;
+ esac
+else
+ enable_static=no
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+ # Check whether --enable-shared was given.
+if test "${enable_shared+set}" = set; then :
+ enableval=$enable_shared; p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_shared=yes ;;
+ no) enable_shared=no ;;
+ *)
+ enable_shared=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+ for pkg in $enableval; do
+ IFS=$lt_save_ifs
+ if test "X$pkg" = "X$p"; then
+ enable_shared=yes
+ fi
+ done
+ IFS=$lt_save_ifs
+ ;;
+ esac
+else
+ enable_shared=yes
+fi
+
+
+
+
+
+
+
+
+
+
+
+# Check whether --with-pic was given.
+if test "${with_pic+set}" = set; then :
+ withval=$with_pic; lt_p=${PACKAGE-default}
+ case $withval in
+ yes|no) pic_mode=$withval ;;
+ *)
+ pic_mode=default
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+ for lt_pkg in $withval; do
+ IFS=$lt_save_ifs
+ if test "X$lt_pkg" = "X$lt_p"; then
+ pic_mode=yes
+ fi
+ done
+ IFS=$lt_save_ifs
+ ;;
+ esac
+else
+ pic_mode=default
+fi
+
+
+
+
+
+
+
+
+ # Check whether --enable-fast-install was given.
+if test "${enable_fast_install+set}" = set; then :
+ enableval=$enable_fast_install; p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_fast_install=yes ;;
+ no) enable_fast_install=no ;;
+ *)
+ enable_fast_install=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+ for pkg in $enableval; do
+ IFS=$lt_save_ifs
+ if test "X$pkg" = "X$p"; then
+ enable_fast_install=yes
+ fi
+ done
+ IFS=$lt_save_ifs
+ ;;
+ esac
+else
+ enable_fast_install=yes
+fi
+
+
+
+
+
+
+
+
+ shared_archive_member_spec=
+case $host,$enable_shared in
+power*-*-aix[5-9]*,yes)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5
+$as_echo_n "checking which variant of shared library versioning to provide... " >&6; }
+
+# Check whether --with-aix-soname was given.
+if test "${with_aix_soname+set}" = set; then :
+ withval=$with_aix_soname; case $withval in
+ aix|svr4|both)
+ ;;
+ *)
+ as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5
+ ;;
+ esac
+ lt_cv_with_aix_soname=$with_aix_soname
+else
+ if ${lt_cv_with_aix_soname+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_with_aix_soname=aix
+fi
+
+ with_aix_soname=$lt_cv_with_aix_soname
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5
+$as_echo "$with_aix_soname" >&6; }
+ if test aix != "$with_aix_soname"; then
+ # For the AIX way of multilib, we name the shared archive member
+ # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o',
+ # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File.
+ # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag,
+ # the AIX toolchain works better with OBJECT_MODE set (default 32).
+ if test 64 = "${OBJECT_MODE-32}"; then
+ shared_archive_member_spec=shr_64
+ else
+ shared_archive_member_spec=shr
+ fi
+ fi
+ ;;
+*)
+ with_aix_soname=aix
+ ;;
+esac
+
+
+
+
+
+
+
+
+
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS=$ltmain
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+test -z "$LN_S" && LN_S="ln -s"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+if test -n "${ZSH_VERSION+set}"; then
+ setopt NO_GLOB_SUBST
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5
+$as_echo_n "checking for objdir... " >&6; }
+if ${lt_cv_objdir+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+ lt_cv_objdir=.libs
+else
+ # MS-DOS does not allow filenames that begin with a dot.
+ lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5
+$as_echo "$lt_cv_objdir" >&6; }
+objdir=$lt_cv_objdir
+
+
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define LT_OBJDIR "$lt_cv_objdir/"
+_ACEOF
+
+
+
+
+case $host_os in
+aix3*)
+ # AIX sometimes has problems with the GCC collect2 program. For some
+ # reason, if we set the COLLECT_NAMES environment variable, the problems
+ # vanish in a puff of smoke.
+ if test set != "${COLLECT_NAMES+set}"; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+ fi
+ ;;
+esac
+
+# Global variables:
+ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a '.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+old_CC=$CC
+old_CFLAGS=$CFLAGS
+
+# Set sane defaults for various variables
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$LD" && LD=ld
+test -z "$ac_objext" && ac_objext=o
+
+func_cc_basename $compiler
+cc_basename=$func_cc_basename_result
+
+
+# Only perform the check for file, if the check method requires it
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+case $deplibs_check_method in
+file_magic*)
+ if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5
+$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; }
+if ${lt_cv_path_MAGIC_CMD+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $MAGIC_CMD in
+[\\/*] | ?:[\\/]*)
+ lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path.
+ ;;
+*)
+ lt_save_MAGIC_CMD=$MAGIC_CMD
+ lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+ ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+ for ac_dir in $ac_dummy; do
+ IFS=$lt_save_ifs
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/${ac_tool_prefix}file"; then
+ lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file"
+ if test -n "$file_magic_test_file"; then
+ case $deplibs_check_method in
+ "file_magic "*)
+ file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+ MAGIC_CMD=$lt_cv_path_MAGIC_CMD
+ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ $EGREP "$file_magic_regex" > /dev/null; then
+ :
+ else
+ cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such. This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem. Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+ fi ;;
+ esac
+ fi
+ break
+ fi
+ done
+ IFS=$lt_save_ifs
+ MAGIC_CMD=$lt_save_MAGIC_CMD
+ ;;
+esac
+fi
+
+MAGIC_CMD=$lt_cv_path_MAGIC_CMD
+if test -n "$MAGIC_CMD"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
+$as_echo "$MAGIC_CMD" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+
+
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+ if test -n "$ac_tool_prefix"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5
+$as_echo_n "checking for file... " >&6; }
+if ${lt_cv_path_MAGIC_CMD+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $MAGIC_CMD in
+[\\/*] | ?:[\\/]*)
+ lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path.
+ ;;
+*)
+ lt_save_MAGIC_CMD=$MAGIC_CMD
+ lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+ ac_dummy="/usr/bin$PATH_SEPARATOR$PATH"
+ for ac_dir in $ac_dummy; do
+ IFS=$lt_save_ifs
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/file"; then
+ lt_cv_path_MAGIC_CMD=$ac_dir/"file"
+ if test -n "$file_magic_test_file"; then
+ case $deplibs_check_method in
+ "file_magic "*)
+ file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+ MAGIC_CMD=$lt_cv_path_MAGIC_CMD
+ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ $EGREP "$file_magic_regex" > /dev/null; then
+ :
+ else
+ cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such. This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem. Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+ fi ;;
+ esac
+ fi
+ break
+ fi
+ done
+ IFS=$lt_save_ifs
+ MAGIC_CMD=$lt_save_MAGIC_CMD
+ ;;
+esac
+fi
+
+MAGIC_CMD=$lt_cv_path_MAGIC_CMD
+if test -n "$MAGIC_CMD"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5
+$as_echo "$MAGIC_CMD" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ else
+ MAGIC_CMD=:
+ fi
+fi
+
+ fi
+ ;;
+esac
+
+# Use C for the default configuration in the libtool script
+
+lt_save_CC=$CC
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+objext=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}'
+
+
+
+
+
+
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+
+# Save the default compiler, since it gets overwritten when the other
+# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
+compiler_DEFAULT=$CC
+
+# save warnings/boilerplate of simple test code
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$RM conftest*
+
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$RM -r conftest*
+
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+
+lt_prog_compiler_no_builtin_flag=
+
+if test yes = "$GCC"; then
+ case $cc_basename in
+ nvcc*)
+ lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;;
+ *)
+ lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;;
+ esac
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5
+$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; }
+if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_prog_compiler_rtti_exceptions=no
+ ac_outfile=conftest.$ac_objext
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="-fno-rtti -fno-exceptions" ## exclude from sc_useless_quotes_in_assignment
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_rtti_exceptions=yes
+ fi
+ fi
+ $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5
+$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; }
+
+if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then
+ lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions"
+else
+ :
+fi
+
+fi
+
+
+
+
+
+
+ lt_prog_compiler_wl=
+lt_prog_compiler_pic=
+lt_prog_compiler_static=
+
+
+ if test yes = "$GCC"; then
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_static='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test ia64 = "$host_cpu"; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static='-Bstatic'
+ fi
+ lt_prog_compiler_pic='-fPIC'
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ lt_prog_compiler_pic='-fPIC'
+ ;;
+ m68k)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the '-m68020' flag to GCC prevents building anything better,
+ # like '-m68040'.
+ lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4'
+ ;;
+ esac
+ ;;
+
+ beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+
+ mingw* | cygwin* | pw32* | os2* | cegcc*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ # Although the cygwin gcc ignores -fPIC, still need this for old-style
+ # (--disable-auto-import) libraries
+ lt_prog_compiler_pic='-DDLL_EXPORT'
+ case $host_os in
+ os2*)
+ lt_prog_compiler_static='$wl-static'
+ ;;
+ esac
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ lt_prog_compiler_pic='-fno-common'
+ ;;
+
+ haiku*)
+ # PIC is the default for Haiku.
+ # The "-static" flag exists, but is broken.
+ lt_prog_compiler_static=
+ ;;
+
+ hpux*)
+ # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+ # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag
+ # sets the default TLS model and affects inlining.
+ case $host_cpu in
+ hppa*64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic='-fPIC'
+ ;;
+ esac
+ ;;
+
+ interix[3-9]*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+
+ msdosdjgpp*)
+ # Just because we use GCC doesn't mean we suddenly get shared libraries
+ # on systems that don't support them.
+ lt_prog_compiler_can_build_shared=no
+ enable_shared=no
+ ;;
+
+ *nto* | *qnx*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ lt_prog_compiler_pic='-fPIC -shared'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ lt_prog_compiler_pic=-Kconform_pic
+ fi
+ ;;
+
+ *)
+ lt_prog_compiler_pic='-fPIC'
+ ;;
+ esac
+
+ case $cc_basename in
+ nvcc*) # Cuda Compiler Driver 2.2
+ lt_prog_compiler_wl='-Xlinker '
+ if test -n "$lt_prog_compiler_pic"; then
+ lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic"
+ fi
+ ;;
+ esac
+ else
+ # PORTME Check for flag to pass linker flags through the system compiler.
+ case $host_os in
+ aix*)
+ lt_prog_compiler_wl='-Wl,'
+ if test ia64 = "$host_cpu"; then
+ # AIX 5 now supports IA64 processor
+ lt_prog_compiler_static='-Bstatic'
+ else
+ lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ lt_prog_compiler_pic='-fno-common'
+ case $cc_basename in
+ nagfor*)
+ # NAG Fortran compiler
+ lt_prog_compiler_wl='-Wl,-Wl,,'
+ lt_prog_compiler_pic='-PIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+ esac
+ ;;
+
+ mingw* | cygwin* | pw32* | os2* | cegcc*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ lt_prog_compiler_pic='-DDLL_EXPORT'
+ case $host_os in
+ os2*)
+ lt_prog_compiler_static='$wl-static'
+ ;;
+ esac
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ lt_prog_compiler_wl='-Wl,'
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ lt_prog_compiler_pic='+Z'
+ ;;
+ esac
+ # Is there a better lt_prog_compiler_static that works with the bundled CC?
+ lt_prog_compiler_static='$wl-a ${wl}archive'
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ lt_prog_compiler_wl='-Wl,'
+ # PIC (with -KPIC) is the default.
+ lt_prog_compiler_static='-non_shared'
+ ;;
+
+ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+ case $cc_basename in
+ # old Intel for x86_64, which still supported -KPIC.
+ ecc*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-static'
+ ;;
+ # icc used to be incompatible with GCC.
+ # ICC 10 doesn't accept -KPIC any more.
+ icc* | ifort*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-fPIC'
+ lt_prog_compiler_static='-static'
+ ;;
+ # Lahey Fortran 8.1.
+ lf95*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='--shared'
+ lt_prog_compiler_static='--static'
+ ;;
+ nagfor*)
+ # NAG Fortran compiler
+ lt_prog_compiler_wl='-Wl,-Wl,,'
+ lt_prog_compiler_pic='-PIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+ tcc*)
+ # Fabrice Bellard et al's Tiny C Compiler
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-fPIC'
+ lt_prog_compiler_static='-static'
+ ;;
+ pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
+ # Portland Group compilers (*not* the Pentium gcc compiler,
+ # which looks to be a dead project)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-fpic'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+ ccc*)
+ lt_prog_compiler_wl='-Wl,'
+ # All Alpha code is PIC.
+ lt_prog_compiler_static='-non_shared'
+ ;;
+ xl* | bgxl* | bgf* | mpixl*)
+ # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-qpic'
+ lt_prog_compiler_static='-qstaticlink'
+ ;;
+ *)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*)
+ # Sun Fortran 8.3 passes all unrecognized flags to the linker
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ lt_prog_compiler_wl=''
+ ;;
+ *Sun\ F* | *Sun*Fortran*)
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ lt_prog_compiler_wl='-Qoption ld '
+ ;;
+ *Sun\ C*)
+ # Sun C 5.9
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ lt_prog_compiler_wl='-Wl,'
+ ;;
+ *Intel*\ [CF]*Compiler*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-fPIC'
+ lt_prog_compiler_static='-static'
+ ;;
+ *Portland\ Group*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-fpic'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+
+ newsos6)
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ *nto* | *qnx*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ lt_prog_compiler_pic='-fPIC -shared'
+ ;;
+
+ osf3* | osf4* | osf5*)
+ lt_prog_compiler_wl='-Wl,'
+ # All OSF/1 code is PIC.
+ lt_prog_compiler_static='-non_shared'
+ ;;
+
+ rdos*)
+ lt_prog_compiler_static='-non_shared'
+ ;;
+
+ solaris*)
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ case $cc_basename in
+ f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
+ lt_prog_compiler_wl='-Qoption ld ';;
+ *)
+ lt_prog_compiler_wl='-Wl,';;
+ esac
+ ;;
+
+ sunos4*)
+ lt_prog_compiler_wl='-Qoption ld '
+ lt_prog_compiler_pic='-PIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ sysv4 | sysv4.2uw2* | sysv4.3*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ lt_prog_compiler_pic='-Kconform_pic'
+ lt_prog_compiler_static='-Bstatic'
+ fi
+ ;;
+
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_pic='-KPIC'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ unicos*)
+ lt_prog_compiler_wl='-Wl,'
+ lt_prog_compiler_can_build_shared=no
+ ;;
+
+ uts4*)
+ lt_prog_compiler_pic='-pic'
+ lt_prog_compiler_static='-Bstatic'
+ ;;
+
+ *)
+ lt_prog_compiler_can_build_shared=no
+ ;;
+ esac
+ fi
+
+case $host_os in
+ # For platforms that do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ lt_prog_compiler_pic=
+ ;;
+ *)
+ lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC"
+ ;;
+esac
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5
+$as_echo_n "checking for $compiler option to produce PIC... " >&6; }
+if ${lt_cv_prog_compiler_pic+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_prog_compiler_pic=$lt_prog_compiler_pic
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5
+$as_echo "$lt_cv_prog_compiler_pic" >&6; }
+lt_prog_compiler_pic=$lt_cv_prog_compiler_pic
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$lt_prog_compiler_pic"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5
+$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; }
+if ${lt_cv_prog_compiler_pic_works+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_prog_compiler_pic_works=no
+ ac_outfile=conftest.$ac_objext
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_pic_works=yes
+ fi
+ fi
+ $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5
+$as_echo "$lt_cv_prog_compiler_pic_works" >&6; }
+
+if test yes = "$lt_cv_prog_compiler_pic_works"; then
+ case $lt_prog_compiler_pic in
+ "" | " "*) ;;
+ *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;;
+ esac
+else
+ lt_prog_compiler_pic=
+ lt_prog_compiler_can_build_shared=no
+fi
+
+fi
+
+
+
+
+
+
+
+
+
+
+
+#
+# Check to make sure the static flag actually works.
+#
+wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5
+$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; }
+if ${lt_cv_prog_compiler_static_works+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_prog_compiler_static_works=no
+ save_LDFLAGS=$LDFLAGS
+ LDFLAGS="$LDFLAGS $lt_tmp_static_flag"
+ echo "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_static_works=yes
+ fi
+ else
+ lt_cv_prog_compiler_static_works=yes
+ fi
+ fi
+ $RM -r conftest*
+ LDFLAGS=$save_LDFLAGS
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5
+$as_echo "$lt_cv_prog_compiler_static_works" >&6; }
+
+if test yes = "$lt_cv_prog_compiler_static_works"; then
+ :
+else
+ lt_prog_compiler_static=
+fi
+
+
+
+
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if ${lt_cv_prog_compiler_c_o+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_prog_compiler_c_o=no
+ $RM -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_c_o=yes
+ fi
+ fi
+ chmod u+w . 2>&5
+ $RM conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+ $RM out/* && rmdir out
+ cd ..
+ $RM -r conftest
+ $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
+$as_echo "$lt_cv_prog_compiler_c_o" >&6; }
+
+
+
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5
+$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; }
+if ${lt_cv_prog_compiler_c_o+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_prog_compiler_c_o=no
+ $RM -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler_c_o=yes
+ fi
+ fi
+ chmod u+w . 2>&5
+ $RM conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+ $RM out/* && rmdir out
+ cd ..
+ $RM -r conftest
+ $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5
+$as_echo "$lt_cv_prog_compiler_c_o" >&6; }
+
+
+
+
+hard_links=nottested
+if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then
+ # do not overwrite the value of need_locks provided by the user
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5
+$as_echo_n "checking if we can lock with hard links... " >&6; }
+ hard_links=yes
+ $RM conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5
+$as_echo "$hard_links" >&6; }
+ if test no = "$hard_links"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5
+$as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;}
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+
+
+
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5
+$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; }
+
+ runpath_var=
+ allow_undefined_flag=
+ always_export_symbols=no
+ archive_cmds=
+ archive_expsym_cmds=
+ compiler_needs_object=no
+ enable_shared_with_static_runtimes=no
+ export_dynamic_flag_spec=
+ export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ hardcode_automatic=no
+ hardcode_direct=no
+ hardcode_direct_absolute=no
+ hardcode_libdir_flag_spec=
+ hardcode_libdir_separator=
+ hardcode_minus_L=no
+ hardcode_shlibpath_var=unsupported
+ inherit_rpath=no
+ link_all_deplibs=unknown
+ module_cmds=
+ module_expsym_cmds=
+ old_archive_from_new_cmds=
+ old_archive_from_expsyms_cmds=
+ thread_safe_flag_spec=
+ whole_archive_flag_spec=
+ # include_expsyms should be a list of space-separated symbols to be *always*
+ # included in the symbol list
+ include_expsyms=
+ # exclude_expsyms can be an extended regexp of symbols to exclude
+ # it will be wrapped by ' (' and ')$', so one must not match beginning or
+ # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc',
+ # as well as any symbol that contains 'd'.
+ exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'
+ # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+ # platforms (ab)use it in PIC code, but their linkers get confused if
+ # the symbol is explicitly referenced. Since portable code cannot
+ # rely on this symbol name, it's probably fine to never include it in
+ # preloaded symbol tables.
+ # Exclude shared library initialization/finalization symbols.
+ extract_expsyms_cmds=
+
+ case $host_os in
+ cygwin* | mingw* | pw32* | cegcc*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ if test yes != "$GCC"; then
+ with_gnu_ld=no
+ fi
+ ;;
+ interix*)
+ # we just hope/assume this is gcc and not c89 (= MSVC++)
+ with_gnu_ld=yes
+ ;;
+ openbsd* | bitrig*)
+ with_gnu_ld=no
+ ;;
+ esac
+
+ ld_shlibs=yes
+
+ # On some targets, GNU ld is compatible enough with the native linker
+ # that we're better off using the native interface for both.
+ lt_use_gnu_ld_interface=no
+ if test yes = "$with_gnu_ld"; then
+ case $host_os in
+ aix*)
+ # The AIX port of GNU ld has always aspired to compatibility
+ # with the native linker. However, as the warning in the GNU ld
+ # block says, versions before 2.19.5* couldn't really create working
+ # shared libraries, regardless of the interface used.
+ case `$LD -v 2>&1` in
+ *\ \(GNU\ Binutils\)\ 2.19.5*) ;;
+ *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;;
+ *\ \(GNU\ Binutils\)\ [3-9]*) ;;
+ *)
+ lt_use_gnu_ld_interface=yes
+ ;;
+ esac
+ ;;
+ *)
+ lt_use_gnu_ld_interface=yes
+ ;;
+ esac
+ fi
+
+ if test yes = "$lt_use_gnu_ld_interface"; then
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ wlarc='$wl'
+
+ # Set some defaults for GNU ld with shared library support. These
+ # are reset later if shared libraries are not supported. Putting them
+ # here allows them to be overridden if necessary.
+ runpath_var=LD_RUN_PATH
+ hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+ export_dynamic_flag_spec='$wl--export-dynamic'
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
+ whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
+ else
+ whole_archive_flag_spec=
+ fi
+ supports_anon_versioning=no
+ case `$LD -v | $SED -e 's/(^)\+)\s\+//' 2>&1` in
+ *GNU\ gold*) supports_anon_versioning=yes ;;
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11
+ *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+ *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+ *\ 2.11.*) ;; # other 2.11 versions
+ *) supports_anon_versioning=yes ;;
+ esac
+
+ # See if GNU ld supports shared libraries.
+ case $host_os in
+ aix[3-9]*)
+ # On AIX/PPC, the GNU linker is very broken
+ if test ia64 != "$host_cpu"; then
+ ld_shlibs=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.19, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support. If you
+*** really care for shared libraries, you may want to install binutils
+*** 2.20 or above, or modify your PATH so that a non-GNU linker is found.
+*** You will then need to restart the configuration process.
+
+_LT_EOF
+ fi
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ archive_expsym_cmds=''
+ ;;
+ m68k)
+ archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ ;;
+ esac
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ allow_undefined_flag=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ cygwin* | mingw* | pw32* | cegcc*)
+ # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless,
+ # as there is no search path for DLLs.
+ hardcode_libdir_flag_spec='-L$libdir'
+ export_dynamic_flag_spec='$wl--export-all-symbols'
+ allow_undefined_flag=unsupported
+ always_export_symbols=no
+ enable_shared_with_static_runtimes=yes
+ export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols'
+ exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'
+
+ if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file, use it as
+ # is; otherwise, prepend EXPORTS...
+ archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ haiku*)
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ link_all_deplibs=yes
+ ;;
+
+ os2*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ allow_undefined_flag=unsupported
+ shrext_cmds=.dll
+ archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ prefix_cmds="$SED"~
+ if test EXPORTS = "`$SED 1q $export_symbols`"; then
+ prefix_cmds="$prefix_cmds -e 1d";
+ fi~
+ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
+ enable_shared_with_static_runtimes=yes
+ ;;
+
+ interix[3-9]*)
+ hardcode_direct=no
+ hardcode_shlibpath_var=no
+ hardcode_libdir_flag_spec='$wl-rpath,$libdir'
+ export_dynamic_flag_spec='$wl-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ archive_expsym_cmds='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+
+ gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
+ tmp_diet=no
+ if test linux-dietlibc = "$host_os"; then
+ case $cc_basename in
+ diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn)
+ esac
+ fi
+ if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
+ && test no = "$tmp_diet"
+ then
+ tmp_addflag=' $pic_flag'
+ tmp_sharedflag='-shared'
+ case $cc_basename,$host_cpu in
+ pgcc*) # Portland Group C compiler
+ whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+ tmp_addflag=' $pic_flag'
+ ;;
+ pgf77* | pgf90* | pgf95* | pgfortran*)
+ # Portland Group f77 and f90 compilers
+ whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+ tmp_addflag=' $pic_flag -Mnomain' ;;
+ ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
+ tmp_addflag=' -i_dynamic' ;;
+ efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
+ tmp_addflag=' -i_dynamic -nofor_main' ;;
+ ifc* | ifort*) # Intel Fortran compiler
+ tmp_addflag=' -nofor_main' ;;
+ lf95*) # Lahey Fortran 8.1
+ whole_archive_flag_spec=
+ tmp_sharedflag='--shared' ;;
+ nagfor*) # NAGFOR 5.3
+ tmp_sharedflag='-Wl,-shared' ;;
+ xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below)
+ tmp_sharedflag='-qmkshrobj'
+ tmp_addflag= ;;
+ nvcc*) # Cuda Compiler Driver 2.2
+ whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+ compiler_needs_object=yes
+ ;;
+ esac
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*) # Sun C 5.9
+ whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+ compiler_needs_object=yes
+ tmp_sharedflag='-G' ;;
+ *Sun\ F*) # Sun Fortran 8.3
+ tmp_sharedflag='-G' ;;
+ esac
+ archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+
+ if test yes = "$supports_anon_versioning"; then
+ archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
+ fi
+
+ case $cc_basename in
+ tcc*)
+ export_dynamic_flag_spec='-rdynamic'
+ ;;
+ xlf* | bgf* | bgxlf* | mpixlf*)
+ # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
+ whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive'
+ hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+ archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib'
+ if test yes = "$supports_anon_versioning"; then
+ archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ echo "local: *; };" >> $output_objdir/$libname.ver~
+ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
+ fi
+ ;;
+ esac
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+ wlarc=
+ else
+ archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+ fi
+ ;;
+
+ solaris*)
+ if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
+ ld_shlibs=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+ case `$LD -v 2>&1` in
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+ ld_shlibs=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot
+*** reliably create shared libraries on SCO systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ ;;
+ *)
+ # For security reasons, it is highly recommended that you always
+ # use absolute paths for naming shared libraries, and exclude the
+ # DT_RUNPATH tag from executables and libraries. But doing so
+ # requires that you compile everything twice, which is a pain.
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ esac
+ ;;
+
+ sunos4*)
+ archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ wlarc=
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ *)
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ esac
+
+ if test no = "$ld_shlibs"; then
+ runpath_var=
+ hardcode_libdir_flag_spec=
+ export_dynamic_flag_spec=
+ whole_archive_flag_spec=
+ fi
+ else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case $host_os in
+ aix3*)
+ allow_undefined_flag=unsupported
+ always_export_symbols=yes
+ archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ hardcode_minus_L=yes
+ if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ hardcode_direct=unsupported
+ fi
+ ;;
+
+ aix[4-9]*)
+ if test ia64 = "$host_cpu"; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=
+ else
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to GNU nm, but means don't demangle to AIX nm.
+ # Without the "-l" option, or with the "-B" option, AIX nm treats
+ # weak defined symbols like other global defined symbols, whereas
+ # GNU nm marks them as "W".
+ # While the 'weak' keyword is ignored in the Export File, we need
+ # it in the Import File for the 'aix-soname' feature, so we have
+ # to replace the "-B" option with "-P" for AIX nm.
+ if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+ export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
+ else
+ export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
+ fi
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # have runtime linking enabled, and use it for executables.
+ # For shared libraries, we enable/disable runtime linking
+ # depending on the kind of the shared library created -
+ # when "with_aix_soname,aix_use_runtimelinking" is:
+ # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables
+ # "aix,yes" lib.so shared, rtl:yes, for executables
+ # lib.a static archive
+ # "both,no" lib.so.V(shr.o) shared, rtl:yes
+ # lib.a(lib.so.V) shared, rtl:no, for executables
+ # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
+ # lib.a(lib.so.V) shared, rtl:no
+ # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables
+ # lib.a static archive
+ case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
+ for ld_flag in $LDFLAGS; do
+ if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
+ # With aix-soname=svr4, we create the lib.so.V shared archives only,
+ # so we don't have lib.a shared libs to link our executables.
+ # We have to force runtime linking in this case.
+ aix_use_runtimelinking=yes
+ LDFLAGS="$LDFLAGS -Wl,-brtl"
+ fi
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ archive_cmds=''
+ hardcode_direct=yes
+ hardcode_direct_absolute=yes
+ hardcode_libdir_separator=':'
+ link_all_deplibs=yes
+ file_list_spec='$wl-f,'
+ case $with_aix_soname,$aix_use_runtimelinking in
+ aix,*) ;; # traditional, no import file
+ svr4,* | *,yes) # use import file
+ # The Import File defines what to hardcode.
+ hardcode_direct=no
+ hardcode_direct_absolute=no
+ ;;
+ esac
+
+ if test yes = "$GCC"; then
+ case $host_os in aix4.[012]|aix4.[012].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`$CC -print-prog-name=collect2`
+ if test -f "$collect2name" &&
+ strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ :
+ else
+ # We have old collect2
+ hardcode_direct=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ hardcode_minus_L=yes
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_libdir_separator=
+ fi
+ ;;
+ esac
+ shared_flag='-shared'
+ if test yes = "$aix_use_runtimelinking"; then
+ shared_flag="$shared_flag "'$wl-G'
+ fi
+ # Need to ensure runtime linking is disabled for the traditional
+ # shared library, or the linker may eventually find shared libraries
+ # /with/ Import File - we do not want to mix them.
+ shared_flag_aix='-shared'
+ shared_flag_svr4='-shared $wl-G'
+ else
+ # not using gcc
+ if test ia64 = "$host_cpu"; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test yes = "$aix_use_runtimelinking"; then
+ shared_flag='$wl-G'
+ else
+ shared_flag='$wl-bM:SRE'
+ fi
+ shared_flag_aix='$wl-bM:SRE'
+ shared_flag_svr4='$wl-G'
+ fi
+ fi
+
+ export_dynamic_flag_spec='$wl-bexpall'
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ always_export_symbols=yes
+ if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ allow_undefined_flag='-berok'
+ # Determine the default libpath from the value encoded in an
+ # empty executable.
+ if test set = "${lt_cv_aix_libpath+set}"; then
+ aix_libpath=$lt_cv_aix_libpath
+else
+ if ${lt_cv_aix_libpath_+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+ lt_aix_libpath_sed='
+ /Import File Strings/,/^$/ {
+ /^0/ {
+ s/^0 *\([^ ]*\) *$/\1/
+ p
+ }
+ }'
+ lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+ # Check for a 64-bit object if we didn't find anything.
+ if test -z "$lt_cv_aix_libpath_"; then
+ lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+ fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ if test -z "$lt_cv_aix_libpath_"; then
+ lt_cv_aix_libpath_=/usr/lib:/lib
+ fi
+
+fi
+
+ aix_libpath=$lt_cv_aix_libpath_
+fi
+
+ hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath"
+ archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
+ else
+ if test ia64 = "$host_cpu"; then
+ hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib'
+ allow_undefined_flag="-z nodefs"
+ archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an
+ # empty executable.
+ if test set = "${lt_cv_aix_libpath+set}"; then
+ aix_libpath=$lt_cv_aix_libpath
+else
+ if ${lt_cv_aix_libpath_+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+ lt_aix_libpath_sed='
+ /Import File Strings/,/^$/ {
+ /^0/ {
+ s/^0 *\([^ ]*\) *$/\1/
+ p
+ }
+ }'
+ lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+ # Check for a 64-bit object if we didn't find anything.
+ if test -z "$lt_cv_aix_libpath_"; then
+ lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+ fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ if test -z "$lt_cv_aix_libpath_"; then
+ lt_cv_aix_libpath_=/usr/lib:/lib
+ fi
+
+fi
+
+ aix_libpath=$lt_cv_aix_libpath_
+fi
+
+ hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ no_undefined_flag=' $wl-bernotok'
+ allow_undefined_flag=' $wl-berok'
+ if test yes = "$with_gnu_ld"; then
+ # We only use this code for GNU lds that support --whole-archive.
+ whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive'
+ else
+ # Exported symbols can be pulled into shared objects from archives
+ whole_archive_flag_spec='$convenience'
+ fi
+ archive_cmds_need_lc=yes
+ archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d'
+ # -brtl affects multiple linker settings, -berok does not and is overridden later
+ compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`'
+ if test svr4 != "$with_aix_soname"; then
+ # This is similar to how AIX traditionally builds its shared libraries.
+ archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
+ fi
+ if test aix != "$with_aix_soname"; then
+ archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp'
+ else
+ # used by -dlpreopen to get the symbols
+ archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir'
+ fi
+ archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d'
+ fi
+ fi
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ archive_expsym_cmds=''
+ ;;
+ m68k)
+ archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ ;;
+ esac
+ ;;
+
+ bsdi[45]*)
+ export_dynamic_flag_spec=-rdynamic
+ ;;
+
+ cygwin* | mingw* | pw32* | cegcc*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ case $cc_basename in
+ cl*)
+ # Native MSVC
+ hardcode_libdir_flag_spec=' '
+ allow_undefined_flag=unsupported
+ always_export_symbols=yes
+ file_list_spec='@'
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=.dll
+ # FIXME: Setting linknames here is a bad hack.
+ archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
+ archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then
+ cp "$export_symbols" "$output_objdir/$soname.def";
+ echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
+ else
+ $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp;
+ fi~
+ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
+ linknames='
+ # The linker will not automatically build a static lib if we build a DLL.
+ # _LT_TAGVAR(old_archive_from_new_cmds, )='true'
+ enable_shared_with_static_runtimes=yes
+ exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
+ export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols'
+ # Don't use ranlib
+ old_postinstall_cmds='chmod 644 $oldlib'
+ postlink_cmds='lt_outputfile="@OUTPUT@"~
+ lt_tool_outputfile="@TOOL_OUTPUT@"~
+ case $lt_outputfile in
+ *.exe|*.EXE) ;;
+ *)
+ lt_outputfile=$lt_outputfile.exe
+ lt_tool_outputfile=$lt_tool_outputfile.exe
+ ;;
+ esac~
+ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then
+ $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
+ $RM "$lt_outputfile.manifest";
+ fi'
+ ;;
+ *)
+ # Assume MSVC wrapper
+ hardcode_libdir_flag_spec=' '
+ allow_undefined_flag=unsupported
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=.dll
+ # FIXME: Setting linknames here is a bad hack.
+ archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames='
+ # The linker will automatically build a .lib file if we build a DLL.
+ old_archive_from_new_cmds='true'
+ # FIXME: Should let the user specify the lib program.
+ old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs'
+ enable_shared_with_static_runtimes=yes
+ ;;
+ esac
+ ;;
+
+ darwin* | rhapsody*)
+
+
+ archive_cmds_need_lc=no
+ hardcode_direct=no
+ hardcode_automatic=yes
+ hardcode_shlibpath_var=unsupported
+ if test yes = "$lt_cv_ld_force_load"; then
+ whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
+
+ else
+ whole_archive_flag_spec=''
+ fi
+ link_all_deplibs=yes
+ allow_undefined_flag=$_lt_dar_allow_undefined
+ case $cc_basename in
+ ifort*|nagfor*) _lt_dar_can_shared=yes ;;
+ *) _lt_dar_can_shared=$GCC ;;
+ esac
+ if test yes = "$_lt_dar_can_shared"; then
+ output_verbose_link_cmd=func_echo_all
+ archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil"
+ module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil"
+ archive_expsym_cmds="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil"
+ module_expsym_cmds="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil"
+
+ else
+ ld_shlibs=no
+ fi
+
+ ;;
+
+ dgux*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_shlibpath_var=no
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # does not break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+ freebsd2.*)
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+ freebsd* | dragonfly*)
+ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ hpux9*)
+ if test yes = "$GCC"; then
+ archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
+ else
+ archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
+ fi
+ hardcode_libdir_flag_spec='$wl+b $wl$libdir'
+ hardcode_libdir_separator=:
+ hardcode_direct=yes
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ export_dynamic_flag_spec='$wl-E'
+ ;;
+
+ hpux10*)
+ if test yes,no = "$GCC,$with_gnu_ld"; then
+ archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ if test no = "$with_gnu_ld"; then
+ hardcode_libdir_flag_spec='$wl+b $wl$libdir'
+ hardcode_libdir_separator=:
+ hardcode_direct=yes
+ hardcode_direct_absolute=yes
+ export_dynamic_flag_spec='$wl-E'
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ fi
+ ;;
+
+ hpux11*)
+ if test yes,no = "$GCC,$with_gnu_ld"; then
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ else
+ case $host_cpu in
+ hppa*64*)
+ archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+
+ # Older versions of the 11.00 compiler do not understand -b yet
+ # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5
+$as_echo_n "checking if $CC understands -b... " >&6; }
+if ${lt_cv_prog_compiler__b+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_prog_compiler__b=no
+ save_LDFLAGS=$LDFLAGS
+ LDFLAGS="$LDFLAGS -b"
+ echo "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&5
+ $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ lt_cv_prog_compiler__b=yes
+ fi
+ else
+ lt_cv_prog_compiler__b=yes
+ fi
+ fi
+ $RM -r conftest*
+ LDFLAGS=$save_LDFLAGS
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5
+$as_echo "$lt_cv_prog_compiler__b" >&6; }
+
+if test yes = "$lt_cv_prog_compiler__b"; then
+ archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+else
+ archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+fi
+
+ ;;
+ esac
+ fi
+ if test no = "$with_gnu_ld"; then
+ hardcode_libdir_flag_spec='$wl+b $wl$libdir'
+ hardcode_libdir_separator=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ hardcode_direct=no
+ hardcode_shlibpath_var=no
+ ;;
+ *)
+ hardcode_direct=yes
+ hardcode_direct_absolute=yes
+ export_dynamic_flag_spec='$wl-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ ;;
+ esac
+ fi
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ if test yes = "$GCC"; then
+ archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+ # Try to use the -exported_symbol ld option, if it does not
+ # work, assume that -exports_file does not work either and
+ # implicitly export all symbols.
+ # This should be the same for all languages, so no per-tag cache variable.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5
+$as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; }
+if ${lt_cv_irix_exported_symbol+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ save_LDFLAGS=$LDFLAGS
+ LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+int foo (void) { return 0; }
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ lt_cv_irix_exported_symbol=yes
+else
+ lt_cv_irix_exported_symbol=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$save_LDFLAGS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5
+$as_echo "$lt_cv_irix_exported_symbol" >&6; }
+ if test yes = "$lt_cv_irix_exported_symbol"; then
+ archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib'
+ fi
+ else
+ archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+ archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib'
+ fi
+ archive_cmds_need_lc='no'
+ hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+ hardcode_libdir_separator=:
+ inherit_rpath=yes
+ link_all_deplibs=yes
+ ;;
+
+ linux*)
+ case $cc_basename in
+ tcc*)
+ # Fabrice Bellard et al's Tiny C Compiler
+ ld_shlibs=yes
+ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
+ else
+ archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
+ fi
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ newsos6)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes
+ hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+ hardcode_libdir_separator=:
+ hardcode_shlibpath_var=no
+ ;;
+
+ *nto* | *qnx*)
+ ;;
+
+ openbsd* | bitrig*)
+ if test -f /usr/libexec/ld.so; then
+ hardcode_direct=yes
+ hardcode_shlibpath_var=no
+ hardcode_direct_absolute=yes
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols'
+ hardcode_libdir_flag_spec='$wl-rpath,$libdir'
+ export_dynamic_flag_spec='$wl-E'
+ else
+ archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ hardcode_libdir_flag_spec='$wl-rpath,$libdir'
+ fi
+ else
+ ld_shlibs=no
+ fi
+ ;;
+
+ os2*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ allow_undefined_flag=unsupported
+ shrext_cmds=.dll
+ archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ prefix_cmds="$SED"~
+ if test EXPORTS = "`$SED 1q $export_symbols`"; then
+ prefix_cmds="$prefix_cmds -e 1d";
+ fi~
+ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
+ enable_shared_with_static_runtimes=yes
+ ;;
+
+ osf3*)
+ if test yes = "$GCC"; then
+ allow_undefined_flag=' $wl-expect_unresolved $wl\*'
+ archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+ else
+ allow_undefined_flag=' -expect_unresolved \*'
+ archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+ fi
+ archive_cmds_need_lc='no'
+ hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+ hardcode_libdir_separator=:
+ ;;
+
+ osf4* | osf5*) # as osf3* with the addition of -msym flag
+ if test yes = "$GCC"; then
+ allow_undefined_flag=' $wl-expect_unresolved $wl\*'
+ archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+ hardcode_libdir_flag_spec='$wl-rpath $wl$libdir'
+ else
+ allow_undefined_flag=' -expect_unresolved \*'
+ archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+ archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
+ $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp'
+
+ # Both c and cxx compiler support -rpath directly
+ hardcode_libdir_flag_spec='-rpath $libdir'
+ fi
+ archive_cmds_need_lc='no'
+ hardcode_libdir_separator=:
+ ;;
+
+ solaris*)
+ no_undefined_flag=' -z defs'
+ if test yes = "$GCC"; then
+ wlarc='$wl'
+ archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+ else
+ case `$CC -V 2>&1` in
+ *"Compilers 5.0"*)
+ wlarc=''
+ archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
+ ;;
+ *)
+ wlarc='$wl'
+ archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+ ;;
+ esac
+ fi
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_shlibpath_var=no
+ case $host_os in
+ solaris2.[0-5] | solaris2.[0-5].*) ;;
+ *)
+ # The compiler driver will combine and reorder linker options,
+ # but understands '-z linker_flag'. GCC discards it without '$wl',
+ # but is careful enough not to reorder.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ if test yes = "$GCC"; then
+ whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract'
+ else
+ whole_archive_flag_spec='-z allextract$convenience -z defaultextract'
+ fi
+ ;;
+ esac
+ link_all_deplibs=yes
+ ;;
+
+ sunos4*)
+ if test sequent = "$host_vendor"; then
+ # Use $CC to link under sequent, because it throws in some extra .o
+ # files that make .init and .fini sections work.
+ archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ hardcode_shlibpath_var=no
+ ;;
+
+ sysv4)
+ case $host_vendor in
+ sni)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=yes # is this really true???
+ ;;
+ siemens)
+ ## LD is ld it makes a PLAMLIB
+ ## CC just makes a GrossModule.
+ archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+ reload_cmds='$CC -r -o $output$reload_objs'
+ hardcode_direct=no
+ ;;
+ motorola)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+ ;;
+ esac
+ runpath_var='LD_RUN_PATH'
+ hardcode_shlibpath_var=no
+ ;;
+
+ sysv4.3*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var=no
+ export_dynamic_flag_spec='-Bexport'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_shlibpath_var=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ ld_shlibs=yes
+ fi
+ ;;
+
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+ no_undefined_flag='$wl-z,text'
+ archive_cmds_need_lc=no
+ hardcode_shlibpath_var=no
+ runpath_var='LD_RUN_PATH'
+
+ if test yes = "$GCC"; then
+ archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We CANNOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ no_undefined_flag='$wl-z,text'
+ allow_undefined_flag='$wl-z,nodefs'
+ archive_cmds_need_lc=no
+ hardcode_shlibpath_var=no
+ hardcode_libdir_flag_spec='$wl-R,$libdir'
+ hardcode_libdir_separator=':'
+ link_all_deplibs=yes
+ export_dynamic_flag_spec='$wl-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ if test yes = "$GCC"; then
+ archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ uts4*)
+ archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_shlibpath_var=no
+ ;;
+
+ *)
+ ld_shlibs=no
+ ;;
+ esac
+
+ if test sni = "$host_vendor"; then
+ case $host in
+ sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+ export_dynamic_flag_spec='$wl-Blargedynsym'
+ ;;
+ esac
+ fi
+ fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5
+$as_echo "$ld_shlibs" >&6; }
+test no = "$ld_shlibs" && can_build_shared=no
+
+with_gnu_ld=$with_gnu_ld
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$archive_cmds_need_lc" in
+x|xyes)
+ # Assume -lc should be added
+ archive_cmds_need_lc=yes
+
+ if test yes,yes = "$GCC,$enable_shared"; then
+ case $archive_cmds in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5
+$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; }
+if ${lt_cv_archive_cmds_need_lc+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ $RM conftest*
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$lt_prog_compiler_wl
+ pic_flag=$lt_prog_compiler_pic
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$allow_undefined_flag
+ allow_undefined_flag=
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5
+ (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ then
+ lt_cv_archive_cmds_need_lc=no
+ else
+ lt_cv_archive_cmds_need_lc=yes
+ fi
+ allow_undefined_flag=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $RM conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5
+$as_echo "$lt_cv_archive_cmds_need_lc" >&6; }
+ archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc
+ ;;
+ esac
+ fi
+ ;;
+esac
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5
+$as_echo_n "checking dynamic linker characteristics... " >&6; }
+
+if test yes = "$GCC"; then
+ case $host_os in
+ darwin*) lt_awk_arg='/^libraries:/,/LR/' ;;
+ *) lt_awk_arg='/^libraries:/' ;;
+ esac
+ case $host_os in
+ mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;;
+ *) lt_sed_strip_eq='s|=/|/|g' ;;
+ esac
+ lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq`
+ case $lt_search_path_spec in
+ *\;*)
+ # if the path contains ";" then we assume it to be the separator
+ # otherwise default to the standard path separator (i.e. ":") - it is
+ # assumed that no part of a normal pathname contains ";" but that should
+ # okay in the real world where ";" in dirpaths is itself problematic.
+ lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'`
+ ;;
+ *)
+ lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"`
+ ;;
+ esac
+ # Ok, now we have the path, separated by spaces, we can step through it
+ # and add multilib dir if necessary...
+ lt_tmp_lt_search_path_spec=
+ lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+ # ...but if some path component already ends with the multilib dir we assume
+ # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer).
+ case "$lt_multi_os_dir; $lt_search_path_spec " in
+ "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*)
+ lt_multi_os_dir=
+ ;;
+ esac
+ for lt_sys_path in $lt_search_path_spec; do
+ if test -d "$lt_sys_path$lt_multi_os_dir"; then
+ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir"
+ elif test -n "$lt_multi_os_dir"; then
+ test -d "$lt_sys_path" && \
+ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
+ fi
+ done
+ lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk '
+BEGIN {RS = " "; FS = "/|\n";} {
+ lt_foo = "";
+ lt_count = 0;
+ for (lt_i = NF; lt_i > 0; lt_i--) {
+ if ($lt_i != "" && $lt_i != ".") {
+ if ($lt_i == "..") {
+ lt_count++;
+ } else {
+ if (lt_count == 0) {
+ lt_foo = "/" $lt_i lt_foo;
+ } else {
+ lt_count--;
+ }
+ }
+ }
+ }
+ if (lt_foo != "") { lt_freq[lt_foo]++; }
+ if (lt_freq[lt_foo] == 1) { print lt_foo; }
+}'`
+ # AWK program above erroneously prepends '/' to C:/dos/paths
+ # for these hosts.
+ case $host_os in
+ mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\
+ $SED 's|/\([A-Za-z]:\)|\1|g'` ;;
+ esac
+ sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP`
+else
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=.so
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+
+
+case $host_os in
+aix3*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ library_names_spec='$libname$release$shared_ext$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='$libname$release$shared_ext$major'
+ ;;
+
+aix[4-9]*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test ia64 = "$host_cpu"; then
+ # AIX 5 supports IA64
+ library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line '#! .'. This would cause the generated library to
+ # depend on '.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[01] | aix4.[01].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # Using Import Files as archive members, it is possible to support
+ # filename-based versioning of shared library archives on AIX. While
+ # this would work for both with and without runtime linking, it will
+ # prevent static linking of such archives. So we do filename-based
+ # shared library versioning with .so extension only, which is used
+ # when both runtime linking and shared linking is enabled.
+ # Unfortunately, runtime linking may impact performance, so we do
+ # not want this to be the default eventually. Also, we use the
+ # versioned .so libs for executables only if there is the -brtl
+ # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only.
+ # To allow for filename-based versioning support, we need to create
+ # libNAME.so.V as an archive file, containing:
+ # *) an Import File, referring to the versioned filename of the
+ # archive as well as the shared archive member, telling the
+ # bitwidth (32 or 64) of that shared object, and providing the
+ # list of exported symbols of that shared object, eventually
+ # decorated with the 'weak' keyword
+ # *) the shared object with the F_LOADONLY flag set, to really avoid
+ # it being seen by the linker.
+ # At run time we better use the real file rather than another symlink,
+ # but for link time we create the symlink libNAME.so -> libNAME.so.V
+
+ case $with_aix_soname,$aix_use_runtimelinking in
+ # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ aix,yes) # traditional libtool
+ dynamic_linker='AIX unversionable lib.so'
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ ;;
+ aix,no) # traditional AIX only
+ dynamic_linker='AIX lib.a(lib.so.V)'
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='$libname$release.a $libname.a'
+ soname_spec='$libname$release$shared_ext$major'
+ ;;
+ svr4,*) # full svr4 only
+ dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)"
+ library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
+ # We do not specify a path in Import Files, so LIBPATH fires.
+ shlibpath_overrides_runpath=yes
+ ;;
+ *,yes) # both, prefer svr4
+ dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)"
+ library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
+ # unpreferred sharedlib libNAME.a needs extra handling
+ postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"'
+ postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"'
+ # We do not specify a path in Import Files, so LIBPATH fires.
+ shlibpath_overrides_runpath=yes
+ ;;
+ *,no) # both, prefer aix
+ dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)"
+ library_names_spec='$libname$release.a $libname.a'
+ soname_spec='$libname$release$shared_ext$major'
+ # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling
+ postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)'
+ postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"'
+ ;;
+ esac
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ case $host_cpu in
+ powerpc)
+ # Since July 2007 AmigaOS4 officially supports .so libraries.
+ # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ ;;
+ m68k)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+ esac
+ ;;
+
+beos*)
+ library_names_spec='$libname$shared_ext'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[45]*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32* | cegcc*)
+ version_type=windows
+ shrext_cmds=.dll
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$cc_basename in
+ yes,*)
+ # gcc
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \$file`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname~
+ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+ eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+ fi'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $RM \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
+
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"
+ ;;
+ mingw* | cegcc*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ ;;
+
+ *,cl*)
+ # Native MSVC
+ libname_spec='$name'
+ soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext'
+ library_names_spec='$libname.dll.lib'
+
+ case $build_os in
+ mingw*)
+ sys_lib_search_path_spec=
+ lt_save_ifs=$IFS
+ IFS=';'
+ for lt_path in $LIB
+ do
+ IFS=$lt_save_ifs
+ # Let DOS variable expansion print the short 8.3 style file name.
+ lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"`
+ sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path"
+ done
+ IFS=$lt_save_ifs
+ # Convert to MSYS style.
+ sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'`
+ ;;
+ cygwin*)
+ # Convert to unix form, then to dos form, then back to unix form
+ # but this time dos style (no spaces!) so that the unix form looks
+ # like /cygdrive/c/PROGRA~1:/cygdr...
+ sys_lib_search_path_spec=`cygpath --path --unix "$LIB"`
+ sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null`
+ sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ ;;
+ *)
+ sys_lib_search_path_spec=$LIB
+ if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then
+ # It is most probably a Windows format PATH.
+ sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ # FIXME: find the short name or the path components, as spaces are
+ # common. (e.g. "Program Files" -> "PROGRA~1")
+ ;;
+ esac
+
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \$file`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $RM \$dlpath'
+ shlibpath_overrides_runpath=yes
+ dynamic_linker='Win32 link.exe'
+ ;;
+
+ *)
+ # Assume MSVC wrapper
+ library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib'
+ dynamic_linker='Win32 ld.exe'
+ ;;
+ esac
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$major$shared_ext $libname$shared_ext'
+ soname_spec='$libname$release$major$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd* | dragonfly*)
+ # DragonFly does not have aout. When/if they implement a new
+ # versioning mechanism, adjust this.
+ if test -x /usr/bin/objformat; then
+ objformat=`/usr/bin/objformat`
+ else
+ case $host_os in
+ freebsd[23].*) objformat=aout ;;
+ *) objformat=elf ;;
+ esac
+ fi
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2.*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.[01]* | freebsdelf3.[01]*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ freebsd3.[2-9]* | freebsdelf3.[2-9]* | \
+ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1)
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ *) # from 4.6 on, and DragonFly
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+haiku*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ dynamic_linker="$host_os runtime_loader"
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib'
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case $host_cpu in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ if test 32 = "$HPUX_IA64_MODE"; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ sys_lib_dlsearch_path_spec=/usr/lib/hpux32
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ sys_lib_dlsearch_path_spec=/usr/lib/hpux64
+ fi
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
+ postinstall_cmds='chmod 555 $lib'
+ # or fails outright, so override atomically:
+ install_override_mode=555
+ ;;
+
+interix[3-9]*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test yes = "$lt_cv_prog_gnu_ld"; then
+ version_type=linux # correct to gnu/linux during the next big refactor
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='$libname$release$shared_ext$major'
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff"
+ sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+linux*android*)
+ version_type=none # Android doesn't support versioned libraries.
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext'
+ soname_spec='$libname$release$shared_ext'
+ finish_cmds=
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ dynamic_linker='Android linker'
+ # Don't embed -rpath directories since the linker doesn't support them.
+ hardcode_libdir_flag_spec='-L$libdir'
+ ;;
+
+# This must be glibc/ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+
+ # Some binutils ld are patched to set DT_RUNPATH
+ if ${lt_cv_shlibpath_overrides_runpath+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ lt_cv_shlibpath_overrides_runpath=no
+ save_LDFLAGS=$LDFLAGS
+ save_libdir=$libdir
+ eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \
+ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then :
+ lt_cv_shlibpath_overrides_runpath=yes
+fi
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$save_LDFLAGS
+ libdir=$save_libdir
+
+fi
+
+ shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
+
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # Add ABI-specific directories to the system library path.
+ sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib"
+
+ # Ideally, we could use ldconfig to report *all* directores which are
+ # searched for libraries, however this is still not possible. Aside from not
+ # being certain /sbin/ldconfig is available, command
+ # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64,
+ # even though it is searched at run-time. Try to do the best guess by
+ # appending ld.so.conf contents (and includes) to the search path.
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+*nto* | *qnx*)
+ version_type=qnx
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='ldqnx.so'
+ ;;
+
+openbsd* | bitrig*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec=/usr/lib
+ need_lib_prefix=no
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+ need_version=no
+ else
+ need_version=yes
+ fi
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+os2*)
+ libname_spec='$name'
+ version_type=windows
+ shrext_cmds=.dll
+ need_version=no
+ need_lib_prefix=no
+ # OS/2 can only load a DLL with a base name of 8 characters or less.
+ soname_spec='`test -n "$os2dllname" && libname="$os2dllname";
+ v=$($ECHO $release$versuffix | tr -d .-);
+ n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _);
+ $ECHO $n$v`$shared_ext'
+ library_names_spec='${libname}_dll.$libext'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=BEGINLIBPATH
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ postinstall_cmds='base_file=`basename \$file`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname~
+ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+ eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+ fi'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $RM \$dlpath'
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='$libname$release$shared_ext$major'
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+
+rdos*)
+ dynamic_linker=no
+ ;;
+
+solaris*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test yes = "$with_gnu_ld"; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.3*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec; then
+ version_type=linux # correct to gnu/linux during the next big refactor
+ library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext'
+ soname_spec='$libname$shared_ext.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ version_type=sco
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ if test yes = "$with_gnu_ld"; then
+ sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+ else
+ sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+ case $host_os in
+ sco3.2v5*)
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+ ;;
+ esac
+ fi
+ sys_lib_dlsearch_path_spec='/usr/lib'
+ ;;
+
+tpf*)
+ # TPF is a cross-target only. Preferred cross-host = GNU/Linux.
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+uts4*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5
+$as_echo "$dynamic_linker" >&6; }
+test no = "$dynamic_linker" && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test yes = "$GCC"; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then
+ sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec
+fi
+
+if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then
+ sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec
+fi
+
+# remember unaugmented sys_lib_dlsearch_path content for libtool script decls...
+configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec
+
+# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code
+func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH"
+
+# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool
+configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5
+$as_echo_n "checking how to hardcode library paths into programs... " >&6; }
+hardcode_action=
+if test -n "$hardcode_libdir_flag_spec" ||
+ test -n "$runpath_var" ||
+ test yes = "$hardcode_automatic"; then
+
+ # We can hardcode non-existent directories.
+ if test no != "$hardcode_direct" &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" &&
+ test no != "$hardcode_minus_L"; then
+ # Linking always hardcodes the temporary library directory.
+ hardcode_action=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ hardcode_action=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ hardcode_action=unsupported
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5
+$as_echo "$hardcode_action" >&6; }
+
+if test relink = "$hardcode_action" ||
+ test yes = "$inherit_rpath"; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test yes = "$shlibpath_overrides_runpath" ||
+ test no = "$enable_shared"; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+
+
+
+
+
+
+ if test yes != "$enable_dlopen"; then
+ enable_dlopen=unknown
+ enable_dlopen_self=unknown
+ enable_dlopen_self_static=unknown
+else
+ lt_cv_dlopen=no
+ lt_cv_dlopen_libs=
+
+ case $host_os in
+ beos*)
+ lt_cv_dlopen=load_add_on
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ;;
+
+ mingw* | pw32* | cegcc*)
+ lt_cv_dlopen=LoadLibrary
+ lt_cv_dlopen_libs=
+ ;;
+
+ cygwin*)
+ lt_cv_dlopen=dlopen
+ lt_cv_dlopen_libs=
+ ;;
+
+ darwin*)
+ # if libdl is installed we need to link against it
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+$as_echo_n "checking for dlopen in -ldl... " >&6; }
+if ${ac_cv_lib_dl_dlopen+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_dl_dlopen=yes
+else
+ ac_cv_lib_dl_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = xyes; then :
+ lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl
+else
+
+ lt_cv_dlopen=dyld
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+
+fi
+
+ ;;
+
+ tpf*)
+ # Don't try to run any link tests for TPF. We know it's impossible
+ # because TPF is a cross-compiler, and we know how we open DSOs.
+ lt_cv_dlopen=dlopen
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=no
+ ;;
+
+ *)
+ ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load"
+if test "x$ac_cv_func_shl_load" = xyes; then :
+ lt_cv_dlopen=shl_load
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5
+$as_echo_n "checking for shl_load in -ldld... " >&6; }
+if ${ac_cv_lib_dld_shl_load+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char shl_load ();
+int
+main ()
+{
+return shl_load ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_dld_shl_load=yes
+else
+ ac_cv_lib_dld_shl_load=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5
+$as_echo "$ac_cv_lib_dld_shl_load" >&6; }
+if test "x$ac_cv_lib_dld_shl_load" = xyes; then :
+ lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld
+else
+ ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen"
+if test "x$ac_cv_func_dlopen" = xyes; then :
+ lt_cv_dlopen=dlopen
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5
+$as_echo_n "checking for dlopen in -ldl... " >&6; }
+if ${ac_cv_lib_dl_dlopen+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_dl_dlopen=yes
+else
+ ac_cv_lib_dl_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5
+$as_echo "$ac_cv_lib_dl_dlopen" >&6; }
+if test "x$ac_cv_lib_dl_dlopen" = xyes; then :
+ lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5
+$as_echo_n "checking for dlopen in -lsvld... " >&6; }
+if ${ac_cv_lib_svld_dlopen+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsvld $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen ();
+int
+main ()
+{
+return dlopen ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_svld_dlopen=yes
+else
+ ac_cv_lib_svld_dlopen=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5
+$as_echo "$ac_cv_lib_svld_dlopen" >&6; }
+if test "x$ac_cv_lib_svld_dlopen" = xyes; then :
+ lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5
+$as_echo_n "checking for dld_link in -ldld... " >&6; }
+if ${ac_cv_lib_dld_dld_link+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldld $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dld_link ();
+int
+main ()
+{
+return dld_link ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_dld_dld_link=yes
+else
+ ac_cv_lib_dld_dld_link=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5
+$as_echo "$ac_cv_lib_dld_dld_link" >&6; }
+if test "x$ac_cv_lib_dld_dld_link" = xyes; then :
+ lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+
+fi
+
+ ;;
+ esac
+
+ if test no = "$lt_cv_dlopen"; then
+ enable_dlopen=no
+ else
+ enable_dlopen=yes
+ fi
+
+ case $lt_cv_dlopen in
+ dlopen)
+ save_CPPFLAGS=$CPPFLAGS
+ test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+ save_LDFLAGS=$LDFLAGS
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+ save_LIBS=$LIBS
+ LIBS="$lt_cv_dlopen_libs $LIBS"
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5
+$as_echo_n "checking whether a program can dlopen itself... " >&6; }
+if ${lt_cv_dlopen_self+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test yes = "$cross_compiling"; then :
+ lt_cv_dlopen_self=cross
+else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<_LT_EOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LT_DLGLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_DLGLOBAL DL_GLOBAL
+# else
+# define LT_DLGLOBAL 0
+# endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LT_DLLAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LT_DLLAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LT_DLLAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LT_DLLAZY_OR_NOW DL_NOW
+# else
+# define LT_DLLAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+/* When -fvisibility=hidden is used, assume the code has been annotated
+ correspondingly for the symbols needed. */
+#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+int fnord () __attribute__((visibility("default")));
+#endif
+
+int fnord () { return 42; }
+int main ()
+{
+ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+ int status = $lt_dlunknown;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
+ else
+ {
+ if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+ else puts (dlerror ());
+ }
+ /* dlclose (self); */
+ }
+ else
+ puts (dlerror ());
+
+ return status;
+}
+_LT_EOF
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then
+ (./conftest; exit; ) >&5 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+ x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;;
+ x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;;
+ x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;;
+ esac
+ else :
+ # compilation failed
+ lt_cv_dlopen_self=no
+ fi
+fi
+rm -fr conftest*
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5
+$as_echo "$lt_cv_dlopen_self" >&6; }
+
+ if test yes = "$lt_cv_dlopen_self"; then
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5
+$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; }
+if ${lt_cv_dlopen_self_static+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test yes = "$cross_compiling"; then :
+ lt_cv_dlopen_self_static=cross
+else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<_LT_EOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LT_DLGLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_DLGLOBAL DL_GLOBAL
+# else
+# define LT_DLGLOBAL 0
+# endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LT_DLLAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LT_DLLAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LT_DLLAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LT_DLLAZY_OR_NOW DL_NOW
+# else
+# define LT_DLLAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+/* When -fvisibility=hidden is used, assume the code has been annotated
+ correspondingly for the symbols needed. */
+#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+int fnord () __attribute__((visibility("default")));
+#endif
+
+int fnord () { return 42; }
+int main ()
+{
+ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+ int status = $lt_dlunknown;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
+ else
+ {
+ if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+ else puts (dlerror ());
+ }
+ /* dlclose (self); */
+ }
+ else
+ puts (dlerror ());
+
+ return status;
+}
+_LT_EOF
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then
+ (./conftest; exit; ) >&5 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+ x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;;
+ x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;;
+ x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;;
+ esac
+ else :
+ # compilation failed
+ lt_cv_dlopen_self_static=no
+ fi
+fi
+rm -fr conftest*
+
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5
+$as_echo "$lt_cv_dlopen_self_static" >&6; }
+ fi
+
+ CPPFLAGS=$save_CPPFLAGS
+ LDFLAGS=$save_LDFLAGS
+ LIBS=$save_LIBS
+ ;;
+ esac
+
+ case $lt_cv_dlopen_self in
+ yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+ *) enable_dlopen_self=unknown ;;
+ esac
+
+ case $lt_cv_dlopen_self_static in
+ yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+ *) enable_dlopen_self_static=unknown ;;
+ esac
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+striplib=
+old_striplib=
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5
+$as_echo_n "checking whether stripping libraries is possible... " >&6; }
+if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
+ test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+ test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+ case $host_os in
+ darwin*)
+ if test -n "$STRIP"; then
+ striplib="$STRIP -x"
+ old_striplib="$STRIP -S"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ fi
+ ;;
+ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ ;;
+ esac
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+ # Report what library types will actually be built
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5
+$as_echo_n "checking if libtool supports shared libraries... " >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5
+$as_echo "$can_build_shared" >&6; }
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5
+$as_echo_n "checking whether to build shared libraries... " >&6; }
+ test no = "$can_build_shared" && enable_shared=no
+
+ # On AIX, shared libraries and static libraries use the same namespace, and
+ # are all built from PIC.
+ case $host_os in
+ aix3*)
+ test yes = "$enable_shared" && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+
+ aix[4-9]*)
+ if test ia64 != "$host_cpu"; then
+ case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
+ yes,aix,yes) ;; # shared object as lib.so file only
+ yes,svr4,*) ;; # shared object as lib.so archive member only
+ yes,*) enable_static=no ;; # shared object in lib.a archive as well
+ esac
+ fi
+ ;;
+ esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5
+$as_echo "$enable_shared" >&6; }
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5
+$as_echo_n "checking whether to build static libraries... " >&6; }
+ # Make sure either enable_shared or enable_static is yes.
+ test yes = "$enable_shared" || enable_static=yes
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5
+$as_echo "$enable_static" >&6; }
+
+
+
+
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+CC=$lt_save_CC
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ac_config_commands="$ac_config_commands libtool"
+
+
+
+
+# Only expand once:
+
+
+# Extract the first word of "glib-mkenums", so it can be a program name with args.
+set dummy glib-mkenums; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_GLIB_MKENUMS+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $GLIB_MKENUMS in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_GLIB_MKENUMS="$GLIB_MKENUMS" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_GLIB_MKENUMS="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+GLIB_MKENUMS=$ac_cv_path_GLIB_MKENUMS
+if test -n "$GLIB_MKENUMS"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GLIB_MKENUMS" >&5
+$as_echo "$GLIB_MKENUMS" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+# Check Operating System
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking operating system" >&5
+$as_echo_n "checking operating system... " >&6; }
+case "$host" in
+ *-*-*mingw*|*-*-*cygwin*)
+ platform=win32
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $platform" >&5
+$as_echo "$platform" >&6; }
+ ;;
+ *)
+ platform=linux/other
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $platform" >&5
+$as_echo "$platform" >&6; }
+ ;;
+esac
+
+ if test "$platform" = "win32"; then
+ WINDOWS_TRUE=
+ WINDOWS_FALSE='#'
+else
+ WINDOWS_TRUE='#'
+ WINDOWS_FALSE=
+fi
+
+
+# Checks for compiler features
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C/C++ restrict keyword" >&5
+$as_echo_n "checking for C/C++ restrict keyword... " >&6; }
+if ${ac_cv_c_restrict+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_c_restrict=no
+ # The order here caters to the fact that C++ does not require restrict.
+ for ac_kw in __restrict __restrict__ _Restrict restrict; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+typedef int * int_ptr;
+ int foo (int_ptr $ac_kw ip) {
+ return ip[0];
+ }
+int
+main ()
+{
+int s[1];
+ int * $ac_kw t = s;
+ t[0] = 0;
+ return foo(t)
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_restrict=$ac_kw
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ test "$ac_cv_c_restrict" != no && break
+ done
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_restrict" >&5
+$as_echo "$ac_cv_c_restrict" >&6; }
+
+ case $ac_cv_c_restrict in
+ restrict) ;;
+ no) $as_echo "#define restrict /**/" >>confdefs.h
+ ;;
+ *) cat >>confdefs.h <<_ACEOF
+#define restrict $ac_cv_c_restrict
+_ACEOF
+ ;;
+ esac
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for variable-length arrays" >&5
+$as_echo_n "checking for variable-length arrays... " >&6; }
+if ${ac_cv_c_vararrays+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+static int x; char a[++x]; a[sizeof a - 1] = 0; return a[0];
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_vararrays=yes
+else
+ ac_cv_c_vararrays=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_vararrays" >&5
+$as_echo "$ac_cv_c_vararrays" >&6; }
+ if test $ac_cv_c_vararrays = yes; then
+
+$as_echo "#define HAVE_C_VARARRAYS 1" >>confdefs.h
+
+ fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable assertions" >&5
+$as_echo_n "checking whether to enable assertions... " >&6; }
+ # Check whether --enable-assert was given.
+if test "${enable_assert+set}" = set; then :
+ enableval=$enable_assert; ac_enable_assert=$enableval
+ if test "x$enableval" = xno; then :
+
+$as_echo "#define NDEBUG 1" >>confdefs.h
+
+elif test "x$enableval" != xyes; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: invalid argument supplied to --enable-assert" >&5
+$as_echo "$as_me: WARNING: invalid argument supplied to --enable-assert" >&2;}
+ ac_enable_assert=yes
+fi
+else
+ ac_enable_assert=yes
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_enable_assert" >&5
+$as_echo "$ac_enable_assert" >&6; }
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdbool.h that conforms to C99" >&5
+$as_echo_n "checking for stdbool.h that conforms to C99... " >&6; }
+if ${ac_cv_header_stdbool_h+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <stdbool.h>
+ #ifndef bool
+ "error: bool is not defined"
+ #endif
+ #ifndef false
+ "error: false is not defined"
+ #endif
+ #if false
+ "error: false is not 0"
+ #endif
+ #ifndef true
+ "error: true is not defined"
+ #endif
+ #if true != 1
+ "error: true is not 1"
+ #endif
+ #ifndef __bool_true_false_are_defined
+ "error: __bool_true_false_are_defined is not defined"
+ #endif
+
+ struct s { _Bool s: 1; _Bool t; } s;
+
+ char a[true == 1 ? 1 : -1];
+ char b[false == 0 ? 1 : -1];
+ char c[__bool_true_false_are_defined == 1 ? 1 : -1];
+ char d[(bool) 0.5 == true ? 1 : -1];
+ /* See body of main program for 'e'. */
+ char f[(_Bool) 0.0 == false ? 1 : -1];
+ char g[true];
+ char h[sizeof (_Bool)];
+ char i[sizeof s.t];
+ enum { j = false, k = true, l = false * true, m = true * 256 };
+ /* The following fails for
+ HP aC++/ANSI C B3910B A.05.55 [Dec 04 2003]. */
+ _Bool n[m];
+ char o[sizeof n == m * sizeof n[0] ? 1 : -1];
+ char p[-1 - (_Bool) 0 < 0 && -1 - (bool) 0 < 0 ? 1 : -1];
+ /* Catch a bug in an HP-UX C compiler. See
+ http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html
+ http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html
+ */
+ _Bool q = true;
+ _Bool *pq = &q;
+
+int
+main ()
+{
+
+ bool e = &s;
+ *pq |= q;
+ *pq |= ! q;
+ /* Refer to every declared value, to avoid compiler optimizations. */
+ return (!a + !b + !c + !d + !e + !f + !g + !h + !i + !!j + !k + !!l
+ + !m + !n + !o + !p + !q + !pq);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_header_stdbool_h=yes
+else
+ ac_cv_header_stdbool_h=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdbool_h" >&5
+$as_echo "$ac_cv_header_stdbool_h" >&6; }
+ ac_fn_c_check_type "$LINENO" "_Bool" "ac_cv_type__Bool" "$ac_includes_default"
+if test "x$ac_cv_type__Bool" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE__BOOL 1
+_ACEOF
+
+
+fi
+
+
+if test $ac_cv_header_stdbool_h = yes; then
+
+$as_echo "#define HAVE_STDBOOL_H 1" >>confdefs.h
+
+fi
+
+
+
+$as_echo "#define NICEAPI_EXPORT " >>confdefs.h
+
+for ac_header in arpa/inet.h net/in.h netdb.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in ifaddrs.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "ifaddrs.h" "ac_cv_header_ifaddrs_h" "$ac_includes_default"
+if test "x$ac_cv_header_ifaddrs_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_IFADDRS_H 1
+_ACEOF
+ for ac_func in getifaddrs
+do :
+ ac_fn_c_check_func "$LINENO" "getifaddrs" "ac_cv_func_getifaddrs"
+if test "x$ac_cv_func_getifaddrs" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_GETIFADDRS 1
+_ACEOF
+
+$as_echo "#define HAVE_GETIFADDRS 1" >>confdefs.h
+
+fi
+done
+
+fi
+
+done
+
+ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default"
+if test "x$ac_cv_type_size_t" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_SIZE_T 1
+_ACEOF
+
+
+fi
+ac_fn_c_check_type "$LINENO" "ssize_t" "ac_cv_type_ssize_t" "$ac_includes_default"
+if test "x$ac_cv_type_ssize_t" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_SSIZE_T 1
+_ACEOF
+
+
+fi
+
+
+# Also put matching version in LIBNICE_CFLAGS
+GLIB_REQ=2.48
+
+LIBNICE_CFLAGS="-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_44 -DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_44"
+
+# Check whether --enable-compile-warnings was given.
+if test "${enable_compile_warnings+set}" = set; then :
+ enableval=$enable_compile_warnings;
+else
+ if test "$LIBNICE_RELEASE" = "yes"; then :
+ enable_compile_warnings="yes"
+else
+ enable_compile_warnings="error"
+fi
+fi
+
+
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror -fno-strict-aliasing" >&5
+$as_echo_n "checking to see if compiler understands -Werror -fno-strict-aliasing... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -fno-strict-aliasing"
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ flag_ok=yes
+else
+ flag_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ LIBNICE_CFLAGS="$LIBNICE_CFLAGS -fno-strict-aliasing"
+ true
+ else
+
+ true
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5
+$as_echo "$flag_ok" >&6; }
+
+
+
+if test "$enable_compile_warnings" != "no"; then :
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror -Wall" >&5
+$as_echo_n "checking to see if compiler understands -Werror -Wall... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -Wall"
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ flag_ok=yes
+else
+ flag_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ LIBNICE_CFLAGS="$LIBNICE_CFLAGS -Wall"
+ true
+ else
+
+ true
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5
+$as_echo "$flag_ok" >&6; }
+
+
+
+fi
+if test "x$enable_compile_warnings" != "xno" -a \
+ "x$enable_compile_warnings" != "xminimum"; then :
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror -Wextra" >&5
+$as_echo_n "checking to see if compiler understands -Werror -Wextra... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -Wextra"
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ flag_ok=yes
+else
+ flag_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ LIBNICE_CFLAGS="$LIBNICE_CFLAGS -Wextra"
+ true
+ else
+
+ true
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5
+$as_echo "$flag_ok" >&6; }
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror -Wundef" >&5
+$as_echo_n "checking to see if compiler understands -Werror -Wundef... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -Wundef"
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ flag_ok=yes
+else
+ flag_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ LIBNICE_CFLAGS="$LIBNICE_CFLAGS -Wundef"
+ true
+ else
+
+ true
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5
+$as_echo "$flag_ok" >&6; }
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror -Wnested-externs" >&5
+$as_echo_n "checking to see if compiler understands -Werror -Wnested-externs... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -Wnested-externs"
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ flag_ok=yes
+else
+ flag_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ LIBNICE_CFLAGS="$LIBNICE_CFLAGS -Wnested-externs"
+ true
+ else
+
+ true
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5
+$as_echo "$flag_ok" >&6; }
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror -Wwrite-strings" >&5
+$as_echo_n "checking to see if compiler understands -Werror -Wwrite-strings... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -Wwrite-strings"
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ flag_ok=yes
+else
+ flag_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ LIBNICE_CFLAGS="$LIBNICE_CFLAGS -Wwrite-strings"
+ true
+ else
+
+ true
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5
+$as_echo "$flag_ok" >&6; }
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror -Wpointer-arith" >&5
+$as_echo_n "checking to see if compiler understands -Werror -Wpointer-arith... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -Wpointer-arith"
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ flag_ok=yes
+else
+ flag_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ LIBNICE_CFLAGS="$LIBNICE_CFLAGS -Wpointer-arith"
+ true
+ else
+
+ true
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5
+$as_echo "$flag_ok" >&6; }
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror -Wmissing-declarations" >&5
+$as_echo_n "checking to see if compiler understands -Werror -Wmissing-declarations... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -Wmissing-declarations"
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ flag_ok=yes
+else
+ flag_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ LIBNICE_CFLAGS="$LIBNICE_CFLAGS -Wmissing-declarations"
+ true
+ else
+
+ true
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5
+$as_echo "$flag_ok" >&6; }
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror -Wmissing-prototypes" >&5
+$as_echo_n "checking to see if compiler understands -Werror -Wmissing-prototypes... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -Wmissing-prototypes"
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ flag_ok=yes
+else
+ flag_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ LIBNICE_CFLAGS="$LIBNICE_CFLAGS -Wmissing-prototypes"
+ true
+ else
+
+ true
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5
+$as_echo "$flag_ok" >&6; }
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror -Wstrict-prototypes" >&5
+$as_echo_n "checking to see if compiler understands -Werror -Wstrict-prototypes... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -Wstrict-prototypes"
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ flag_ok=yes
+else
+ flag_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ LIBNICE_CFLAGS="$LIBNICE_CFLAGS -Wstrict-prototypes"
+ true
+ else
+
+ true
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5
+$as_echo "$flag_ok" >&6; }
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror -Wredundant-decls" >&5
+$as_echo_n "checking to see if compiler understands -Werror -Wredundant-decls... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -Wredundant-decls"
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ flag_ok=yes
+else
+ flag_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ LIBNICE_CFLAGS="$LIBNICE_CFLAGS -Wredundant-decls"
+ true
+ else
+
+ true
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5
+$as_echo "$flag_ok" >&6; }
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror -Wno-unused-parameter" >&5
+$as_echo_n "checking to see if compiler understands -Werror -Wno-unused-parameter... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -Wno-unused-parameter"
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ flag_ok=yes
+else
+ flag_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ LIBNICE_CFLAGS="$LIBNICE_CFLAGS -Wno-unused-parameter"
+ true
+ else
+
+ true
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5
+$as_echo "$flag_ok" >&6; }
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror -Wno-missing-field-initializers" >&5
+$as_echo_n "checking to see if compiler understands -Werror -Wno-missing-field-initializers... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -Wno-missing-field-initializers"
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ flag_ok=yes
+else
+ flag_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ LIBNICE_CFLAGS="$LIBNICE_CFLAGS -Wno-missing-field-initializers"
+ true
+ else
+
+ true
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5
+$as_echo "$flag_ok" >&6; }
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror -Wdeclaration-after-statement" >&5
+$as_echo_n "checking to see if compiler understands -Werror -Wdeclaration-after-statement... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -Wdeclaration-after-statement"
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ flag_ok=yes
+else
+ flag_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ LIBNICE_CFLAGS="$LIBNICE_CFLAGS -Wdeclaration-after-statement"
+ true
+ else
+
+ true
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5
+$as_echo "$flag_ok" >&6; }
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror -Wformat=2" >&5
+$as_echo_n "checking to see if compiler understands -Werror -Wformat=2... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -Wformat=2"
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ flag_ok=yes
+else
+ flag_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ LIBNICE_CFLAGS="$LIBNICE_CFLAGS -Wformat=2"
+ true
+ else
+
+ true
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5
+$as_echo "$flag_ok" >&6; }
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror -Wold-style-definition" >&5
+$as_echo_n "checking to see if compiler understands -Werror -Wold-style-definition... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -Wold-style-definition"
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ flag_ok=yes
+else
+ flag_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ LIBNICE_CFLAGS="$LIBNICE_CFLAGS -Wold-style-definition"
+ true
+ else
+
+ true
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5
+$as_echo "$flag_ok" >&6; }
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror -Wcast-align" >&5
+$as_echo_n "checking to see if compiler understands -Werror -Wcast-align... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -Wcast-align"
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ flag_ok=yes
+else
+ flag_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ LIBNICE_CFLAGS="$LIBNICE_CFLAGS -Wcast-align"
+ true
+ else
+
+ true
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5
+$as_echo "$flag_ok" >&6; }
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror -Wformat-nonliteral" >&5
+$as_echo_n "checking to see if compiler understands -Werror -Wformat-nonliteral... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -Wformat-nonliteral"
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ flag_ok=yes
+else
+ flag_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ LIBNICE_CFLAGS="$LIBNICE_CFLAGS -Wformat-nonliteral"
+ true
+ else
+
+ true
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5
+$as_echo "$flag_ok" >&6; }
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror -Wformat-security" >&5
+$as_echo_n "checking to see if compiler understands -Werror -Wformat-security... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -Wformat-security"
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ flag_ok=yes
+else
+ flag_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ LIBNICE_CFLAGS="$LIBNICE_CFLAGS -Wformat-security"
+ true
+ else
+
+ true
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5
+$as_echo "$flag_ok" >&6; }
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror -Wno-cast-function-type" >&5
+$as_echo_n "checking to see if compiler understands -Werror -Wno-cast-function-type... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -Wno-cast-function-type"
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ flag_ok=yes
+else
+ flag_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ LIBNICE_CFLAGS="$LIBNICE_CFLAGS -Wno-cast-function-type"
+ true
+ else
+
+ true
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5
+$as_echo "$flag_ok" >&6; }
+
+
+
+fi
+if test "$enable_compile_warnings" = "yes" -o \
+ "$enable_compile_warnings" = "maximum" -o \
+ "$enable_compile_warnings" = "error"; then :
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror -Wsign-compare" >&5
+$as_echo_n "checking to see if compiler understands -Werror -Wsign-compare... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -Wsign-compare"
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ flag_ok=yes
+else
+ flag_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ LIBNICE_CFLAGS="$LIBNICE_CFLAGS -Wsign-compare"
+ true
+ else
+
+ true
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5
+$as_echo "$flag_ok" >&6; }
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror -Wstrict-aliasing" >&5
+$as_echo_n "checking to see if compiler understands -Werror -Wstrict-aliasing... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -Wstrict-aliasing"
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ flag_ok=yes
+else
+ flag_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ LIBNICE_CFLAGS="$LIBNICE_CFLAGS -Wstrict-aliasing"
+ true
+ else
+
+ true
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5
+$as_echo "$flag_ok" >&6; }
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror -Wshadow" >&5
+$as_echo_n "checking to see if compiler understands -Werror -Wshadow... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -Wshadow"
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ flag_ok=yes
+else
+ flag_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ LIBNICE_CFLAGS="$LIBNICE_CFLAGS -Wshadow"
+ true
+ else
+
+ true
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5
+$as_echo "$flag_ok" >&6; }
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror -Winline" >&5
+$as_echo_n "checking to see if compiler understands -Werror -Winline... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -Winline"
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ flag_ok=yes
+else
+ flag_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ LIBNICE_CFLAGS="$LIBNICE_CFLAGS -Winline"
+ true
+ else
+
+ true
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5
+$as_echo "$flag_ok" >&6; }
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror -Wpacked" >&5
+$as_echo_n "checking to see if compiler understands -Werror -Wpacked... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -Wpacked"
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ flag_ok=yes
+else
+ flag_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ LIBNICE_CFLAGS="$LIBNICE_CFLAGS -Wpacked"
+ true
+ else
+
+ true
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5
+$as_echo "$flag_ok" >&6; }
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror -Wmissing-format-attribute" >&5
+$as_echo_n "checking to see if compiler understands -Werror -Wmissing-format-attribute... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -Wmissing-format-attribute"
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ flag_ok=yes
+else
+ flag_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ LIBNICE_CFLAGS="$LIBNICE_CFLAGS -Wmissing-format-attribute"
+ true
+ else
+
+ true
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5
+$as_echo "$flag_ok" >&6; }
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror -Winit-self" >&5
+$as_echo_n "checking to see if compiler understands -Werror -Winit-self... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -Winit-self"
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ flag_ok=yes
+else
+ flag_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ LIBNICE_CFLAGS="$LIBNICE_CFLAGS -Winit-self"
+ true
+ else
+
+ true
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5
+$as_echo "$flag_ok" >&6; }
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror -Wredundant-decls" >&5
+$as_echo_n "checking to see if compiler understands -Werror -Wredundant-decls... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -Wredundant-decls"
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ flag_ok=yes
+else
+ flag_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ LIBNICE_CFLAGS="$LIBNICE_CFLAGS -Wredundant-decls"
+ true
+ else
+
+ true
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5
+$as_echo "$flag_ok" >&6; }
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror -Wmissing-include-dirs" >&5
+$as_echo_n "checking to see if compiler understands -Werror -Wmissing-include-dirs... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -Wmissing-include-dirs"
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ flag_ok=yes
+else
+ flag_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ LIBNICE_CFLAGS="$LIBNICE_CFLAGS -Wmissing-include-dirs"
+ true
+ else
+
+ true
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5
+$as_echo "$flag_ok" >&6; }
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror -Wunused-but-set-variable" >&5
+$as_echo_n "checking to see if compiler understands -Werror -Wunused-but-set-variable... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -Wunused-but-set-variable"
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ flag_ok=yes
+else
+ flag_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ LIBNICE_CFLAGS="$LIBNICE_CFLAGS -Wunused-but-set-variable"
+ true
+ else
+
+ true
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5
+$as_echo "$flag_ok" >&6; }
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror -Warray-bounds" >&5
+$as_echo_n "checking to see if compiler understands -Werror -Warray-bounds... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -Warray-bounds"
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ flag_ok=yes
+else
+ flag_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ LIBNICE_CFLAGS="$LIBNICE_CFLAGS -Warray-bounds"
+ true
+ else
+
+ true
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5
+$as_echo "$flag_ok" >&6; }
+
+
+
+fi
+if test "$enable_compile_warnings" = "maximum" -o \
+ "$enable_compile_warnings" = "error"; then :
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror -Wswitch-default" >&5
+$as_echo_n "checking to see if compiler understands -Werror -Wswitch-default... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -Wswitch-default"
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ flag_ok=yes
+else
+ flag_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ LIBNICE_CFLAGS="$LIBNICE_CFLAGS -Wswitch-default"
+ true
+ else
+
+ true
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5
+$as_echo "$flag_ok" >&6; }
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror -Waggregate-return" >&5
+$as_echo_n "checking to see if compiler understands -Werror -Waggregate-return... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -Waggregate-return"
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ flag_ok=yes
+else
+ flag_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ LIBNICE_CFLAGS="$LIBNICE_CFLAGS -Waggregate-return"
+ true
+ else
+
+ true
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5
+$as_echo "$flag_ok" >&6; }
+
+
+
+fi
+if test "x$enable_compile_warnings" = "xerror"; then :
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror -Werror" >&5
+$as_echo_n "checking to see if compiler understands -Werror -Werror... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -Werror"
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ flag_ok=yes
+else
+ flag_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ LIBNICE_CFLAGS="$LIBNICE_CFLAGS -Werror"
+ true
+ else
+
+ true
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5
+$as_echo "$flag_ok" >&6; }
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking to see if compiler understands -Werror -Wno-suggest-attribute=format" >&5
+$as_echo_n "checking to see if compiler understands -Werror -Wno-suggest-attribute=format... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Werror -Wno-suggest-attribute=format"
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ flag_ok=yes
+else
+ flag_ok=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ LIBNICE_CFLAGS="$LIBNICE_CFLAGS -Wno-suggest-attribute=format"
+ true
+ else
+
+ true
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag_ok" >&5
+$as_echo "$flag_ok" >&6; }
+
+
+
+fi
+
+#
+# Fixes for Solaris
+#
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing inet_pton" >&5
+$as_echo_n "checking for library containing inet_pton... " >&6; }
+if ${ac_cv_search_inet_pton+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char inet_pton ();
+int
+main ()
+{
+return inet_pton ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' nsl; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_inet_pton=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_inet_pton+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_inet_pton+:} false; then :
+
+else
+ ac_cv_search_inet_pton=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_inet_pton" >&5
+$as_echo "$ac_cv_search_inet_pton" >&6; }
+ac_res=$ac_cv_search_inet_pton
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing socket" >&5
+$as_echo_n "checking for library containing socket... " >&6; }
+if ${ac_cv_search_socket+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char socket ();
+int
+main ()
+{
+return socket ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' socket inet; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_socket=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_socket+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_socket+:} false; then :
+
+else
+ ac_cv_search_socket=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_socket" >&5
+$as_echo "$ac_cv_search_socket" >&6; }
+ac_res=$ac_cv_search_socket
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+case $host in
+ *-*-solaris* )
+
+$as_echo "#define _XOPEN_SOURCE 600" >>confdefs.h
+
+
+$as_echo "#define __EXTENSIONS__ 1" >>confdefs.h
+
+ ;;
+esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: set LIBNICE_CFLAGS to $LIBNICE_CFLAGS" >&5
+$as_echo "$as_me: set LIBNICE_CFLAGS to $LIBNICE_CFLAGS" >&6;}
+
+# Checks for libraries.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
+$as_echo_n "checking for clock_gettime in -lrt... " >&6; }
+if ${ac_cv_lib_rt_clock_gettime+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lrt $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char clock_gettime ();
+int
+main ()
+{
+return clock_gettime ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_rt_clock_gettime=yes
+else
+ ac_cv_lib_rt_clock_gettime=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
+$as_echo "$ac_cv_lib_rt_clock_gettime" >&6; }
+if test "x$ac_cv_lib_rt_clock_gettime" = xyes; then :
+ LIBRT="-lrt"
+else
+ LIBRT=""
+fi
+
+for ac_func in poll
+do :
+ ac_fn_c_check_func "$LINENO" "poll" "ac_cv_func_poll"
+if test "x$ac_cv_func_poll" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_POLL 1
+_ACEOF
+
+fi
+done
+
+
+
+# Dependencies
+
+NICE_PACKAGES_PUBLIC="glib-2.0 >= $GLIB_REQ gio-2.0 >= $GLIB_REQ gobject-2.0 >= $GLIB_REQ"
+NICE_PACKAGES_PRIVATE="gthread-2.0"
+
+
+
+
+
+
+
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
+set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PKG_CONFIG+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $PKG_CONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+PKG_CONFIG=$ac_cv_path_PKG_CONFIG
+if test -n "$PKG_CONFIG"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
+$as_echo "$PKG_CONFIG" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_path_PKG_CONFIG"; then
+ ac_pt_PKG_CONFIG=$PKG_CONFIG
+ # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $ac_pt_PKG_CONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG
+if test -n "$ac_pt_PKG_CONFIG"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5
+$as_echo "$ac_pt_PKG_CONFIG" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_pt_PKG_CONFIG" = x; then
+ PKG_CONFIG=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ PKG_CONFIG=$ac_pt_PKG_CONFIG
+ fi
+else
+ PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
+fi
+
+fi
+if test -n "$PKG_CONFIG"; then
+ _pkg_min_version=0.9.0
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5
+$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; }
+ if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ PKG_CONFIG=""
+ fi
+fi
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GLIB" >&5
+$as_echo_n "checking for GLIB... " >&6; }
+
+if test -n "$GLIB_CFLAGS"; then
+ pkg_cv_GLIB_CFLAGS="$GLIB_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$NICE_PACKAGES_PUBLIC \$NICE_PACKAGES_PRIVATE\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "$NICE_PACKAGES_PUBLIC $NICE_PACKAGES_PRIVATE") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_GLIB_CFLAGS=`$PKG_CONFIG --cflags "$NICE_PACKAGES_PUBLIC $NICE_PACKAGES_PRIVATE" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$GLIB_LIBS"; then
+ pkg_cv_GLIB_LIBS="$GLIB_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$NICE_PACKAGES_PUBLIC \$NICE_PACKAGES_PRIVATE\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "$NICE_PACKAGES_PUBLIC $NICE_PACKAGES_PRIVATE") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_GLIB_LIBS=`$PKG_CONFIG --libs "$NICE_PACKAGES_PUBLIC $NICE_PACKAGES_PRIVATE" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi
+ if test $_pkg_short_errors_supported = yes; then
+ GLIB_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$NICE_PACKAGES_PUBLIC $NICE_PACKAGES_PRIVATE" 2>&1`
+ else
+ GLIB_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$NICE_PACKAGES_PUBLIC $NICE_PACKAGES_PRIVATE" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$GLIB_PKG_ERRORS" >&5
+
+ as_fn_error $? "Package requirements ($NICE_PACKAGES_PUBLIC $NICE_PACKAGES_PRIVATE) were not met:
+
+$GLIB_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+Alternatively, you may set the environment variables GLIB_CFLAGS
+and GLIB_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details." "$LINENO" 5
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+Alternatively, you may set the environment variables GLIB_CFLAGS
+and GLIB_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ GLIB_CFLAGS=$pkg_cv_GLIB_CFLAGS
+ GLIB_LIBS=$pkg_cv_GLIB_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+
+
+# Check whether --with-crypto-library was given.
+if test "${with_crypto_library+set}" = set; then :
+ withval=$with_crypto_library; with_crypto_library=${withval}
+else
+ with_crypto_library=auto
+fi
+
+
+
+if test "$with_crypto_library" != "openssl"; then :
+
+ GNUTLS_PACKAGES_PRIVATE="gnutls >= 2.12.0"
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNUTLS" >&5
+$as_echo_n "checking for GNUTLS... " >&6; }
+
+if test -n "$GNUTLS_CFLAGS"; then
+ pkg_cv_GNUTLS_CFLAGS="$GNUTLS_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$GNUTLS_PACKAGES_PRIVATE\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "$GNUTLS_PACKAGES_PRIVATE") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_GNUTLS_CFLAGS=`$PKG_CONFIG --cflags "$GNUTLS_PACKAGES_PRIVATE" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$GNUTLS_LIBS"; then
+ pkg_cv_GNUTLS_LIBS="$GNUTLS_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$GNUTLS_PACKAGES_PRIVATE\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "$GNUTLS_PACKAGES_PRIVATE") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_GNUTLS_LIBS=`$PKG_CONFIG --libs "$GNUTLS_PACKAGES_PRIVATE" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi
+ if test $_pkg_short_errors_supported = yes; then
+ GNUTLS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$GNUTLS_PACKAGES_PRIVATE" 2>&1`
+ else
+ GNUTLS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$GNUTLS_PACKAGES_PRIVATE" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$GNUTLS_PKG_ERRORS" >&5
+
+
+ if test "$with_crypto_library" == "gnutls"; then :
+
+ as_fn_error $? "Neither GnuTLS is not available" "$LINENO" 5
+
+
+fi
+
+
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+ if test "$with_crypto_library" == "gnutls"; then :
+
+ as_fn_error $? "Neither GnuTLS is not available" "$LINENO" 5
+
+
+fi
+
+
+else
+ GNUTLS_CFLAGS=$pkg_cv_GNUTLS_CFLAGS
+ GNUTLS_LIBS=$pkg_cv_GNUTLS_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+
+$as_echo "#define HAVE_GNUTLS 1" >>confdefs.h
+
+ GNUTLS_FOUND=yes
+ NICE_PACKAGES_PRIVATE="$NICE_PACKAGES_PRIVATE $GNUTLS_PACKAGES_PRIVATE"
+
+fi
+
+
+fi
+
+if test "x${GNUTLS_FOUND}" != "xyes"; then :
+
+
+ found=false
+
+# Check whether --with-openssl was given.
+if test "${with_openssl+set}" = set; then :
+ withval=$with_openssl;
+ case "$withval" in
+ "" | y | ye | yes | n | no)
+ as_fn_error $? "Invalid --with-openssl value" "$LINENO" 5
+ ;;
+ *) ssldirs="$withval"
+ ;;
+ esac
+
+else
+
+ # if pkg-config is installed and openssl has installed a .pc file,
+ # then use that information and don't search ssldirs
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
+set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_PKG_CONFIG+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$PKG_CONFIG"; then
+ ac_cv_prog_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_PKG_CONFIG="${ac_tool_prefix}pkg-config"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+PKG_CONFIG=$ac_cv_prog_PKG_CONFIG
+if test -n "$PKG_CONFIG"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
+$as_echo "$PKG_CONFIG" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_PKG_CONFIG"; then
+ ac_ct_PKG_CONFIG=$PKG_CONFIG
+ # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_PKG_CONFIG+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_PKG_CONFIG"; then
+ ac_cv_prog_ac_ct_PKG_CONFIG="$ac_ct_PKG_CONFIG" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_PKG_CONFIG="pkg-config"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_PKG_CONFIG=$ac_cv_prog_ac_ct_PKG_CONFIG
+if test -n "$ac_ct_PKG_CONFIG"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_PKG_CONFIG" >&5
+$as_echo "$ac_ct_PKG_CONFIG" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_PKG_CONFIG" = x; then
+ PKG_CONFIG=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ PKG_CONFIG=$ac_ct_PKG_CONFIG
+ fi
+else
+ PKG_CONFIG="$ac_cv_prog_PKG_CONFIG"
+fi
+
+ if test x"$PKG_CONFIG" != x""; then
+ OPENSSL_LDFLAGS=`$PKG_CONFIG openssl --libs-only-L 2>/dev/null`
+ if test $? = 0; then
+ OPENSSL_LIBS=`$PKG_CONFIG openssl --libs-only-l 2>/dev/null`
+ OPENSSL_INCLUDES=`$PKG_CONFIG openssl --cflags-only-I 2>/dev/null`
+ found=true
+ fi
+ fi
+
+ # no such luck; use some default ssldirs
+ if ! $found; then
+ ssldirs="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /usr"
+ fi
+
+
+fi
+
+
+
+ # note that we #include <openssl/foo.h>, so the OpenSSL headers have to be in
+ # an 'openssl' subdirectory
+
+ if ! $found; then
+ OPENSSL_INCLUDES=
+ for ssldir in $ssldirs; do
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for openssl/ssl.h in $ssldir" >&5
+$as_echo_n "checking for openssl/ssl.h in $ssldir... " >&6; }
+ if test -f "$ssldir/include/openssl/ssl.h"; then
+ OPENSSL_INCLUDES="-I$ssldir/include"
+ OPENSSL_LDFLAGS="-L$ssldir/lib"
+ OPENSSL_LIBS="-lssl -lcrypto"
+ found=true
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ break
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ fi
+ done
+
+ # if the file wasn't found, well, go ahead and try the link anyway -- maybe
+ # it will just work!
+ fi
+
+ # try the preprocessor and linker with our new flags,
+ # being careful not to pollute the global LIBS, LDFLAGS, and CPPFLAGS
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiling and linking against OpenSSL works" >&5
+$as_echo_n "checking whether compiling and linking against OpenSSL works... " >&6; }
+ echo "Trying link with OPENSSL_LDFLAGS=$OPENSSL_LDFLAGS;" \
+ "OPENSSL_LIBS=$OPENSSL_LIBS; OPENSSL_INCLUDES=$OPENSSL_INCLUDES" >&5
+
+ save_LIBS="$LIBS"
+ save_LDFLAGS="$LDFLAGS"
+ save_CPPFLAGS="$CPPFLAGS"
+ LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS"
+ LIBS="$OPENSSL_LIBS $LIBS"
+ CPPFLAGS="$OPENSSL_INCLUDES $CPPFLAGS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <openssl/ssl.h>
+int
+main ()
+{
+SSL_new(NULL)
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+
+$as_echo "#define HAVE_OPENSSL 1" >>confdefs.h
+
+ NICE_PACKAGES_PRIVATE="$NICE_PACKAGES_PRIVATE libcrypto"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: OpenSSL selected" >&5
+$as_echo "$as_me: OpenSSL selected" >&6;}
+
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+ as_fn_error $? "Neither GnuTLS or OpenSSL is available" "$LINENO" 5
+
+
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ CPPFLAGS="$save_CPPFLAGS"
+ LDFLAGS="$save_LDFLAGS"
+ LIBS="$save_LIBS"
+
+
+
+
+
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: GnuTLS selected" >&5
+$as_echo "$as_me: GnuTLS selected" >&6;}
+
+
+fi
+
+
+
+
+
+
+# Check whether --with-gstreamer was given.
+if test "${with_gstreamer+set}" = set; then :
+ withval=$with_gstreamer; with_gstreamer=${withval}
+else
+ with_gstreamer=auto
+fi
+
+
+
+# Check whether --with-gstreamer-0.10 was given.
+if test "${with_gstreamer_0_10+set}" = set; then :
+ withval=$with_gstreamer_0_10; with_gstreamer010=${withval}
+else
+ with_gstreamer010=auto
+fi
+
+
+if test "$with_gstreamer" != no; then :
+
+
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GST" >&5
+$as_echo_n "checking for GST... " >&6; }
+
+if test -n "$GST_CFLAGS"; then
+ pkg_cv_GST_CFLAGS="$GST_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"
+ gstreamer-1.0 >= 0.11.91
+ gstreamer-base-1.0 >= 0.11.91
+ \""; } >&5
+ ($PKG_CONFIG --exists --print-errors "
+ gstreamer-1.0 >= 0.11.91
+ gstreamer-base-1.0 >= 0.11.91
+ ") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_GST_CFLAGS=`$PKG_CONFIG --cflags "
+ gstreamer-1.0 >= 0.11.91
+ gstreamer-base-1.0 >= 0.11.91
+ " 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$GST_LIBS"; then
+ pkg_cv_GST_LIBS="$GST_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"
+ gstreamer-1.0 >= 0.11.91
+ gstreamer-base-1.0 >= 0.11.91
+ \""; } >&5
+ ($PKG_CONFIG --exists --print-errors "
+ gstreamer-1.0 >= 0.11.91
+ gstreamer-base-1.0 >= 0.11.91
+ ") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_GST_LIBS=`$PKG_CONFIG --libs "
+ gstreamer-1.0 >= 0.11.91
+ gstreamer-base-1.0 >= 0.11.91
+ " 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi
+ if test $_pkg_short_errors_supported = yes; then
+ GST_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "
+ gstreamer-1.0 >= 0.11.91
+ gstreamer-base-1.0 >= 0.11.91
+ " 2>&1`
+ else
+ GST_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "
+ gstreamer-1.0 >= 0.11.91
+ gstreamer-base-1.0 >= 0.11.91
+ " 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$GST_PKG_ERRORS" >&5
+
+
+ if test "$with_gstreamer" = yes; then :
+
+ as_fn_error $? "GStreamer 1.0 support was requested but GStreamer 1.0 libraries are not available" "$LINENO" 5
+
+fi
+
+ with_gstreamer=no
+
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+ if test "$with_gstreamer" = yes; then :
+
+ as_fn_error $? "GStreamer 1.0 support was requested but GStreamer 1.0 libraries are not available" "$LINENO" 5
+
+fi
+
+ with_gstreamer=no
+
+else
+ GST_CFLAGS=$pkg_cv_GST_CFLAGS
+ GST_LIBS=$pkg_cv_GST_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+ with_gstreamer=yes
+ GST_MAJORMINOR=1.0
+ gstplugindir="\$(libdir)/gstreamer-$GST_MAJORMINOR"
+
+fi
+
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GST_CHECK" >&5
+$as_echo_n "checking for GST_CHECK... " >&6; }
+
+if test -n "$GST_CHECK_CFLAGS"; then
+ pkg_cv_GST_CHECK_CFLAGS="$GST_CHECK_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"
+ gstreamer-check-1.0 >= 0.11.91
+ \""; } >&5
+ ($PKG_CONFIG --exists --print-errors "
+ gstreamer-check-1.0 >= 0.11.91
+ ") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_GST_CHECK_CFLAGS=`$PKG_CONFIG --cflags "
+ gstreamer-check-1.0 >= 0.11.91
+ " 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$GST_CHECK_LIBS"; then
+ pkg_cv_GST_CHECK_LIBS="$GST_CHECK_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"
+ gstreamer-check-1.0 >= 0.11.91
+ \""; } >&5
+ ($PKG_CONFIG --exists --print-errors "
+ gstreamer-check-1.0 >= 0.11.91
+ ") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_GST_CHECK_LIBS=`$PKG_CONFIG --libs "
+ gstreamer-check-1.0 >= 0.11.91
+ " 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi
+ if test $_pkg_short_errors_supported = yes; then
+ GST_CHECK_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "
+ gstreamer-check-1.0 >= 0.11.91
+ " 2>&1`
+ else
+ GST_CHECK_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "
+ gstreamer-check-1.0 >= 0.11.91
+ " 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$GST_CHECK_PKG_ERRORS" >&5
+
+
+ have_gst_check=no
+
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+ have_gst_check=no
+
+else
+ GST_CHECK_CFLAGS=$pkg_cv_GST_CHECK_CFLAGS
+ GST_CHECK_LIBS=$pkg_cv_GST_CHECK_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+ have_gst_check=yes
+
+fi
+
+fi
+
+if test "$with_gstreamer010" != no; then :
+
+
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GST010" >&5
+$as_echo_n "checking for GST010... " >&6; }
+
+if test -n "$GST010_CFLAGS"; then
+ pkg_cv_GST010_CFLAGS="$GST010_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"
+ gstreamer-0.10 >= 0.10.10
+ gstreamer-base-0.10 >= 0.10.10
+ \""; } >&5
+ ($PKG_CONFIG --exists --print-errors "
+ gstreamer-0.10 >= 0.10.10
+ gstreamer-base-0.10 >= 0.10.10
+ ") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_GST010_CFLAGS=`$PKG_CONFIG --cflags "
+ gstreamer-0.10 >= 0.10.10
+ gstreamer-base-0.10 >= 0.10.10
+ " 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$GST010_LIBS"; then
+ pkg_cv_GST010_LIBS="$GST010_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"
+ gstreamer-0.10 >= 0.10.10
+ gstreamer-base-0.10 >= 0.10.10
+ \""; } >&5
+ ($PKG_CONFIG --exists --print-errors "
+ gstreamer-0.10 >= 0.10.10
+ gstreamer-base-0.10 >= 0.10.10
+ ") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_GST010_LIBS=`$PKG_CONFIG --libs "
+ gstreamer-0.10 >= 0.10.10
+ gstreamer-base-0.10 >= 0.10.10
+ " 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi
+ if test $_pkg_short_errors_supported = yes; then
+ GST010_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "
+ gstreamer-0.10 >= 0.10.10
+ gstreamer-base-0.10 >= 0.10.10
+ " 2>&1`
+ else
+ GST010_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "
+ gstreamer-0.10 >= 0.10.10
+ gstreamer-base-0.10 >= 0.10.10
+ " 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$GST010_PKG_ERRORS" >&5
+
+
+ if test "$with_gstreamer010" = yes; then :
+
+ as_fn_error $? "GStreamer 0.10 support was requested but GStreamer 0.10 libraries are not available" "$LINENO" 5
+
+fi
+
+ with_gstreamer010=no
+
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+ if test "$with_gstreamer010" = yes; then :
+
+ as_fn_error $? "GStreamer 0.10 support was requested but GStreamer 0.10 libraries are not available" "$LINENO" 5
+
+fi
+
+ with_gstreamer010=no
+
+else
+ GST010_CFLAGS=$pkg_cv_GST010_CFLAGS
+ GST010_LIBS=$pkg_cv_GST010_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+ with_gstreamer010=yes
+ GST_MAJORMINOR=0.10
+ gstplugin010dir="\$(libdir)/gstreamer-$GST_MAJORMINOR"
+
+fi
+
+fi
+
+
+
+
+ if test "$with_gstreamer" = yes; then
+ WITH_GSTREAMER_TRUE=
+ WITH_GSTREAMER_FALSE='#'
+else
+ WITH_GSTREAMER_TRUE='#'
+ WITH_GSTREAMER_FALSE=
+fi
+
+ if test "$have_gst_check" = yes; then
+ HAVE_GST_CHECK_TRUE=
+ HAVE_GST_CHECK_FALSE='#'
+else
+ HAVE_GST_CHECK_TRUE='#'
+ HAVE_GST_CHECK_FALSE=
+fi
+
+ if test "$with_gstreamer010" = yes; then
+ WITH_GSTREAMER010_TRUE=
+ WITH_GSTREAMER010_FALSE='#'
+else
+ WITH_GSTREAMER010_TRUE='#'
+ WITH_GSTREAMER010_FALSE=
+fi
+
+
+GUPNP_IGD_REQUIRED=0.2.4
+
+# Check whether --enable-gupnp was given.
+if test "${enable_gupnp+set}" = set; then :
+ enableval=$enable_gupnp; case "${enableval}" in
+ yes) WANT_GUPNP=yes ;;
+ no) WANT_GUPNP=no ;;
+ *) as_fn_error $? "bad value ${enableval} for --enable-gupnp" "$LINENO" 5 ;;
+ esac
+else
+ WANT_GUPNP=test
+fi
+
+
+GUPNP_PACKAGES_PUBLIC=""
+GUPNP_PACKAGES_PRIVATE="gupnp-igd-1.0 >= $GUPNP_IGD_REQUIRED"
+GUPNP_PACKAGES="$GUPNP_PACKAGES_PUBLIC $GUPNP_PACKAGES_PRIVATE"
+
+HAVE_GUPNP=no
+if test "x$WANT_GUPNP" != "xno"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GUPNP" >&5
+$as_echo_n "checking for GUPNP... " >&6; }
+
+if test -n "$GUPNP_CFLAGS"; then
+ pkg_cv_GUPNP_CFLAGS="$GUPNP_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$GUPNP_PACKAGES\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "$GUPNP_PACKAGES") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_GUPNP_CFLAGS=`$PKG_CONFIG --cflags "$GUPNP_PACKAGES" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$GUPNP_LIBS"; then
+ pkg_cv_GUPNP_LIBS="$GUPNP_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$GUPNP_PACKAGES\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "$GUPNP_PACKAGES") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_GUPNP_LIBS=`$PKG_CONFIG --libs "$GUPNP_PACKAGES" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi
+ if test $_pkg_short_errors_supported = yes; then
+ GUPNP_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$GUPNP_PACKAGES" 2>&1`
+ else
+ GUPNP_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$GUPNP_PACKAGES" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$GUPNP_PKG_ERRORS" >&5
+
+ HAVE_GUPNP=no
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ HAVE_GUPNP=no
+else
+ GUPNP_CFLAGS=$pkg_cv_GUPNP_CFLAGS
+ GUPNP_LIBS=$pkg_cv_GUPNP_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ HAVE_GUPNP=yes
+fi
+fi
+if test "x$WANT_GUPNP" = "xyes" && test "x$HAVE_GUPNP" = "xno"; then
+ as_fn_error $? "Requested GUPnP IGD, but it is not available" "$LINENO" 5
+fi
+
+if test "x$HAVE_GUPNP" = "xyes"; then
+
+$as_echo "#define HAVE_GUPNP /**/" >>confdefs.h
+
+ UPNP_ENABLED="true"
+else
+ GUPNP_PACKAGES_PUBLIC=""
+ GUPNP_PACKAGES_PRIVATE=""
+ GUPNP_PACKAGES=""
+fi
+
+
+
+
+
+
+
+
+# Check whether --enable-coverage was given.
+if test "${enable_coverage+set}" = set; then :
+ enableval=$enable_coverage;
+else
+ enable_coverage="no"
+fi
+
+if test "${enable_coverage}" != "no"; then :
+
+ CFLAGS="${CFLAGS} -g -O0 -fprofile-arcs -ftest-coverage"
+ LDFLAGS="-lgcov"
+ CCACHE_DISABLE=1
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static plugins or not" >&5
+$as_echo_n "checking whether to build static plugins or not... " >&6; }
+# Check whether --enable-static-plugins was given.
+if test "${enable_static_plugins+set}" = set; then :
+ enableval=$enable_static_plugins; case $enableval in #(
+ no) :
+ ;; #(
+ yes) :
+ ;; #(
+ *) :
+ as_fn_error $? "bad value \"$enableval\" for --enable-static-plugins" "$LINENO" 5 ;;
+esac
+else
+ enable_static_plugins=no
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static_plugins" >&5
+$as_echo "$enable_static_plugins" >&6; }
+if test "x$enable_static_plugins" = xyes; then
+
+$as_echo "#define GST_PLUGIN_BUILD_STATIC 1" >>confdefs.h
+
+fi
+ if test "x$enable_static_plugins" = "xyes"; then
+ GST_PLUGIN_BUILD_STATIC_TRUE=
+ GST_PLUGIN_BUILD_STATIC_FALSE='#'
+else
+ GST_PLUGIN_BUILD_STATIC_TRUE='#'
+ GST_PLUGIN_BUILD_STATIC_FALSE=
+fi
+
+
+case $host_os in
+ solaris*)
+ LDFLAGS="$LDFLAGS -lsocket -lnsl"
+ ;;
+ *)
+ ;;
+esac
+
+# check for gtk-doc
+
+
+
+
+ gtk_doc_requires="gtk-doc >= 1.10"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gtk-doc" >&5
+$as_echo_n "checking for gtk-doc... " >&6; }
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$gtk_doc_requires\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "$gtk_doc_requires") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ have_gtk_doc=yes
+else
+ have_gtk_doc=no
+fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_gtk_doc" >&5
+$as_echo "$have_gtk_doc" >&6; }
+
+ if test "$have_gtk_doc" = "no"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING:
+ You will not be able to create source packages with 'make dist'
+ because $gtk_doc_requires is not found." >&5
+$as_echo "$as_me: WARNING:
+ You will not be able to create source packages with 'make dist'
+ because $gtk_doc_requires is not found." >&2;}
+ fi
+
+ # Extract the first word of "gtkdoc-check", so it can be a program name with args.
+set dummy gtkdoc-check; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_GTKDOC_CHECK+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$GTKDOC_CHECK"; then
+ ac_cv_prog_GTKDOC_CHECK="$GTKDOC_CHECK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_GTKDOC_CHECK="gtkdoc-check.test"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+GTKDOC_CHECK=$ac_cv_prog_GTKDOC_CHECK
+if test -n "$GTKDOC_CHECK"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GTKDOC_CHECK" >&5
+$as_echo "$GTKDOC_CHECK" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ # Extract the first word of "gtkdoc-check", so it can be a program name with args.
+set dummy gtkdoc-check; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_GTKDOC_CHECK_PATH+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $GTKDOC_CHECK_PATH in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_GTKDOC_CHECK_PATH="$GTKDOC_CHECK_PATH" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_GTKDOC_CHECK_PATH="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+GTKDOC_CHECK_PATH=$ac_cv_path_GTKDOC_CHECK_PATH
+if test -n "$GTKDOC_CHECK_PATH"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GTKDOC_CHECK_PATH" >&5
+$as_echo "$GTKDOC_CHECK_PATH" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ for ac_prog in gtkdoc-rebase
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_GTKDOC_REBASE+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $GTKDOC_REBASE in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_GTKDOC_REBASE="$GTKDOC_REBASE" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_GTKDOC_REBASE="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+GTKDOC_REBASE=$ac_cv_path_GTKDOC_REBASE
+if test -n "$GTKDOC_REBASE"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GTKDOC_REBASE" >&5
+$as_echo "$GTKDOC_REBASE" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$GTKDOC_REBASE" && break
+done
+test -n "$GTKDOC_REBASE" || GTKDOC_REBASE="true"
+
+ # Extract the first word of "gtkdoc-mkpdf", so it can be a program name with args.
+set dummy gtkdoc-mkpdf; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_GTKDOC_MKPDF+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $GTKDOC_MKPDF in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_GTKDOC_MKPDF="$GTKDOC_MKPDF" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_GTKDOC_MKPDF="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+GTKDOC_MKPDF=$ac_cv_path_GTKDOC_MKPDF
+if test -n "$GTKDOC_MKPDF"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GTKDOC_MKPDF" >&5
+$as_echo "$GTKDOC_MKPDF" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+
+# Check whether --with-html-dir was given.
+if test "${with_html_dir+set}" = set; then :
+ withval=$with_html_dir;
+else
+ with_html_dir='${datadir}/gtk-doc/html'
+fi
+
+ HTML_DIR="$with_html_dir"
+
+
+ # Check whether --enable-gtk-doc was given.
+if test "${enable_gtk_doc+set}" = set; then :
+ enableval=$enable_gtk_doc;
+else
+ enable_gtk_doc=no
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build gtk-doc documentation" >&5
+$as_echo_n "checking whether to build gtk-doc documentation... " >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_gtk_doc" >&5
+$as_echo "$enable_gtk_doc" >&6; }
+
+ if test "x$enable_gtk_doc" = "xyes" && test "$have_gtk_doc" = "no"; then
+ as_fn_error $? "
+ You must have $gtk_doc_requires installed to build documentation for
+ $PACKAGE_NAME. Please install gtk-doc or disable building the
+ documentation by adding '--disable-gtk-doc' to '$0'." "$LINENO" 5
+ fi
+
+ if test "x$PACKAGE_NAME" != "xglib"; then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GTKDOC_DEPS" >&5
+$as_echo_n "checking for GTKDOC_DEPS... " >&6; }
+
+if test -n "$GTKDOC_DEPS_CFLAGS"; then
+ pkg_cv_GTKDOC_DEPS_CFLAGS="$GTKDOC_DEPS_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_GTKDOC_DEPS_CFLAGS=`$PKG_CONFIG --cflags "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$GTKDOC_DEPS_LIBS"; then
+ pkg_cv_GTKDOC_DEPS_LIBS="$GTKDOC_DEPS_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_GTKDOC_DEPS_LIBS=`$PKG_CONFIG --libs "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
+else
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi
+ if test $_pkg_short_errors_supported = yes; then
+ GTKDOC_DEPS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0" 2>&1`
+ else
+ GTKDOC_DEPS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$GTKDOC_DEPS_PKG_ERRORS" >&5
+
+ :
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ :
+else
+ GTKDOC_DEPS_CFLAGS=$pkg_cv_GTKDOC_DEPS_CFLAGS
+ GTKDOC_DEPS_LIBS=$pkg_cv_GTKDOC_DEPS_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+ fi
+
+ # Check whether --enable-gtk-doc-html was given.
+if test "${enable_gtk_doc_html+set}" = set; then :
+ enableval=$enable_gtk_doc_html;
+else
+ enable_gtk_doc_html=yes
+fi
+
+ # Check whether --enable-gtk-doc-pdf was given.
+if test "${enable_gtk_doc_pdf+set}" = set; then :
+ enableval=$enable_gtk_doc_pdf;
+else
+ enable_gtk_doc_pdf=no
+fi
+
+
+ if test -z "$GTKDOC_MKPDF"; then
+ enable_gtk_doc_pdf=no
+ fi
+
+ if test -z "$AM_DEFAULT_VERBOSITY"; then
+ AM_DEFAULT_VERBOSITY=1
+ fi
+
+
+ if test x$have_gtk_doc = xyes; then
+ HAVE_GTK_DOC_TRUE=
+ HAVE_GTK_DOC_FALSE='#'
+else
+ HAVE_GTK_DOC_TRUE='#'
+ HAVE_GTK_DOC_FALSE=
+fi
+
+ if test x$enable_gtk_doc = xyes; then
+ ENABLE_GTK_DOC_TRUE=
+ ENABLE_GTK_DOC_FALSE='#'
+else
+ ENABLE_GTK_DOC_TRUE='#'
+ ENABLE_GTK_DOC_FALSE=
+fi
+
+ if test x$enable_gtk_doc_html = xyes; then
+ GTK_DOC_BUILD_HTML_TRUE=
+ GTK_DOC_BUILD_HTML_FALSE='#'
+else
+ GTK_DOC_BUILD_HTML_TRUE='#'
+ GTK_DOC_BUILD_HTML_FALSE=
+fi
+
+ if test x$enable_gtk_doc_pdf = xyes; then
+ GTK_DOC_BUILD_PDF_TRUE=
+ GTK_DOC_BUILD_PDF_FALSE='#'
+else
+ GTK_DOC_BUILD_PDF_TRUE='#'
+ GTK_DOC_BUILD_PDF_FALSE=
+fi
+
+ if test -n "$LIBTOOL"; then
+ GTK_DOC_USE_LIBTOOL_TRUE=
+ GTK_DOC_USE_LIBTOOL_FALSE='#'
+else
+ GTK_DOC_USE_LIBTOOL_TRUE='#'
+ GTK_DOC_USE_LIBTOOL_FALSE=
+fi
+
+ if test -n "$GTKDOC_REBASE"; then
+ GTK_DOC_USE_REBASE_TRUE=
+ GTK_DOC_USE_REBASE_FALSE='#'
+else
+ GTK_DOC_USE_REBASE_TRUE='#'
+ GTK_DOC_USE_REBASE_FALSE=
+fi
+
+
+
+
+# GObject introspection
+
+
+
+ # Check whether --enable-introspection was given.
+if test "${enable_introspection+set}" = set; then :
+ enableval=$enable_introspection;
+else
+ enable_introspection=auto
+fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gobject-introspection" >&5
+$as_echo_n "checking for gobject-introspection... " >&6; }
+
+ case $enable_introspection in #(
+ no) :
+ found_introspection="no (disabled, use --enable-introspection to enable)"
+ ;; #(
+ yes) :
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gobject-introspection-1.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "gobject-introspection-1.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ :
+else
+ as_fn_error $? "gobject-introspection-1.0 is not installed" "$LINENO" 5
+fi
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gobject-introspection-1.0 >= 1.30.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "gobject-introspection-1.0 >= 1.30.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ found_introspection=yes
+else
+ as_fn_error $? "You need to have gobject-introspection >= 1.30.0 installed to build libnice" "$LINENO" 5
+fi
+ ;; #(
+ auto) :
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gobject-introspection-1.0 >= 1.30.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "gobject-introspection-1.0 >= 1.30.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ found_introspection=yes
+else
+ found_introspection=no
+fi
+ enable_introspection=$found_introspection
+ ;; #(
+ *) :
+ as_fn_error $? "invalid argument passed to --enable-introspection, should be one of [no/auto/yes]" "$LINENO" 5
+ ;;
+esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $found_introspection" >&5
+$as_echo "$found_introspection" >&6; }
+
+ INTROSPECTION_SCANNER=
+ INTROSPECTION_COMPILER=
+ INTROSPECTION_GENERATE=
+ INTROSPECTION_GIRDIR=
+ INTROSPECTION_TYPELIBDIR=
+ if test "x$found_introspection" = "xyes"; then
+ INTROSPECTION_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0`
+ INTROSPECTION_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0`
+ INTROSPECTION_GENERATE=`$PKG_CONFIG --variable=g_ir_generate gobject-introspection-1.0`
+ INTROSPECTION_GIRDIR=`$PKG_CONFIG --variable=girdir gobject-introspection-1.0`
+ INTROSPECTION_TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)"
+ INTROSPECTION_CFLAGS=`$PKG_CONFIG --cflags gobject-introspection-1.0`
+ INTROSPECTION_LIBS=`$PKG_CONFIG --libs gobject-introspection-1.0`
+ INTROSPECTION_MAKEFILE=`$PKG_CONFIG --variable=datadir gobject-introspection-1.0`/gobject-introspection-1.0/Makefile.introspection
+ fi
+
+
+
+
+
+
+
+
+
+ if test "x$found_introspection" = "xyes"; then
+ HAVE_INTROSPECTION_TRUE=
+ HAVE_INTROSPECTION_FALSE='#'
+else
+ HAVE_INTROSPECTION_TRUE='#'
+ HAVE_INTROSPECTION_FALSE=
+fi
+
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to ignore a specific network interface name prefix" >&5
+$as_echo_n "checking whether to ignore a specific network interface name prefix... " >&6; }
+
+# Check whether --with-ignored-network-interface-prefix was given.
+if test "${with_ignored_network_interface_prefix+set}" = set; then :
+ withval=$with_ignored_network_interface_prefix; interface_prefix="$withval"
+fi
+
+if test -n "$interface_prefix"; then :
+
+cat >>confdefs.h <<_ACEOF
+#define IGNORED_IFACE_PREFIX "$interface_prefix"
+_ACEOF
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, $interface_prefix" >&5
+$as_echo "yes, $interface_prefix" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes: double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \.
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ if test "x$cache_file" != "x/dev/null"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+ if test ! -f "$cache_file" || test -h "$cache_file"; then
+ cat confcache >"$cache_file"
+ else
+ case $cache_file in #(
+ */* | ?:*)
+ mv -f confcache "$cache_file"$$ &&
+ mv -f "$cache_file"$$ "$cache_file" ;; #(
+ *)
+ mv -f confcache "$cache_file" ;;
+ esac
+ fi
+ fi
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5
+$as_echo_n "checking that generated files are newer than configure... " >&6; }
+ if test -n "$am_sleep_pid"; then
+ # Hide warnings about reused PIDs.
+ wait $am_sleep_pid 2>/dev/null
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5
+$as_echo "done" >&6; }
+ if test -n "$EXEEXT"; then
+ am__EXEEXT_TRUE=
+ am__EXEEXT_FALSE='#'
+else
+ am__EXEEXT_TRUE='#'
+ am__EXEEXT_FALSE=
+fi
+
+if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
+ as_fn_error $? "conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+ as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+ as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${WINDOWS_TRUE}" && test -z "${WINDOWS_FALSE}"; then
+ as_fn_error $? "conditional \"WINDOWS\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${WITH_GSTREAMER_TRUE}" && test -z "${WITH_GSTREAMER_FALSE}"; then
+ as_fn_error $? "conditional \"WITH_GSTREAMER\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${HAVE_GST_CHECK_TRUE}" && test -z "${HAVE_GST_CHECK_FALSE}"; then
+ as_fn_error $? "conditional \"HAVE_GST_CHECK\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${WITH_GSTREAMER010_TRUE}" && test -z "${WITH_GSTREAMER010_FALSE}"; then
+ as_fn_error $? "conditional \"WITH_GSTREAMER010\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${GST_PLUGIN_BUILD_STATIC_TRUE}" && test -z "${GST_PLUGIN_BUILD_STATIC_FALSE}"; then
+ as_fn_error $? "conditional \"GST_PLUGIN_BUILD_STATIC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${HAVE_GTK_DOC_TRUE}" && test -z "${HAVE_GTK_DOC_FALSE}"; then
+ as_fn_error $? "conditional \"HAVE_GTK_DOC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${ENABLE_GTK_DOC_TRUE}" && test -z "${ENABLE_GTK_DOC_FALSE}"; then
+ as_fn_error $? "conditional \"ENABLE_GTK_DOC\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${GTK_DOC_BUILD_HTML_TRUE}" && test -z "${GTK_DOC_BUILD_HTML_FALSE}"; then
+ as_fn_error $? "conditional \"GTK_DOC_BUILD_HTML\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${GTK_DOC_BUILD_PDF_TRUE}" && test -z "${GTK_DOC_BUILD_PDF_FALSE}"; then
+ as_fn_error $? "conditional \"GTK_DOC_BUILD_PDF\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${GTK_DOC_USE_LIBTOOL_TRUE}" && test -z "${GTK_DOC_USE_LIBTOOL_FALSE}"; then
+ as_fn_error $? "conditional \"GTK_DOC_USE_LIBTOOL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${GTK_DOC_USE_REBASE_TRUE}" && test -z "${GTK_DOC_USE_REBASE_FALSE}"; then
+ as_fn_error $? "conditional \"GTK_DOC_USE_REBASE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${HAVE_INTROSPECTION_TRUE}" && test -z "${HAVE_INTROSPECTION_FALSE}"; then
+ as_fn_error $? "conditional \"HAVE_INTROSPECTION\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by libnice $as_me 0.1.16, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to the package provider."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+libnice config.status 0.1.16
+configured by $0, generated by GNU Autoconf 2.69,
+ with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+MKDIR_P='$MKDIR_P'
+AWK='$AWK'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=?*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ $as_echo "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ $as_echo "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+ --help | --hel | -h )
+ $as_echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+ set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ shift
+ \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ CONFIG_SHELL='$SHELL'
+ export CONFIG_SHELL
+ exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+#
+# INIT-COMMANDS
+#
+AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"
+
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+sed_quote_subst='$sed_quote_subst'
+double_quote_subst='$double_quote_subst'
+delay_variable_subst='$delay_variable_subst'
+macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`'
+macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`'
+AS='`$ECHO "$AS" | $SED "$delay_single_quote_subst"`'
+DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`'
+OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`'
+enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`'
+enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`'
+pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`'
+enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`'
+shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`'
+SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`'
+ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`'
+PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`'
+host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`'
+host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`'
+host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`'
+build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`'
+build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`'
+build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`'
+SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`'
+Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`'
+GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`'
+EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`'
+FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`'
+LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`'
+NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`'
+LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`'
+max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`'
+ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`'
+exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`'
+lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`'
+lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`'
+lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`'
+lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`'
+lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`'
+reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`'
+reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`'
+deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`'
+file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`'
+file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`'
+want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`'
+sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`'
+AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`'
+AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`'
+archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`'
+STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`'
+RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`'
+old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`'
+old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
+old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`'
+lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`'
+CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`'
+CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`'
+compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`'
+GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`'
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`'
+lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`'
+nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`'
+lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`'
+lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`'
+objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`'
+MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`'
+lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`'
+lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`'
+need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`'
+MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`'
+DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`'
+NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`'
+LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`'
+OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`'
+OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`'
+libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`'
+shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`'
+extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
+archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`'
+enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`'
+export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`'
+whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`'
+compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`'
+old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`'
+old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`'
+archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`'
+archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`'
+module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`'
+module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`'
+with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`'
+allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`'
+no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`'
+hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`'
+hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`'
+hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`'
+hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`'
+hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`'
+hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`'
+inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`'
+link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`'
+always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`'
+export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`'
+exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`'
+include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`'
+prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`'
+postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`'
+file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`'
+variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`'
+need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`'
+need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`'
+version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`'
+runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`'
+shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`'
+shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`'
+libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`'
+library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`'
+soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`'
+install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`'
+postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`'
+postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`'
+finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`'
+finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`'
+hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`'
+sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`'
+configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`'
+configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`'
+hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`'
+enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`'
+enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`'
+enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`'
+old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`'
+striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`'
+
+LTCC='$LTCC'
+LTCFLAGS='$LTCFLAGS'
+compiler='$compiler_DEFAULT'
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+ eval 'cat <<_LTECHO_EOF
+\$1
+_LTECHO_EOF'
+}
+
+# Quote evaled strings.
+for var in AS \
+DLLTOOL \
+OBJDUMP \
+SHELL \
+ECHO \
+PATH_SEPARATOR \
+SED \
+GREP \
+EGREP \
+FGREP \
+LD \
+NM \
+LN_S \
+lt_SP2NL \
+lt_NL2SP \
+reload_flag \
+deplibs_check_method \
+file_magic_cmd \
+file_magic_glob \
+want_nocaseglob \
+sharedlib_from_linklib_cmd \
+AR \
+AR_FLAGS \
+archiver_list_spec \
+STRIP \
+RANLIB \
+CC \
+CFLAGS \
+compiler \
+lt_cv_sys_global_symbol_pipe \
+lt_cv_sys_global_symbol_to_cdecl \
+lt_cv_sys_global_symbol_to_import \
+lt_cv_sys_global_symbol_to_c_name_address \
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \
+lt_cv_nm_interface \
+nm_file_list_spec \
+lt_cv_truncate_bin \
+lt_prog_compiler_no_builtin_flag \
+lt_prog_compiler_pic \
+lt_prog_compiler_wl \
+lt_prog_compiler_static \
+lt_cv_prog_compiler_c_o \
+need_locks \
+MANIFEST_TOOL \
+DSYMUTIL \
+NMEDIT \
+LIPO \
+OTOOL \
+OTOOL64 \
+shrext_cmds \
+export_dynamic_flag_spec \
+whole_archive_flag_spec \
+compiler_needs_object \
+with_gnu_ld \
+allow_undefined_flag \
+no_undefined_flag \
+hardcode_libdir_flag_spec \
+hardcode_libdir_separator \
+exclude_expsyms \
+include_expsyms \
+file_list_spec \
+variables_saved_for_relink \
+libname_spec \
+library_names_spec \
+soname_spec \
+install_override_mode \
+finish_eval \
+old_striplib \
+striplib; do
+ case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+ *[\\\\\\\`\\"\\\$]*)
+ eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
+ ;;
+ *)
+ eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+ ;;
+ esac
+done
+
+# Double-quote double-evaled strings.
+for var in reload_cmds \
+old_postinstall_cmds \
+old_postuninstall_cmds \
+old_archive_cmds \
+extract_expsyms_cmds \
+old_archive_from_new_cmds \
+old_archive_from_expsyms_cmds \
+archive_cmds \
+archive_expsym_cmds \
+module_cmds \
+module_expsym_cmds \
+export_symbols_cmds \
+prelink_cmds \
+postlink_cmds \
+postinstall_cmds \
+postuninstall_cmds \
+finish_cmds \
+sys_lib_search_path_spec \
+configure_time_dlsearch_path \
+configure_time_lt_sys_library_path; do
+ case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+ *[\\\\\\\`\\"\\\$]*)
+ eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
+ ;;
+ *)
+ eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+ ;;
+ esac
+done
+
+ac_aux_dir='$ac_aux_dir'
+
+# See if we are running on zsh, and set the options that allow our
+# commands through without removal of \ escapes INIT.
+if test -n "\${ZSH_VERSION+set}"; then
+ setopt NO_GLOB_SUBST
+fi
+
+
+ PACKAGE='$PACKAGE'
+ VERSION='$VERSION'
+ RM='$RM'
+ ofile='$ofile'
+
+
+
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "agent/Makefile") CONFIG_FILES="$CONFIG_FILES agent/Makefile" ;;
+ "stun/Makefile") CONFIG_FILES="$CONFIG_FILES stun/Makefile" ;;
+ "stun/tests/Makefile") CONFIG_FILES="$CONFIG_FILES stun/tests/Makefile" ;;
+ "stun/tools/Makefile") CONFIG_FILES="$CONFIG_FILES stun/tools/Makefile" ;;
+ "socket/Makefile") CONFIG_FILES="$CONFIG_FILES socket/Makefile" ;;
+ "nice/Makefile") CONFIG_FILES="$CONFIG_FILES nice/Makefile" ;;
+ "nice/nice.pc") CONFIG_FILES="$CONFIG_FILES nice/nice.pc" ;;
+ "random/Makefile") CONFIG_FILES="$CONFIG_FILES random/Makefile" ;;
+ "gst/Makefile") CONFIG_FILES="$CONFIG_FILES gst/Makefile" ;;
+ "docs/Makefile") CONFIG_FILES="$CONFIG_FILES docs/Makefile" ;;
+ "docs/reference/Makefile") CONFIG_FILES="$CONFIG_FILES docs/reference/Makefile" ;;
+ "docs/reference/libnice/Makefile") CONFIG_FILES="$CONFIG_FILES docs/reference/libnice/Makefile" ;;
+ "tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;;
+ "examples/Makefile") CONFIG_FILES="$CONFIG_FILES examples/Makefile" ;;
+ "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+ "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;;
+
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+ test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp= ac_tmp=
+ trap 'exit_status=$?
+ : "${ac_tmp:=$tmp}"
+ { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+ ac_cs_awk_cr='\\r'
+else
+ ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+ echo "cat >conf$$subs.awk <<_ACEOF" &&
+ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+ echo "_ACEOF"
+} >conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ . ./conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+ ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+ if test $ac_delim_n = $ac_delim_num; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+ N
+ s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = "\a"
+
+}
+{
+ line = $ 0
+ nfields = split(line, field, "@")
+ substed = 0
+ len = length(field[1])
+ for (i = 2; i < nfields; i++) {
+ key = field[i]
+ keylen = length(key)
+ if (S_is_set[key]) {
+ value = S[key]
+ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+ len += length(value) + length(field[++i])
+ substed = 1
+ } else
+ len += 1 + keylen
+ }
+
+ print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+ cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+ ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
+ if test -z "$ac_tt"; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any. Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[ ]*#[ ]*define[ ][ ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ for (key in D) D_is_set[key] = 1
+ FS = "\a"
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+ line = \$ 0
+ split(line, arg, " ")
+ if (arg[1] == "#") {
+ defundef = arg[2]
+ mac1 = arg[3]
+ } else {
+ defundef = substr(arg[1], 2)
+ mac1 = arg[2]
+ }
+ split(mac1, mac2, "(") #)
+ macro = mac2[1]
+ prefix = substr(line, 1, index(line, defundef) - 1)
+ if (D_is_set[macro]) {
+ # Preserve the white space surrounding the "#".
+ print prefix "define", macro P[macro] D[macro]
+ next
+ } else {
+ # Replace #undef with comments. This is necessary, for example,
+ # in the case of _POSIX_SOURCE, which is predefined and required
+ # on some systems where configure will not decide to define it.
+ if (defundef == "undef") {
+ print "/*", prefix defundef, macro, "*/"
+ next
+ }
+ }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS"
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$ac_tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ esac
+ case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`$as_echo "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$ac_tmp/stdin" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+ esac
+ ac_MKDIR_P=$MKDIR_P
+ case $MKDIR_P in
+ [\\/$]* | ?:[\\/]* ) ;;
+ */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
+ esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+s&@MKDIR_P@&$ac_MKDIR_P&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
+ "$ac_tmp/out"`; test -z "$ac_out"; } &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&2;}
+
+ rm -f "$ac_tmp/stdin"
+ case $ac_file in
+ -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+ *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+ :H)
+ #
+ # CONFIG_HEADER
+ #
+ if test x"$ac_file" != x-; then
+ {
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+ } >"$ac_tmp/config.h" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f "$ac_file"
+ mv "$ac_tmp/config.h" "$ac_file" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ fi
+ else
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
+ || as_fn_error $? "could not create -" "$LINENO" 5
+ fi
+# Compute "$ac_file"'s index in $config_headers.
+_am_arg="$ac_file"
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+ case $_am_header in
+ $_am_arg | $_am_arg:* )
+ break ;;
+ * )
+ _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+ esac
+done
+echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" ||
+$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$_am_arg" : 'X\(//\)[^/]' \| \
+ X"$_am_arg" : 'X\(//\)$' \| \
+ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$_am_arg" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`/stamp-h$_am_stamp_count
+ ;;
+
+ :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
+$as_echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+ esac
+
+
+ case $ac_file$ac_mode in
+ "depfiles":C) test x"$AMDEP_TRUE" != x"" || {
+ # Older Autoconf quotes --file arguments for eval, but not when files
+ # are listed without --file. Let's play safe and only enable the eval
+ # if we detect the quoting.
+ # TODO: see whether this extra hack can be removed once we start
+ # requiring Autoconf 2.70 or later.
+ case $CONFIG_FILES in #(
+ *\'*) :
+ eval set x "$CONFIG_FILES" ;; #(
+ *) :
+ set x $CONFIG_FILES ;; #(
+ *) :
+ ;;
+esac
+ shift
+ # Used to flag and report bootstrapping failures.
+ am_rc=0
+ for am_mf
+ do
+ # Strip MF so we end up with the name of the file.
+ am_mf=`$as_echo "$am_mf" | sed -e 's/:.*$//'`
+ # Check whether this is an Automake generated Makefile which includes
+ # dependency-tracking related rules and includes.
+ # Grep'ing the whole file directly is not great: AIX grep has a line
+ # limit of 2048, but all sed's we know have understand at least 4000.
+ sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \
+ || continue
+ am_dirpart=`$as_dirname -- "$am_mf" ||
+$as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$am_mf" : 'X\(//\)[^/]' \| \
+ X"$am_mf" : 'X\(//\)$' \| \
+ X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$am_mf" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ am_filepart=`$as_basename -- "$am_mf" ||
+$as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$am_mf" : 'X\(//\)$' \| \
+ X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$am_mf" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ { echo "$as_me:$LINENO: cd "$am_dirpart" \
+ && sed -e '/# am--include-marker/d' "$am_filepart" \
+ | $MAKE -f - am--depfiles" >&5
+ (cd "$am_dirpart" \
+ && sed -e '/# am--include-marker/d' "$am_filepart" \
+ | $MAKE -f - am--depfiles) >&5 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } || am_rc=$?
+ done
+ if test $am_rc -ne 0; then
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "Something went wrong bootstrapping makefile fragments
+ for automatic dependency tracking. Try re-running configure with the
+ '--disable-dependency-tracking' option to at least be able to build
+ the package (albeit without support for automatic dependency tracking).
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ { am_dirpart=; unset am_dirpart;}
+ { am_filepart=; unset am_filepart;}
+ { am_mf=; unset am_mf;}
+ { am_rc=; unset am_rc;}
+ rm -f conftest-deps.mk
+}
+ ;;
+ "libtool":C)
+
+ # See if we are running on zsh, and set the options that allow our
+ # commands through without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}"; then
+ setopt NO_GLOB_SUBST
+ fi
+
+ cfgfile=${ofile}T
+ trap "$RM \"$cfgfile\"; exit 1" 1 2 15
+ $RM "$cfgfile"
+
+ cat <<_LT_EOF >> "$cfgfile"
+#! $SHELL
+# Generated automatically by $as_me ($PACKAGE) $VERSION
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+
+# Provide generalized library-building support services.
+# Written by Gordon Matzigkeit, 1996
+
+# Copyright (C) 2014 Free Software Foundation, Inc.
+# This is free software; see the source for copying conditions. There is NO
+# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+# GNU Libtool is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of of the License, or
+# (at your option) any later version.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program or library that is built
+# using GNU Libtool, you may include this file under the same
+# distribution terms that you use for the rest of that program.
+#
+# GNU Libtool is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+# The names of the tagged configurations supported by this script.
+available_tags=''
+
+# Configured defaults for sys_lib_dlsearch_path munging.
+: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"}
+
+# ### BEGIN LIBTOOL CONFIG
+
+# Which release of libtool.m4 was used?
+macro_version=$macro_version
+macro_revision=$macro_revision
+
+# Assembler program.
+AS=$lt_AS
+
+# DLL creation program.
+DLLTOOL=$lt_DLLTOOL
+
+# Object dumper program.
+OBJDUMP=$lt_OBJDUMP
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# What type of objects to build.
+pic_mode=$pic_mode
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# Shared archive member basename,for filename based shared library versioning on AIX.
+shared_archive_member_spec=$shared_archive_member_spec
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# An echo program that protects backslashes.
+ECHO=$lt_ECHO
+
+# The PATH separator for the build system.
+PATH_SEPARATOR=$lt_PATH_SEPARATOR
+
+# The host system.
+host_alias=$host_alias
+host=$host
+host_os=$host_os
+
+# The build system.
+build_alias=$build_alias
+build=$build
+build_os=$build_os
+
+# A sed program that does not truncate output.
+SED=$lt_SED
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="\$SED -e 1s/^X//"
+
+# A grep program that handles long lines.
+GREP=$lt_GREP
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# A literal string matcher.
+FGREP=$lt_FGREP
+
+# A BSD- or MS-compatible name lister.
+NM=$lt_NM
+
+# Whether we need soft or hard links.
+LN_S=$lt_LN_S
+
+# What is the maximum length of a command?
+max_cmd_len=$max_cmd_len
+
+# Object file suffix (normally "o").
+objext=$ac_objext
+
+# Executable file suffix (normally "").
+exeext=$exeext
+
+# whether the shell understands "unset".
+lt_unset=$lt_unset
+
+# turn spaces into newlines.
+SP2NL=$lt_lt_SP2NL
+
+# turn newlines into spaces.
+NL2SP=$lt_lt_NL2SP
+
+# convert \$build file names to \$host format.
+to_host_file_cmd=$lt_cv_to_host_file_cmd
+
+# convert \$build files to toolchain format.
+to_tool_file_cmd=$lt_cv_to_tool_file_cmd
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method = "file_magic".
+file_magic_cmd=$lt_file_magic_cmd
+
+# How to find potential files when deplibs_check_method = "file_magic".
+file_magic_glob=$lt_file_magic_glob
+
+# Find potential files using nocaseglob when deplibs_check_method = "file_magic".
+want_nocaseglob=$lt_want_nocaseglob
+
+# Command to associate shared and link libraries.
+sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd
+
+# The archiver.
+AR=$lt_AR
+
+# Flags to create an archive.
+AR_FLAGS=$lt_AR_FLAGS
+
+# How to feed a file listing to the archiver.
+archiver_list_spec=$lt_archiver_list_spec
+
+# A symbol stripping program.
+STRIP=$lt_STRIP
+
+# Commands used to install an old-style archive.
+RANLIB=$lt_RANLIB
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Whether to use a lock for old archive extraction.
+lock_old_archive_extraction=$lock_old_archive_extraction
+
+# A C compiler.
+LTCC=$lt_CC
+
+# LTCC compiler flags.
+LTCFLAGS=$lt_CFLAGS
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration.
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm into a list of symbols to manually relocate.
+global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import
+
+# Transform the output of nm in a C name address pair.
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# Transform the output of nm in a C name address pair when lib prefix is needed.
+global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix
+
+# The name lister interface.
+nm_interface=$lt_lt_cv_nm_interface
+
+# Specify filename containing input files for \$NM.
+nm_file_list_spec=$lt_nm_file_list_spec
+
+# The root where to search for dependent libraries,and where our libraries should be installed.
+lt_sysroot=$lt_sysroot
+
+# Command to truncate a binary pipe.
+lt_truncate_bin=$lt_lt_cv_truncate_bin
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# Used to examine libraries when file_magic_cmd begins with "file".
+MAGIC_CMD=$MAGIC_CMD
+
+# Must we lock files when doing compilation?
+need_locks=$lt_need_locks
+
+# Manifest tool.
+MANIFEST_TOOL=$lt_MANIFEST_TOOL
+
+# Tool to manipulate archived DWARF debug symbol files on Mac OS X.
+DSYMUTIL=$lt_DSYMUTIL
+
+# Tool to change global to local symbols on Mac OS X.
+NMEDIT=$lt_NMEDIT
+
+# Tool to manipulate fat objects and archives on Mac OS X.
+LIPO=$lt_LIPO
+
+# ldd/readelf like tool for Mach-O binaries on Mac OS X.
+OTOOL=$lt_OTOOL
+
+# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4.
+OTOOL64=$lt_OTOOL64
+
+# Old archive suffix (normally "a").
+libext=$libext
+
+# Shared library suffix (normally ".so").
+shrext_cmds=$lt_shrext_cmds
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at link time.
+variables_saved_for_relink=$lt_variables_saved_for_relink
+
+# Do we need the "lib" prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Library versioning type.
+version_type=$version_type
+
+# Shared library runtime path variable.
+runpath_var=$runpath_var
+
+# Shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names. First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Permission mode override for installation of shared libraries.
+install_override_mode=$lt_install_override_mode
+
+# Command to use after installation of a shared archive.
+postinstall_cmds=$lt_postinstall_cmds
+
+# Command to use after uninstallation of a shared archive.
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# As "finish_cmds", except a single script fragment to be evaled but
+# not shown.
+finish_eval=$lt_finish_eval
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Compile-time system search path for libraries.
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Detected run-time system search path for libraries.
+sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path
+
+# Explicit LT_SYS_LIBRARY_PATH set during ./configure time.
+configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+
+# The linker used to build libraries.
+LD=$lt_LD
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# Commands used to build an old-style archive.
+old_archive_cmds=$lt_old_archive_cmds
+
+# A language specific compiler.
+CC=$lt_compiler
+
+# Is the compiler the GNU compiler?
+with_gcc=$GCC
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_lt_prog_compiler_pic
+
+# How to pass a linker flag through the compiler.
+wl=$lt_lt_prog_compiler_wl
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_lt_prog_compiler_static
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_lt_cv_prog_compiler_c_o
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$archive_cmds_need_lc
+
+# Whether or not to disallow shared libs when runtime libs are static.
+allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_export_dynamic_flag_spec
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_whole_archive_flag_spec
+
+# Whether the compiler copes with passing no objects directly.
+compiler_needs_object=$lt_compiler_needs_object
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_old_archive_from_new_cmds
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds
+
+# Commands used to build a shared archive.
+archive_cmds=$lt_archive_cmds
+archive_expsym_cmds=$lt_archive_expsym_cmds
+
+# Commands used to build a loadable module if different from building
+# a shared archive.
+module_cmds=$lt_module_cmds
+module_expsym_cmds=$lt_module_expsym_cmds
+
+# Whether we are building with GNU ld or not.
+with_gnu_ld=$lt_with_gnu_ld
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_allow_undefined_flag
+
+# Flag that enforces no undefined symbols.
+no_undefined_flag=$lt_no_undefined_flag
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist
+hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec
+
+# Whether we need a single "-rpath" flag with a separated argument.
+hardcode_libdir_separator=$lt_hardcode_libdir_separator
+
+# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes
+# DIR into the resulting binary.
+hardcode_direct=$hardcode_direct
+
+# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes
+# DIR into the resulting binary and the resulting library dependency is
+# "absolute",i.e impossible to change by setting \$shlibpath_var if the
+# library is relocated.
+hardcode_direct_absolute=$hardcode_direct_absolute
+
+# Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+# into the resulting binary.
+hardcode_minus_L=$hardcode_minus_L
+
+# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+# into the resulting binary.
+hardcode_shlibpath_var=$hardcode_shlibpath_var
+
+# Set to "yes" if building a shared library automatically hardcodes DIR
+# into the library and all subsequent libraries and executables linked
+# against it.
+hardcode_automatic=$hardcode_automatic
+
+# Set to yes if linker adds runtime paths of dependent libraries
+# to runtime path list.
+inherit_rpath=$inherit_rpath
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$link_all_deplibs
+
+# Set to "yes" if exported symbols are required.
+always_export_symbols=$always_export_symbols
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_export_symbols_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_exclude_expsyms
+
+# Symbols that must always be exported.
+include_expsyms=$lt_include_expsyms
+
+# Commands necessary for linking programs (against libraries) with templates.
+prelink_cmds=$lt_prelink_cmds
+
+# Commands necessary for finishing linking programs.
+postlink_cmds=$lt_postlink_cmds
+
+# Specify filename containing input files.
+file_list_spec=$lt_file_list_spec
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$hardcode_action
+
+# ### END LIBTOOL CONFIG
+
+_LT_EOF
+
+ cat <<'_LT_EOF' >> "$cfgfile"
+
+# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE
+
+# func_munge_path_list VARIABLE PATH
+# -----------------------------------
+# VARIABLE is name of variable containing _space_ separated list of
+# directories to be munged by the contents of PATH, which is string
+# having a format:
+# "DIR[:DIR]:"
+# string "DIR[ DIR]" will be prepended to VARIABLE
+# ":DIR[:DIR]"
+# string "DIR[ DIR]" will be appended to VARIABLE
+# "DIRP[:DIRP]::[DIRA:]DIRA"
+# string "DIRP[ DIRP]" will be prepended to VARIABLE and string
+# "DIRA[ DIRA]" will be appended to VARIABLE
+# "DIR[:DIR]"
+# VARIABLE will be replaced by "DIR[ DIR]"
+func_munge_path_list ()
+{
+ case x$2 in
+ x)
+ ;;
+ *:)
+ eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\"
+ ;;
+ x:*)
+ eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\"
+ ;;
+ *::*)
+ eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\"
+ eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\"
+ ;;
+ *)
+ eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\"
+ ;;
+ esac
+}
+
+
+# Calculate cc_basename. Skip known compiler wrappers and cross-prefix.
+func_cc_basename ()
+{
+ for cc_temp in $*""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+ done
+ func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+}
+
+
+# ### END FUNCTIONS SHARED WITH CONFIGURE
+
+_LT_EOF
+
+ case $host_os in
+ aix3*)
+ cat <<\_LT_EOF >> "$cfgfile"
+# AIX sometimes has problems with the GCC collect2 program. For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test set != "${COLLECT_NAMES+set}"; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+fi
+_LT_EOF
+ ;;
+ esac
+
+
+ltmain=$ac_aux_dir/ltmain.sh
+
+
+ # We use sed instead of cat because bash on DJGPP gets confused if
+ # if finds mixed CR/LF and LF-only lines. Since sed operates in
+ # text mode, it properly converts lines to CR/LF. This bash problem
+ # is reportedly fixed, but why not run on old versions too?
+ sed '$q' "$ltmain" >> "$cfgfile" \
+ || (rm -f "$cfgfile"; exit 1)
+
+ mv -f "$cfgfile" "$ofile" ||
+ (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+ chmod +x "$ofile"
+
+ ;;
+
+ esac
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
+
--- /dev/null
+
+AC_PREREQ(2.62)
+
+dnl Always compile with -Wall; if --enable-compile-warnings=error is passed,
+dnl also use -Werror. git and pre-releases default to -Werror
+
+dnl use a three digit version number for releases, and four for cvs/prerelease
+AC_INIT([libnice],[0.1.16])
+LIBNICE_RELEASE="yes"
+
+AC_CANONICAL_TARGET
+
+AC_CONFIG_SRCDIR([agent/agent.c])
+AC_CONFIG_HEADERS([config.h])
+AM_INIT_AUTOMAKE([1.12 -Wall -Wno-portability subdir-objects])
+
+AC_CONFIG_FILES([
+ Makefile
+ agent/Makefile
+ stun/Makefile
+ stun/tests/Makefile
+ stun/tools/Makefile
+ socket/Makefile
+ nice/Makefile
+ nice/nice.pc
+ random/Makefile
+ gst/Makefile
+ docs/Makefile
+ docs/reference/Makefile
+ docs/reference/libnice/Makefile
+ tests/Makefile
+ examples/Makefile
+ ])
+
+# Set the libtool C/A/R version info
+# If the source code was changed, but there were no interface changes:
+# Increment REVISION.
+# If there was a compatible interface change:
+# Increment CURRENT and AGE. Set REVISION to 0
+# If there was an incompatible interface change:
+# Increment CURRENT. Set AGE and REVISION to 0
+LIBNICE_CURRENT=19
+LIBNICE_REVISION=0
+LIBNICE_AGE=9
+LIBNICE_LIBVERSION=${LIBNICE_CURRENT}:${LIBNICE_REVISION}:${LIBNICE_AGE}
+LIBNICE_LT_LDFLAGS="-version-info ${LIBNICE_LIBVERSION} -no-undefined"
+AC_SUBST(LIBNICE_LT_LDFLAGS)
+
+dnl use pretty build output
+AM_SILENT_RULES([yes])
+
+
+# Checks for programs.
+
+AC_USE_SYSTEM_EXTENSIONS
+AC_PROG_CC
+AM_PROG_AR
+LT_PREREQ([2.2.6])
+LT_INIT([dlopen win32-dll disable-static])
+AC_PATH_PROG([GLIB_MKENUMS],[glib-mkenums])
+
+# Check Operating System
+AC_MSG_CHECKING([operating system])
+case "$host" in
+ *-*-*mingw*|*-*-*cygwin*)
+ platform=win32
+ AC_MSG_RESULT($platform)
+ ;;
+ *)
+ platform=linux/other
+ AC_MSG_RESULT($platform)
+ ;;
+esac
+
+AM_CONDITIONAL([WINDOWS], [test "$platform" = "win32"])
+
+# Checks for compiler features
+
+AC_C_RESTRICT
+AC_C_VARARRAYS
+AC_HEADER_ASSERT
+AC_HEADER_STDBOOL
+AH_VERBATIM([_FORTIFY_SOURCE],
+[/* Define to `2' to get GNU/libc warnings. */
+/* Only define if -O1 or more is enabled */
+#if defined __OPTIMIZE__ && __OPTIMIZE__ > 0
+# define _FORTIFY_SOURCE 2
+#endif])
+AC_DEFINE([NICEAPI_EXPORT], [ ], [Public library function implementation])
+AC_CHECK_HEADERS([arpa/inet.h net/in.h netdb.h])
+AC_CHECK_HEADERS([ifaddrs.h],
+ [AC_CHECK_FUNCS([getifaddrs],
+ [AC_DEFINE(HAVE_GETIFADDRS, [1],
+ [Whether getifaddrs() is available on the system])])])
+AC_CHECK_TYPES([size_t, ssize_t])
+
+# Also put matching version in LIBNICE_CFLAGS
+GLIB_REQ=2.48
+
+LIBNICE_CFLAGS="-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_44 -DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_2_44"
+
+dnl Support different levels of compiler error reporting.
+dnl This configure flag is designed to mimic one from gnome-common,
+dnl Defaults to "error" except for releases where it defaults to "yes"
+AC_ARG_ENABLE(compile-warnings,
+ AS_HELP_STRING([--enable-compile-warnings=@<:@no/minimum/yes/maximum/error@:>@],
+ [Enable different levels of compiler warnings]),,
+ [AS_IF([test "$LIBNICE_RELEASE" = "yes"],
+ [enable_compile_warnings="yes"],
+ [enable_compile_warnings="error"])])
+
+AC_DEFUN([NICE_ADD_FLAG],
+ AS_COMPILER_FLAG([-Werror $1], LIBNICE_CFLAGS="$LIBNICE_CFLAGS $1", [])
+)
+
+NICE_ADD_FLAG([-fno-strict-aliasing])
+
+AS_IF([test "$enable_compile_warnings" != "no"],[
+ NICE_ADD_FLAG([-Wall])
+])
+AS_IF([test "x$enable_compile_warnings" != "xno" -a \
+ "x$enable_compile_warnings" != "xminimum"],[
+ NICE_ADD_FLAG([-Wextra])
+ NICE_ADD_FLAG([-Wundef])
+ NICE_ADD_FLAG([-Wnested-externs])
+ NICE_ADD_FLAG([-Wwrite-strings])
+ NICE_ADD_FLAG([-Wpointer-arith])
+ NICE_ADD_FLAG([-Wmissing-declarations])
+ NICE_ADD_FLAG([-Wmissing-prototypes])
+ NICE_ADD_FLAG([-Wstrict-prototypes])
+ NICE_ADD_FLAG([-Wredundant-decls])
+ NICE_ADD_FLAG([-Wno-unused-parameter])
+ NICE_ADD_FLAG([-Wno-missing-field-initializers])
+ NICE_ADD_FLAG([-Wdeclaration-after-statement])
+ NICE_ADD_FLAG([-Wformat=2])
+ NICE_ADD_FLAG([-Wold-style-definition])
+ NICE_ADD_FLAG([-Wcast-align])
+ NICE_ADD_FLAG([-Wformat-nonliteral])
+ NICE_ADD_FLAG([-Wformat-security])
+ NICE_ADD_FLAG([-Wno-cast-function-type])
+])
+AS_IF([test "$enable_compile_warnings" = "yes" -o \
+ "$enable_compile_warnings" = "maximum" -o \
+ "$enable_compile_warnings" = "error"],[
+ NICE_ADD_FLAG([-Wsign-compare])
+ NICE_ADD_FLAG([-Wstrict-aliasing])
+ NICE_ADD_FLAG([-Wshadow])
+ NICE_ADD_FLAG([-Winline])
+ NICE_ADD_FLAG([-Wpacked])
+ NICE_ADD_FLAG([-Wmissing-format-attribute])
+ NICE_ADD_FLAG([-Winit-self])
+ NICE_ADD_FLAG([-Wredundant-decls])
+ NICE_ADD_FLAG([-Wmissing-include-dirs])
+ NICE_ADD_FLAG([-Wunused-but-set-variable])
+ NICE_ADD_FLAG([-Warray-bounds])
+])
+AS_IF([test "$enable_compile_warnings" = "maximum" -o \
+ "$enable_compile_warnings" = "error"],[
+ NICE_ADD_FLAG([-Wswitch-default])
+ NICE_ADD_FLAG([-Waggregate-return])
+])
+AS_IF([test "x$enable_compile_warnings" = "xerror"],[
+ NICE_ADD_FLAG([-Werror])
+ NICE_ADD_FLAG([-Wno-suggest-attribute=format])
+])
+
+#
+# Fixes for Solaris
+#
+AC_SEARCH_LIBS([inet_pton],[nsl])
+AC_SEARCH_LIBS([socket],[socket inet])
+case $host in
+ *-*-solaris* )
+ AC_DEFINE(_XOPEN_SOURCE, 600, Needed to get declarations for msg_control and msg_controllen on Solaris)
+ AC_DEFINE(__EXTENSIONS__, 1, Needed to get declarations for msg_control and msg_controllen on Solaris)
+ ;;
+esac
+
+AC_SUBST(LIBNICE_CFLAGS)
+AC_MSG_NOTICE([set LIBNICE_CFLAGS to $LIBNICE_CFLAGS])
+
+# Checks for libraries.
+AC_CHECK_LIB(rt, clock_gettime, [LIBRT="-lrt"], [LIBRT=""])
+AC_CHECK_FUNCS([poll])
+AC_SUBST(LIBRT)
+
+# Dependencies
+
+NICE_PACKAGES_PUBLIC="glib-2.0 >= $GLIB_REQ gio-2.0 >= $GLIB_REQ gobject-2.0 >= $GLIB_REQ"
+NICE_PACKAGES_PRIVATE="gthread-2.0"
+
+PKG_CHECK_MODULES(GLIB, [$NICE_PACKAGES_PUBLIC $NICE_PACKAGES_PRIVATE])
+
+AC_ARG_WITH(crypto-library,
+ AS_HELP_STRING([--with-crypto-library=\{gnutls,openssl,auto\}],[select Crypto library (gnutls or openssl)]),
+ [with_crypto_library=${withval}],
+ [with_crypto_library=auto])
+
+
+AS_IF([test "$with_crypto_library" != "openssl"],
+ [
+ GNUTLS_PACKAGES_PRIVATE="gnutls >= 2.12.0"
+ PKG_CHECK_MODULES(GNUTLS, [$GNUTLS_PACKAGES_PRIVATE],
+ [
+ AC_DEFINE([HAVE_GNUTLS], [1], [Use GnuTLS])
+ GNUTLS_FOUND=yes
+ NICE_PACKAGES_PRIVATE="$NICE_PACKAGES_PRIVATE $GNUTLS_PACKAGES_PRIVATE"
+ ],
+ [
+ AS_IF([test "$with_crypto_library" == "gnutls"],
+ [
+ AC_MSG_ERROR([Neither GnuTLS is not available])
+ ]
+ )
+ ]
+ )
+ ]
+)
+
+AS_IF([test "x${GNUTLS_FOUND}" != "xyes"],
+ [
+ AX_CHECK_OPENSSL(
+ [
+ AC_DEFINE([HAVE_OPENSSL], [1], [Use OpenSSL])
+ NICE_PACKAGES_PRIVATE="$NICE_PACKAGES_PRIVATE libcrypto"
+ AC_MSG_NOTICE([OpenSSL selected])
+ ],
+ [
+ AC_MSG_ERROR([Neither GnuTLS or OpenSSL is available])
+ ]
+ )
+ ],
+ [
+ AC_MSG_NOTICE([GnuTLS selected])
+ ]
+)
+
+AC_SUBST([NICE_PACKAGES_PUBLIC])
+AC_SUBST([NICE_PACKAGES_PRIVATE])
+
+
+AC_ARG_WITH(gstreamer,
+ AS_HELP_STRING([--with-gstreamer],[build GStreamer plugin]),
+ [with_gstreamer=${withval}],
+ [with_gstreamer=auto])
+
+AC_ARG_WITH(gstreamer-0.10,
+ AS_HELP_STRING([--with-gstreamer-0.10],[build GStreamer 0.10 plugin]),
+ [with_gstreamer010=${withval}],
+ [with_gstreamer010=auto])
+
+AS_IF([test "$with_gstreamer" != no], [
+
+ PKG_CHECK_MODULES(GST, [
+ gstreamer-1.0 >= 0.11.91
+ gstreamer-base-1.0 >= 0.11.91
+ ],
+ [
+ with_gstreamer=yes
+ GST_MAJORMINOR=1.0
+ gstplugindir="\$(libdir)/gstreamer-$GST_MAJORMINOR"
+ ],
+ [
+ AS_IF([test "$with_gstreamer" = yes], [
+ AC_MSG_ERROR([GStreamer 1.0 support was requested but GStreamer 1.0 libraries are not available])
+ ])
+
+ with_gstreamer=no
+ ])
+
+ PKG_CHECK_MODULES(GST_CHECK, [
+ gstreamer-check-1.0 >= 0.11.91
+ ],
+ [
+ have_gst_check=yes
+ ],
+ [
+ have_gst_check=no
+ ])
+])
+
+AS_IF([test "$with_gstreamer010" != no], [
+
+ PKG_CHECK_MODULES(GST010, [
+ gstreamer-0.10 >= 0.10.10
+ gstreamer-base-0.10 >= 0.10.10
+ ],
+ [
+ with_gstreamer010=yes
+ GST_MAJORMINOR=0.10
+ gstplugin010dir="\$(libdir)/gstreamer-$GST_MAJORMINOR"
+ ],
+ [
+ AS_IF([test "$with_gstreamer010" = yes], [
+ AC_MSG_ERROR([GStreamer 0.10 support was requested but GStreamer 0.10 libraries are not available])
+ ])
+
+ with_gstreamer010=no
+ ])
+])
+
+AC_SUBST(gstplugindir)
+AC_SUBST(gstplugin010dir)
+
+AM_CONDITIONAL(WITH_GSTREAMER, test "$with_gstreamer" = yes)
+AM_CONDITIONAL(HAVE_GST_CHECK, test "$have_gst_check" = yes)
+AM_CONDITIONAL(WITH_GSTREAMER010, test "$with_gstreamer010" = yes)
+
+GUPNP_IGD_REQUIRED=0.2.4
+
+AC_ARG_ENABLE([gupnp],
+ AS_HELP_STRING([--disable-gupnp],[Disable GUPnP IGD support]),
+ [case "${enableval}" in
+ yes) WANT_GUPNP=yes ;;
+ no) WANT_GUPNP=no ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-gupnp) ;;
+ esac],
+ WANT_GUPNP=test)
+
+GUPNP_PACKAGES_PUBLIC=""
+GUPNP_PACKAGES_PRIVATE="gupnp-igd-1.0 >= $GUPNP_IGD_REQUIRED"
+GUPNP_PACKAGES="$GUPNP_PACKAGES_PUBLIC $GUPNP_PACKAGES_PRIVATE"
+
+HAVE_GUPNP=no
+if test "x$WANT_GUPNP" != "xno"; then
+ PKG_CHECK_MODULES(GUPNP, [$GUPNP_PACKAGES],
+ [ HAVE_GUPNP=yes ],
+ [ HAVE_GUPNP=no ])
+fi
+if test "x$WANT_GUPNP" = "xyes" && test "x$HAVE_GUPNP" = "xno"; then
+ AC_MSG_ERROR([Requested GUPnP IGD, but it is not available])
+fi
+
+if test "x$HAVE_GUPNP" = "xyes"; then
+ AC_DEFINE(HAVE_GUPNP,,[Have the GUPnP IGD library])
+ UPNP_ENABLED="true"
+else
+ GUPNP_PACKAGES_PUBLIC=""
+ GUPNP_PACKAGES_PRIVATE=""
+ GUPNP_PACKAGES=""
+fi
+
+AC_SUBST([GUPNP_PACKAGES_PUBLIC])
+AC_SUBST([GUPNP_PACKAGES_PRIVATE])
+AC_SUBST([GUPNP_PACKAGES])
+
+AC_SUBST(HAVE_GUPNP)
+AC_SUBST([UPNP_ENABLED])
+
+dnl Test coverage
+AC_ARG_ENABLE([coverage],
+ [AS_HELP_STRING([--enable-coverage],
+ [build for test coverage (default disabled)])],,
+ [enable_coverage="no"])
+AS_IF([test "${enable_coverage}" != "no"], [
+ CFLAGS="${CFLAGS} -g -O0 -fprofile-arcs -ftest-coverage"
+ LDFLAGS="-lgcov"
+ CCACHE_DISABLE=1
+])
+AC_SUBST(CCACHE_DISABLE)
+
+dnl build static plugins or not
+AC_MSG_CHECKING([whether to build static plugins or not])
+AC_ARG_ENABLE(
+ static-plugins,
+ AC_HELP_STRING(
+ [--enable-static-plugins],
+ [build static plugins @<:@default=no@:>@]),
+ [AS_CASE(
+ [$enableval], [no], [], [yes], [],
+ [AC_MSG_ERROR([bad value "$enableval" for --enable-static-plugins])])],
+ [enable_static_plugins=no])
+AC_MSG_RESULT([$enable_static_plugins])
+if test "x$enable_static_plugins" = xyes; then
+ AC_DEFINE(GST_PLUGIN_BUILD_STATIC, 1,
+ [Define if static plugins should be built])
+fi
+AM_CONDITIONAL(GST_PLUGIN_BUILD_STATIC, test "x$enable_static_plugins" = "xyes")
+
+case $host_os in
+ solaris*)
+ LDFLAGS="$LDFLAGS -lsocket -lnsl"
+ ;;
+ *)
+ ;;
+esac
+
+# check for gtk-doc
+m4_ifdef([GTK_DOC_CHECK], [
+GTK_DOC_CHECK([1.10],[--flavour no-tmpl])
+],[
+AM_CONDITIONAL([ENABLE_GTK_DOC], false)
+])
+
+# GObject introspection
+GOBJECT_INTROSPECTION_CHECK([1.30.0])
+
+dnl Ignore a specific network interface name prefix from the connection check
+AC_MSG_CHECKING([whether to ignore a specific network interface name prefix])
+AC_ARG_WITH([ignored-network-interface-prefix],
+ [AS_HELP_STRING([--with-ignored-network-interface-prefix=string],
+ [Ignore network interfaces whose name starts with "string" from the ICE connection
+ check algorithm. For example, interfaces "virbr" in the case of the virtual bridge
+ handled by libvirtd, do not help in finding connectivity.])],
+ [interface_prefix="$withval"])
+AS_IF([test -n "$interface_prefix"],
+ [AC_DEFINE_UNQUOTED([IGNORED_IFACE_PREFIX],["$interface_prefix"],
+ [Ignore this network interface prefix from the connection check])
+ AC_MSG_RESULT([yes, $interface_prefix])],
+ [AC_MSG_RESULT([no])])
+
+AC_CONFIG_MACRO_DIR(m4)
+
+AC_OUTPUT
+
--- /dev/null
+#! /bin/sh
+# depcomp - compile a program generating dependencies as side-effects
+
+scriptversion=2018-03-07.03; # UTC
+
+# Copyright (C) 1999-2018 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
+
+case $1 in
+ '')
+ echo "$0: No command. Try '$0 --help' for more information." 1>&2
+ exit 1;
+ ;;
+ -h | --h*)
+ cat <<\EOF
+Usage: depcomp [--help] [--version] PROGRAM [ARGS]
+
+Run PROGRAMS ARGS to compile a file, generating dependencies
+as side-effects.
+
+Environment variables:
+ depmode Dependency tracking mode.
+ source Source file read by 'PROGRAMS ARGS'.
+ object Object file output by 'PROGRAMS ARGS'.
+ DEPDIR directory where to store dependencies.
+ depfile Dependency file to output.
+ tmpdepfile Temporary file to use when outputting dependencies.
+ libtool Whether libtool is used (yes/no).
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+ exit $?
+ ;;
+ -v | --v*)
+ echo "depcomp $scriptversion"
+ exit $?
+ ;;
+esac
+
+# Get the directory component of the given path, and save it in the
+# global variables '$dir'. Note that this directory component will
+# be either empty or ending with a '/' character. This is deliberate.
+set_dir_from ()
+{
+ case $1 in
+ */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
+ *) dir=;;
+ esac
+}
+
+# Get the suffix-stripped basename of the given path, and save it the
+# global variable '$base'.
+set_base_from ()
+{
+ base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
+}
+
+# If no dependency file was actually created by the compiler invocation,
+# we still have to create a dummy depfile, to avoid errors with the
+# Makefile "include basename.Plo" scheme.
+make_dummy_depfile ()
+{
+ echo "#dummy" > "$depfile"
+}
+
+# Factor out some common post-processing of the generated depfile.
+# Requires the auxiliary global variable '$tmpdepfile' to be set.
+aix_post_process_depfile ()
+{
+ # If the compiler actually managed to produce a dependency file,
+ # post-process it.
+ if test -f "$tmpdepfile"; then
+ # Each line is of the form 'foo.o: dependency.h'.
+ # Do two passes, one to just change these to
+ # $object: dependency.h
+ # and one to simply output
+ # dependency.h:
+ # which is needed to avoid the deleted-header problem.
+ { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
+ sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
+ } > "$depfile"
+ rm -f "$tmpdepfile"
+ else
+ make_dummy_depfile
+ fi
+}
+
+# A tabulation character.
+tab=' '
+# A newline character.
+nl='
+'
+# Character ranges might be problematic outside the C locale.
+# These definitions help.
+upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
+lower=abcdefghijklmnopqrstuvwxyz
+digits=0123456789
+alpha=${upper}${lower}
+
+if test -z "$depmode" || test -z "$source" || test -z "$object"; then
+ echo "depcomp: Variables source, object and depmode must be set" 1>&2
+ exit 1
+fi
+
+# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
+depfile=${depfile-`echo "$object" |
+ sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
+tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
+
+rm -f "$tmpdepfile"
+
+# Avoid interferences from the environment.
+gccflag= dashmflag=
+
+# Some modes work just like other modes, but use different flags. We
+# parameterize here, but still list the modes in the big case below,
+# to make depend.m4 easier to write. Note that we *cannot* use a case
+# here, because this file can only contain one case statement.
+if test "$depmode" = hp; then
+ # HP compiler uses -M and no extra arg.
+ gccflag=-M
+ depmode=gcc
+fi
+
+if test "$depmode" = dashXmstdout; then
+ # This is just like dashmstdout with a different argument.
+ dashmflag=-xM
+ depmode=dashmstdout
+fi
+
+cygpath_u="cygpath -u -f -"
+if test "$depmode" = msvcmsys; then
+ # This is just like msvisualcpp but w/o cygpath translation.
+ # Just convert the backslash-escaped backslashes to single forward
+ # slashes to satisfy depend.m4
+ cygpath_u='sed s,\\\\,/,g'
+ depmode=msvisualcpp
+fi
+
+if test "$depmode" = msvc7msys; then
+ # This is just like msvc7 but w/o cygpath translation.
+ # Just convert the backslash-escaped backslashes to single forward
+ # slashes to satisfy depend.m4
+ cygpath_u='sed s,\\\\,/,g'
+ depmode=msvc7
+fi
+
+if test "$depmode" = xlc; then
+ # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
+ gccflag=-qmakedep=gcc,-MF
+ depmode=gcc
+fi
+
+case "$depmode" in
+gcc3)
+## gcc 3 implements dependency tracking that does exactly what
+## we want. Yay! Note: for some reason libtool 1.4 doesn't like
+## it if -MD -MP comes after the -MF stuff. Hmm.
+## Unfortunately, FreeBSD c89 acceptance of flags depends upon
+## the command line argument order; so add the flags where they
+## appear in depend2.am. Note that the slowdown incurred here
+## affects only configure: in makefiles, %FASTDEP% shortcuts this.
+ for arg
+ do
+ case $arg in
+ -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
+ *) set fnord "$@" "$arg" ;;
+ esac
+ shift # fnord
+ shift # $arg
+ done
+ "$@"
+ stat=$?
+ if test $stat -ne 0; then
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ mv "$tmpdepfile" "$depfile"
+ ;;
+
+gcc)
+## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
+## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
+## (see the conditional assignment to $gccflag above).
+## There are various ways to get dependency output from gcc. Here's
+## why we pick this rather obscure method:
+## - Don't want to use -MD because we'd like the dependencies to end
+## up in a subdir. Having to rename by hand is ugly.
+## (We might end up doing this anyway to support other compilers.)
+## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
+## -MM, not -M (despite what the docs say). Also, it might not be
+## supported by the other compilers which use the 'gcc' depmode.
+## - Using -M directly means running the compiler twice (even worse
+## than renaming).
+ if test -z "$gccflag"; then
+ gccflag=-MD,
+ fi
+ "$@" -Wp,"$gccflag$tmpdepfile"
+ stat=$?
+ if test $stat -ne 0; then
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ # The second -e expression handles DOS-style file names with drive
+ # letters.
+ sed -e 's/^[^:]*: / /' \
+ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
+## This next piece of magic avoids the "deleted header file" problem.
+## The problem is that when a header file which appears in a .P file
+## is deleted, the dependency causes make to die (because there is
+## typically no way to rebuild the header). We avoid this by adding
+## dummy dependencies for each header file. Too bad gcc doesn't do
+## this for us directly.
+## Some versions of gcc put a space before the ':'. On the theory
+## that the space means something, we add a space to the output as
+## well. hp depmode also adds that space, but also prefixes the VPATH
+## to the object. Take care to not repeat it in the output.
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly. Breaking it into two sed invocations is a workaround.
+ tr ' ' "$nl" < "$tmpdepfile" \
+ | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
+ | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+hp)
+ # This case exists only to let depend.m4 do its work. It works by
+ # looking at the text of this script. This case will never be run,
+ # since it is checked for above.
+ exit 1
+ ;;
+
+sgi)
+ if test "$libtool" = yes; then
+ "$@" "-Wp,-MDupdate,$tmpdepfile"
+ else
+ "$@" -MDupdate "$tmpdepfile"
+ fi
+ stat=$?
+ if test $stat -ne 0; then
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+
+ if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
+ echo "$object : \\" > "$depfile"
+ # Clip off the initial element (the dependent). Don't try to be
+ # clever and replace this with sed code, as IRIX sed won't handle
+ # lines with more than a fixed number of characters (4096 in
+ # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
+ # the IRIX cc adds comments like '#:fec' to the end of the
+ # dependency line.
+ tr ' ' "$nl" < "$tmpdepfile" \
+ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
+ | tr "$nl" ' ' >> "$depfile"
+ echo >> "$depfile"
+ # The second pass generates a dummy entry for each header file.
+ tr ' ' "$nl" < "$tmpdepfile" \
+ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
+ >> "$depfile"
+ else
+ make_dummy_depfile
+ fi
+ rm -f "$tmpdepfile"
+ ;;
+
+xlc)
+ # This case exists only to let depend.m4 do its work. It works by
+ # looking at the text of this script. This case will never be run,
+ # since it is checked for above.
+ exit 1
+ ;;
+
+aix)
+ # The C for AIX Compiler uses -M and outputs the dependencies
+ # in a .u file. In older versions, this file always lives in the
+ # current directory. Also, the AIX compiler puts '$object:' at the
+ # start of each line; $object doesn't have directory information.
+ # Version 6 uses the directory in both cases.
+ set_dir_from "$object"
+ set_base_from "$object"
+ if test "$libtool" = yes; then
+ tmpdepfile1=$dir$base.u
+ tmpdepfile2=$base.u
+ tmpdepfile3=$dir.libs/$base.u
+ "$@" -Wc,-M
+ else
+ tmpdepfile1=$dir$base.u
+ tmpdepfile2=$dir$base.u
+ tmpdepfile3=$dir$base.u
+ "$@" -M
+ fi
+ stat=$?
+ if test $stat -ne 0; then
+ rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+ exit $stat
+ fi
+
+ for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+ do
+ test -f "$tmpdepfile" && break
+ done
+ aix_post_process_depfile
+ ;;
+
+tcc)
+ # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
+ # FIXME: That version still under development at the moment of writing.
+ # Make that this statement remains true also for stable, released
+ # versions.
+ # It will wrap lines (doesn't matter whether long or short) with a
+ # trailing '\', as in:
+ #
+ # foo.o : \
+ # foo.c \
+ # foo.h \
+ #
+ # It will put a trailing '\' even on the last line, and will use leading
+ # spaces rather than leading tabs (at least since its commit 0394caf7
+ # "Emit spaces for -MD").
+ "$@" -MD -MF "$tmpdepfile"
+ stat=$?
+ if test $stat -ne 0; then
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+ # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
+ # We have to change lines of the first kind to '$object: \'.
+ sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
+ # And for each line of the second kind, we have to emit a 'dep.h:'
+ # dummy dependency, to avoid the deleted-header problem.
+ sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+## The order of this option in the case statement is important, since the
+## shell code in configure will try each of these formats in the order
+## listed in this file. A plain '-MD' option would be understood by many
+## compilers, so we must ensure this comes after the gcc and icc options.
+pgcc)
+ # Portland's C compiler understands '-MD'.
+ # Will always output deps to 'file.d' where file is the root name of the
+ # source file under compilation, even if file resides in a subdirectory.
+ # The object file name does not affect the name of the '.d' file.
+ # pgcc 10.2 will output
+ # foo.o: sub/foo.c sub/foo.h
+ # and will wrap long lines using '\' :
+ # foo.o: sub/foo.c ... \
+ # sub/foo.h ... \
+ # ...
+ set_dir_from "$object"
+ # Use the source, not the object, to determine the base name, since
+ # that's sadly what pgcc will do too.
+ set_base_from "$source"
+ tmpdepfile=$base.d
+
+ # For projects that build the same source file twice into different object
+ # files, the pgcc approach of using the *source* file root name can cause
+ # problems in parallel builds. Use a locking strategy to avoid stomping on
+ # the same $tmpdepfile.
+ lockdir=$base.d-lock
+ trap "
+ echo '$0: caught signal, cleaning up...' >&2
+ rmdir '$lockdir'
+ exit 1
+ " 1 2 13 15
+ numtries=100
+ i=$numtries
+ while test $i -gt 0; do
+ # mkdir is a portable test-and-set.
+ if mkdir "$lockdir" 2>/dev/null; then
+ # This process acquired the lock.
+ "$@" -MD
+ stat=$?
+ # Release the lock.
+ rmdir "$lockdir"
+ break
+ else
+ # If the lock is being held by a different process, wait
+ # until the winning process is done or we timeout.
+ while test -d "$lockdir" && test $i -gt 0; do
+ sleep 1
+ i=`expr $i - 1`
+ done
+ fi
+ i=`expr $i - 1`
+ done
+ trap - 1 2 13 15
+ if test $i -le 0; then
+ echo "$0: failed to acquire lock after $numtries attempts" >&2
+ echo "$0: check lockdir '$lockdir'" >&2
+ exit 1
+ fi
+
+ if test $stat -ne 0; then
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+ # Each line is of the form `foo.o: dependent.h',
+ # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
+ # Do two passes, one to just change these to
+ # `$object: dependent.h' and one to simply `dependent.h:'.
+ sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
+ # Some versions of the HPUX 10.20 sed can't process this invocation
+ # correctly. Breaking it into two sed invocations is a workaround.
+ sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \
+ | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+hp2)
+ # The "hp" stanza above does not work with aCC (C++) and HP's ia64
+ # compilers, which have integrated preprocessors. The correct option
+ # to use with these is +Maked; it writes dependencies to a file named
+ # 'foo.d', which lands next to the object file, wherever that
+ # happens to be.
+ # Much of this is similar to the tru64 case; see comments there.
+ set_dir_from "$object"
+ set_base_from "$object"
+ if test "$libtool" = yes; then
+ tmpdepfile1=$dir$base.d
+ tmpdepfile2=$dir.libs/$base.d
+ "$@" -Wc,+Maked
+ else
+ tmpdepfile1=$dir$base.d
+ tmpdepfile2=$dir$base.d
+ "$@" +Maked
+ fi
+ stat=$?
+ if test $stat -ne 0; then
+ rm -f "$tmpdepfile1" "$tmpdepfile2"
+ exit $stat
+ fi
+
+ for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
+ do
+ test -f "$tmpdepfile" && break
+ done
+ if test -f "$tmpdepfile"; then
+ sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
+ # Add 'dependent.h:' lines.
+ sed -ne '2,${
+ s/^ *//
+ s/ \\*$//
+ s/$/:/
+ p
+ }' "$tmpdepfile" >> "$depfile"
+ else
+ make_dummy_depfile
+ fi
+ rm -f "$tmpdepfile" "$tmpdepfile2"
+ ;;
+
+tru64)
+ # The Tru64 compiler uses -MD to generate dependencies as a side
+ # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
+ # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
+ # dependencies in 'foo.d' instead, so we check for that too.
+ # Subdirectories are respected.
+ set_dir_from "$object"
+ set_base_from "$object"
+
+ if test "$libtool" = yes; then
+ # Libtool generates 2 separate objects for the 2 libraries. These
+ # two compilations output dependencies in $dir.libs/$base.o.d and
+ # in $dir$base.o.d. We have to check for both files, because
+ # one of the two compilations can be disabled. We should prefer
+ # $dir$base.o.d over $dir.libs/$base.o.d because the latter is
+ # automatically cleaned when .libs/ is deleted, while ignoring
+ # the former would cause a distcleancheck panic.
+ tmpdepfile1=$dir$base.o.d # libtool 1.5
+ tmpdepfile2=$dir.libs/$base.o.d # Likewise.
+ tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504
+ "$@" -Wc,-MD
+ else
+ tmpdepfile1=$dir$base.d
+ tmpdepfile2=$dir$base.d
+ tmpdepfile3=$dir$base.d
+ "$@" -MD
+ fi
+
+ stat=$?
+ if test $stat -ne 0; then
+ rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+ exit $stat
+ fi
+
+ for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+ do
+ test -f "$tmpdepfile" && break
+ done
+ # Same post-processing that is required for AIX mode.
+ aix_post_process_depfile
+ ;;
+
+msvc7)
+ if test "$libtool" = yes; then
+ showIncludes=-Wc,-showIncludes
+ else
+ showIncludes=-showIncludes
+ fi
+ "$@" $showIncludes > "$tmpdepfile"
+ stat=$?
+ grep -v '^Note: including file: ' "$tmpdepfile"
+ if test $stat -ne 0; then
+ rm -f "$tmpdepfile"
+ exit $stat
+ fi
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ # The first sed program below extracts the file names and escapes
+ # backslashes for cygpath. The second sed program outputs the file
+ # name when reading, but also accumulates all include files in the
+ # hold buffer in order to output them again at the end. This only
+ # works with sed implementations that can handle large buffers.
+ sed < "$tmpdepfile" -n '
+/^Note: including file: *\(.*\)/ {
+ s//\1/
+ s/\\/\\\\/g
+ p
+}' | $cygpath_u | sort -u | sed -n '
+s/ /\\ /g
+s/\(.*\)/'"$tab"'\1 \\/p
+s/.\(.*\) \\/\1:/
+H
+$ {
+ s/.*/'"$tab"'/
+ G
+ p
+}' >> "$depfile"
+ echo >> "$depfile" # make sure the fragment doesn't end with a backslash
+ rm -f "$tmpdepfile"
+ ;;
+
+msvc7msys)
+ # This case exists only to let depend.m4 do its work. It works by
+ # looking at the text of this script. This case will never be run,
+ # since it is checked for above.
+ exit 1
+ ;;
+
+#nosideeffect)
+ # This comment above is used by automake to tell side-effect
+ # dependency tracking mechanisms from slower ones.
+
+dashmstdout)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the preprocessed file to stdout, regardless of -o.
+ "$@" || exit $?
+
+ # Remove the call to Libtool.
+ if test "$libtool" = yes; then
+ while test "X$1" != 'X--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+
+ # Remove '-o $object'.
+ IFS=" "
+ for arg
+ do
+ case $arg in
+ -o)
+ shift
+ ;;
+ $object)
+ shift
+ ;;
+ *)
+ set fnord "$@" "$arg"
+ shift # fnord
+ shift # $arg
+ ;;
+ esac
+ done
+
+ test -z "$dashmflag" && dashmflag=-M
+ # Require at least two characters before searching for ':'
+ # in the target name. This is to cope with DOS-style filenames:
+ # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
+ "$@" $dashmflag |
+ sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
+ rm -f "$depfile"
+ cat < "$tmpdepfile" > "$depfile"
+ # Some versions of the HPUX 10.20 sed can't process this sed invocation
+ # correctly. Breaking it into two sed invocations is a workaround.
+ tr ' ' "$nl" < "$tmpdepfile" \
+ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
+ | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+dashXmstdout)
+ # This case only exists to satisfy depend.m4. It is never actually
+ # run, as this mode is specially recognized in the preamble.
+ exit 1
+ ;;
+
+makedepend)
+ "$@" || exit $?
+ # Remove any Libtool call
+ if test "$libtool" = yes; then
+ while test "X$1" != 'X--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+ # X makedepend
+ shift
+ cleared=no eat=no
+ for arg
+ do
+ case $cleared in
+ no)
+ set ""; shift
+ cleared=yes ;;
+ esac
+ if test $eat = yes; then
+ eat=no
+ continue
+ fi
+ case "$arg" in
+ -D*|-I*)
+ set fnord "$@" "$arg"; shift ;;
+ # Strip any option that makedepend may not understand. Remove
+ # the object too, otherwise makedepend will parse it as a source file.
+ -arch)
+ eat=yes ;;
+ -*|$object)
+ ;;
+ *)
+ set fnord "$@" "$arg"; shift ;;
+ esac
+ done
+ obj_suffix=`echo "$object" | sed 's/^.*\././'`
+ touch "$tmpdepfile"
+ ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
+ rm -f "$depfile"
+ # makedepend may prepend the VPATH from the source file name to the object.
+ # No need to regex-escape $object, excess matching of '.' is harmless.
+ sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
+ # Some versions of the HPUX 10.20 sed can't process the last invocation
+ # correctly. Breaking it into two sed invocations is a workaround.
+ sed '1,2d' "$tmpdepfile" \
+ | tr ' ' "$nl" \
+ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
+ | sed -e 's/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile" "$tmpdepfile".bak
+ ;;
+
+cpp)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the preprocessed file to stdout.
+ "$@" || exit $?
+
+ # Remove the call to Libtool.
+ if test "$libtool" = yes; then
+ while test "X$1" != 'X--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+
+ # Remove '-o $object'.
+ IFS=" "
+ for arg
+ do
+ case $arg in
+ -o)
+ shift
+ ;;
+ $object)
+ shift
+ ;;
+ *)
+ set fnord "$@" "$arg"
+ shift # fnord
+ shift # $arg
+ ;;
+ esac
+ done
+
+ "$@" -E \
+ | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
+ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
+ | sed '$ s: \\$::' > "$tmpdepfile"
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ cat < "$tmpdepfile" >> "$depfile"
+ sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+msvisualcpp)
+ # Important note: in order to support this mode, a compiler *must*
+ # always write the preprocessed file to stdout.
+ "$@" || exit $?
+
+ # Remove the call to Libtool.
+ if test "$libtool" = yes; then
+ while test "X$1" != 'X--mode=compile'; do
+ shift
+ done
+ shift
+ fi
+
+ IFS=" "
+ for arg
+ do
+ case "$arg" in
+ -o)
+ shift
+ ;;
+ $object)
+ shift
+ ;;
+ "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
+ set fnord "$@"
+ shift
+ shift
+ ;;
+ *)
+ set fnord "$@" "$arg"
+ shift
+ shift
+ ;;
+ esac
+ done
+ "$@" -E 2>/dev/null |
+ sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
+ rm -f "$depfile"
+ echo "$object : \\" > "$depfile"
+ sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
+ echo "$tab" >> "$depfile"
+ sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
+ rm -f "$tmpdepfile"
+ ;;
+
+msvcmsys)
+ # This case exists only to let depend.m4 do its work. It works by
+ # looking at the text of this script. This case will never be run,
+ # since it is checked for above.
+ exit 1
+ ;;
+
+none)
+ exec "$@"
+ ;;
+
+*)
+ echo "Unknown depmode $depmode" 1>&2
+ exit 1
+ ;;
+esac
+
+exit 0
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC0"
+# time-stamp-end: "; # UTC"
+# End:
--- /dev/null
+
+SUBDIRS = reference
+
+EXTRA_DIST = design.txt
--- /dev/null
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = docs
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/as-compiler-flag.m4 \
+ $(top_srcdir)/m4/ax_check_openssl.m4 \
+ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/introspection.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
+ ctags-recursive dvi-recursive html-recursive info-recursive \
+ install-data-recursive install-dvi-recursive \
+ install-exec-recursive install-html-recursive \
+ install-info-recursive install-pdf-recursive \
+ install-ps-recursive install-recursive installcheck-recursive \
+ installdirs-recursive pdf-recursive ps-recursive \
+ tags-recursive uninstall-recursive
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+am__recursive_targets = \
+ $(RECURSIVE_TARGETS) \
+ $(RECURSIVE_CLEAN_TARGETS) \
+ $(am__extra_recursive_targets)
+AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
+ distdir distdir-am
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+am__DIST_COMMON = $(srcdir)/Makefile.in
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCACHE_DISABLE = @CCACHE_DISABLE@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GST010_CFLAGS = @GST010_CFLAGS@
+GST010_LIBS = @GST010_LIBS@
+GST_CFLAGS = @GST_CFLAGS@
+GST_CHECK_CFLAGS = @GST_CHECK_CFLAGS@
+GST_CHECK_LIBS = @GST_CHECK_LIBS@
+GST_LIBS = @GST_LIBS@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@
+GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@
+GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@
+GTKDOC_MKPDF = @GTKDOC_MKPDF@
+GTKDOC_REBASE = @GTKDOC_REBASE@
+GUPNP_CFLAGS = @GUPNP_CFLAGS@
+GUPNP_LIBS = @GUPNP_LIBS@
+GUPNP_PACKAGES = @GUPNP_PACKAGES@
+GUPNP_PACKAGES_PRIVATE = @GUPNP_PACKAGES_PRIVATE@
+GUPNP_PACKAGES_PUBLIC = @GUPNP_PACKAGES_PUBLIC@
+HAVE_GUPNP = @HAVE_GUPNP@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@
+INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@
+INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@
+INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@
+INTROSPECTION_LIBS = @INTROSPECTION_LIBS@
+INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@
+INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
+INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBNICE_CFLAGS = @LIBNICE_CFLAGS@
+LIBNICE_LT_LDFLAGS = @LIBNICE_LT_LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBRT = @LIBRT@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NICE_PACKAGES_PRIVATE = @NICE_PACKAGES_PRIVATE@
+NICE_PACKAGES_PUBLIC = @NICE_PACKAGES_PUBLIC@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_INCLUDES = @OPENSSL_INCLUDES@
+OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+UPNP_ENABLED = @UPNP_ENABLED@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gstplugin010dir = @gstplugin010dir@
+gstplugindir = @gstplugindir@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = reference
+EXTRA_DIST = design.txt
+all: all-recursive
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu docs/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu docs/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run 'make' without going through this Makefile.
+# To change the values of 'make' variables: instead of editing Makefiles,
+# (1) if the variable is set in 'config.status', edit 'config.status'
+# (which will cause the Makefiles to be regenerated when you run 'make');
+# (2) otherwise, pass the desired values on the 'make' command line.
+$(am__recursive_targets):
+ @fail=; \
+ if $(am__make_keepgoing); then \
+ failcom='fail=yes'; \
+ else \
+ failcom='exit 1'; \
+ fi; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-recursive
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-recursive
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-recursive
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ $(am__make_dryrun) \
+ || test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-recursive
+all-am: Makefile
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(am__recursive_targets) install-am install-strip
+
+.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \
+ check-am clean clean-generic clean-libtool cscopelist-am ctags \
+ ctags-am distclean distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ installdirs-am maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \
+ ps ps-am tags tags-am uninstall uninstall-am
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null
+Nice: Design documentation
+==========================
+
+Socket ownership
+----------------
+
+For UDP candidates, one socket is created for each component and bound
+to INADDR_ANY. The same local socket is used for the host candidate,
+STUN candidate as well as the TURN candidate. The socket handles are
+stored to the Component structure.
+
+The library will use the source address of incoming packets in order
+to identify from which remote candidates, if any (peer-derived
+candidates), packets were sent.
+
+XXX: Describe the subtle issues with ICMP error handling when one
+socket is used to send to multiple destinations.
+
+Real-time considerations
+------------------------
+
+One potential use for libnice code is providing network connectivity
+for media transport in voice and video telephony applications. This
+means that the libnice code is potentially run in real-time context
+(for instance under POSIX SCHED_FIFO/SHCED_RR scheduling policy) and
+ideally has deterministic execution time.
+
+To be real-time friendly, operations with non-deterministic execution
+time (dynamic memory allocation, file and other resource access) should
+be done at startup/initialization phase. During an active session
+(connectivity has been established and non-STUN traffic is being sent),
+code should be as deterministic as possible.
+
+Memory management
+-----------------
+
+To work on platforms where available memory may be constrained, libnice
+should gracefully handle out of memory situations. If memory allocation
+fails, the library should return an error via the originating public
+library API function.
+
+Use of glib creates some challenges to meet the above:
+
+- A lot of glib's internal code assumes memory allocations will
+ always work. Use of these glib facilities should be limited.
+ While the glib default policy (see g_malloc() documentation) of terminating
+ the process is ok for applications, this is not acceptable for library
+ components.
+- Glib has weak support for preallocating structures needed at
+ runtime (for instance use of timers creates a lot of memory
+ allocation activity).
+
+To work around the above limitations, the following guidelines need
+to be followed:
+
+- Always check return values of glib functions.
+- Use safe variants: g_malloc_try(), etc
+- Current issues (last update 2007-05-04)
+ - g_slist_append() will crash if alloc fails
+
+Timers
+------
+
+Management of timers is handled by the 'agent' module. Other modules
+may use timer APIs to get timestamps, but they do not run timers.
+
+Glib's timer interface has some problems that have affected the design:
+
+ - an expired timer will destroy the source (a potentially costly
+ operation)
+ - it is not possible to cancel, or adjust the timer expiration
+ timer without destroying the associated source and creating
+ a new one, which again causes malloc/frees and is potentially
+ a costly operation
+ - on Linux, glib uses gettimeofday() which is subject to clock
+ skew, and no monotonic timer API is available
+
+Due to the above, 'agent' code runs fixed interval periodic timers
+(started with g_timeout_add()) during candidate gathering, connectivity
+check, and session keepalive phases. Timer frequency is set separately
+for each phase of processing. A more elegant design would use dynamic
+timeouts, but this would be too expensive with glib timer
+infrastructure.
+
+Control flow for NICE agent API (NiceAgentClass)
+------------------------------------------------
+
+The main library interface for applications using libnice is the
+NiceAgent GObject interface defined in 'nice/agent.h'.
+
+The rough order of control follow is as follows:
+
+- creation of NiceAgent object instance
+- setting agent properties such as STUN and TURN server addresses
+- connecting the GObject signals with g_signal_connect() to application
+ callback functions
+- adding local interface addresses to use with
+ nice_agent_add_local_address()
+
+And continues when making an initial offer:
+
+- creating the streams with nice_agent_add_stream()
+- attach the mainloop context to connect the NiceAgent sockets to
+ the application's event loop (using nice_agent_attach_recv())
+- start candidate gathering by calling nice_agent_gather_candidates()
+- the application should wait for the "candidate-gathering-done" signal
+ before going forward (so that ICE can gather the needed set of local
+ connectiviy candidates)
+- get the information needed for sending offer using
+ nice_agent_get_local_candidates() and
+ nice_agent_get_local_credentials()
+- client should now send the session offer
+- once it receives an answer, it can pass the information to NiceAgent
+ using nice_agent_set_remote_candidates() and
+ nice_agent_set_remote_credentials()
+
+Alternatively, when answering to an initial offer:
+
+- the first five steps are the same as above (making initial offer)
+- pass the remote session information to NiceAgent using
+ nice_agent_set_remote_candidates() and
+ nice_agent_set_remote_credentials()
+- client can send the answer to session offer
+
+Special considerations for a SIP client:
+
+- Upon sending the initial offer/answer, client should pick one
+ local candidate as the default one, and encode it to the SDP
+ "m" and "c" lines, in addition to the ICE "a=candidate" lines.
+- Client should connect to "new-selected-pair" signals. If this
+ signal is received, a new candidate pair has been set as
+ a selected pair (highest priority nominated pair). See
+ ICE specification for a definition of "nominated pairs".
+- Once all components of a stream have reached the
+ "NICE_COMPONENT_STATE_READY" state (as reported by
+ "component-state-changed" signals), the client should check
+ whether its original default candidate matches the latest
+ selected pair. If not, it needs to send an updated offer
+ it is in controlling mode. Before sending the offer, client
+ should check the "controlling-mode" property to check that
+ it still is in controlling mode (might change during ICE
+ processing due to ICE role conflicts).
+- The "remote-attributes" SDP attribute can be created from
+ the information provided by "component-state-changed" (which
+ components are ready), "new-selected-pair" (which candidates
+ are selected) and "new-remote-candidate" (peer-reflexive
+ candidates discovered during processing) signals.
+- Supporting forked calls is not yet supported by the API (multiple
+ sets of remote candidates for one local set of candidates).
+
+Restarting ICE:
+
+- ICE processing can be restarted by calling nice_agent_restart()
+- Restart will clean the set of remote candidates, so client must
+ afterwards call nice_agent_set_remote_candidates() after receiving
+ a new offer/answer for the restarted ICE session.
+- Restart will reinitialize the local credentials (see
+ nice_agent_get_local_credentials()).
+- Note that to modify the set of local candidates, a new stream
+ has to be created. For the remote party, this looks like a ICE
+ restart as well.
+
+Handling fallback to non-ICE operation:
+
+- If we are the offering party, and the remote party indicates
+ it doesn't support ICE, we can use nice_agent_set_selected_pair()
+ to force selection of a candidate pair (for remote party,
+ the information on SDP 'm=' and 'c=' lines needs to be used
+ to generate one remote candidate for each component of the
+ streams). This function will halt all ICE processing (excluding
+ keepalives), while still allowing to send and receive media (assuming
+ NATs won't interfere).
+
+Notes about sending media:
+
+- Client may send media once all components of a stream have reached
+ state of NICE_COMPONENT_STATE_CONNECTED or NICE_COMPONENT_STATE_READY,
+ (as reported by "component-state-changed" signals), and a selected pair
+ is set for all components (as reported by "new-selected-pair" signals).
+
+STUN API
+--------
+
+The underlying STUN library takes care of formatting and parsing STUN
+messages (lower layer),
+
+Applications should only need to use the higher layer API which then
+uses the lower layer API.
+
+The following STUN usages are currently implemented by the
+transaction layer:
+- Binding discovery (RFC5389 with RFC3489 backward compatibility)
+- Binding keep-alive
+- ICE connectivity checks
+- TURN
+- STUN retransmission timers
+
+
+STUN message API
+----------------
+
+STUN message API provide thin wrappers to parse and format STUN
+messages. To achieve maximum cross-architectures portability and retain
+real-time friendliness, these functions are fully "computational" [1].
+They also make no assumption about endianess or memory alignment
+(reading single bytes or using memcpy()).
+
+Message buffers are provided by the caller (so these can be
+preallocated). Because STUN uses a relatively computer-friendly binary
+format, STUN messages are stored in wire format within the buffers.
+There is no intermediary translation, so the APIs can operate directly
+with data received from or sent to the network.
+
+[1] With one exception: The random number generated might access the
+system entropy pool (/dev/urandom) if available.
--- /dev/null
+
+SUBDIRS = libnice
--- /dev/null
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = docs/reference
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/as-compiler-flag.m4 \
+ $(top_srcdir)/m4/ax_check_openssl.m4 \
+ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/introspection.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
+ ctags-recursive dvi-recursive html-recursive info-recursive \
+ install-data-recursive install-dvi-recursive \
+ install-exec-recursive install-html-recursive \
+ install-info-recursive install-pdf-recursive \
+ install-ps-recursive install-recursive installcheck-recursive \
+ installdirs-recursive pdf-recursive ps-recursive \
+ tags-recursive uninstall-recursive
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+am__recursive_targets = \
+ $(RECURSIVE_TARGETS) \
+ $(RECURSIVE_CLEAN_TARGETS) \
+ $(am__extra_recursive_targets)
+AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
+ distdir distdir-am
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+am__DIST_COMMON = $(srcdir)/Makefile.in
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCACHE_DISABLE = @CCACHE_DISABLE@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GST010_CFLAGS = @GST010_CFLAGS@
+GST010_LIBS = @GST010_LIBS@
+GST_CFLAGS = @GST_CFLAGS@
+GST_CHECK_CFLAGS = @GST_CHECK_CFLAGS@
+GST_CHECK_LIBS = @GST_CHECK_LIBS@
+GST_LIBS = @GST_LIBS@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@
+GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@
+GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@
+GTKDOC_MKPDF = @GTKDOC_MKPDF@
+GTKDOC_REBASE = @GTKDOC_REBASE@
+GUPNP_CFLAGS = @GUPNP_CFLAGS@
+GUPNP_LIBS = @GUPNP_LIBS@
+GUPNP_PACKAGES = @GUPNP_PACKAGES@
+GUPNP_PACKAGES_PRIVATE = @GUPNP_PACKAGES_PRIVATE@
+GUPNP_PACKAGES_PUBLIC = @GUPNP_PACKAGES_PUBLIC@
+HAVE_GUPNP = @HAVE_GUPNP@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@
+INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@
+INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@
+INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@
+INTROSPECTION_LIBS = @INTROSPECTION_LIBS@
+INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@
+INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
+INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBNICE_CFLAGS = @LIBNICE_CFLAGS@
+LIBNICE_LT_LDFLAGS = @LIBNICE_LT_LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBRT = @LIBRT@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NICE_PACKAGES_PRIVATE = @NICE_PACKAGES_PRIVATE@
+NICE_PACKAGES_PUBLIC = @NICE_PACKAGES_PUBLIC@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_INCLUDES = @OPENSSL_INCLUDES@
+OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+UPNP_ENABLED = @UPNP_ENABLED@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gstplugin010dir = @gstplugin010dir@
+gstplugindir = @gstplugindir@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = libnice
+all: all-recursive
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu docs/reference/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu docs/reference/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run 'make' without going through this Makefile.
+# To change the values of 'make' variables: instead of editing Makefiles,
+# (1) if the variable is set in 'config.status', edit 'config.status'
+# (which will cause the Makefiles to be regenerated when you run 'make');
+# (2) otherwise, pass the desired values on the 'make' command line.
+$(am__recursive_targets):
+ @fail=; \
+ if $(am__make_keepgoing); then \
+ failcom='fail=yes'; \
+ else \
+ failcom='exit 1'; \
+ fi; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-recursive
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-recursive
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-recursive
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ $(am__make_dryrun) \
+ || test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-recursive
+all-am: Makefile
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(am__recursive_targets) install-am install-strip
+
+.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \
+ check-am clean clean-generic clean-libtool cscopelist-am ctags \
+ ctags-am distclean distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ installdirs-am maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \
+ ps ps-am tags tags-am uninstall uninstall-am
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null
+## Process this file with automake to produce Makefile.in
+
+# We require automake 1.6 at least.
+AUTOMAKE_OPTIONS = 1.6
+
+# The name of the module, e.g. 'glib'.
+DOC_MODULE=libnice
+
+# The top-level SGML file. You can change this if you want to.
+DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.xml
+
+# The directory containing the source code. Relative to $(srcdir).
+# gtk-doc will search all .c & .h files beneath here for inline comments
+# documenting the functions and macros.
+# e.g. DOC_SOURCE_DIR=../../../gtk
+DOC_SOURCE_DIR=$(top_srcdir)/agent $(top_srcdir)/stun
+
+# Extra options to pass to gtkdoc-scangobj. Not normally needed.
+SCANGOBJ_OPTIONS=
+
+# Extra options to supply to gtkdoc-scan.
+# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
+SCAN_OPTIONS=--rebuild-types
+
+# Extra options to supply to gtkdoc-mkdb.
+# e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml
+MKDB_OPTIONS=--xml-mode --output-format=xml --name-space=Nice
+
+# Extra options to supply to gtkdoc-mktmpl
+# e.g. MKTMPL_OPTIONS=--only-section-tmpl
+MKTMPL_OPTIONS=
+
+# Extra options to supply to gtkdoc-fixref. Not normally needed.
+# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html
+FIXXREF_OPTIONS=
+
+# Used for dependencies. The docs will be rebuilt if any of these change.
+# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h
+# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c
+HFILE_GLOB=$(top_srcdir)/agent/agent.h $(top_srcdir)/agent/address.h \
+ $(top_srcdir)/agent/debug.h $(top_srcdir)/agent/candidate.h \
+ $(top_srcdir)/agent/interfaces.h \
+ $(top_srcdir)/agent/pseudotcp.h \
+ $(top_srcdir)/stun/stunagent.h \
+ $(top_srcdir)/stun/stunmessage.h \
+ $(top_srcdir)/stun/debug.h \
+ $(top_srcdir)/stun/usages/bind.h \
+ $(top_srcdir)/stun/usages/ice.h \
+ $(top_srcdir)/stun/usages/timer.h \
+ $(top_srcdir)/stun/usages/turn.h
+
+CFILE_GLOB=$(top_srcdir)/agent/agent.c \
+ $(top_srcdir)/agent/pseudotcp.c
+
+# Header files to ignore when scanning.
+# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h
+IGNORE_HFILES= conncheck.h discovery.h stream.h component.h agent-priv.h \
+ iostream.h inputstream.h outputstream.h \
+ gstnice.h gstnicesrc.h gstnicesink.h \
+ md5.h sha1.h stunhmac.h utils.h rand.h stun5389.h stuncrc32.h \
+ stund.h agent-signals-marshal.h win32_common.h
+
+# Images to copy into HTML directory.
+# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
+HTML_IMAGES = states.png
+
+# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
+# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
+content_files=
+
+# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
+# These files must be listed here *and* in content_files
+# e.g. expand_content_files=running.sgml
+expand_content_files=
+
+# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library.
+# Only needed if you are using gtkdoc-scangobj to dynamically query widget
+# signals and properties.
+# e.g. INCLUDES=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
+# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
+AM_CFLAGS = $(LIBNICE_CFLAGS) \
+ $(GLIB_CFLAGS) \
+ -I $(top_srcdir) \
+ -I $(top_srcdir)/random \
+ -I $(top_srcdir)/socket \
+ -I $(top_srcdir)/stun
+
+GTKDOC_LIBS= $(top_builddir)/agent/libagent.la $(GLIB_LIBS) $(top_builddir)/stun/libstun.la \
+ $(GUPNP_LIBS)
+
+
+# This includes the standard gtk-doc make rules, copied by gtkdocize.
+include $(top_srcdir)/gtk-doc.make
+
+# Other files to distribute
+# e.g. EXTRA_DIST += version.xml.in
+EXTRA_DIST += states.gv
+
+EXTRA_DIST += meson.build
+
+# Files not to distribute
+# for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types
+# for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt
+#DISTCLEANFILES +=
+
+# If we ever need to regenerate this diagram.
+# Since it’s not expected to change much, let’s not depend on GraphViz to
+# build the docs.
+states.png: states.gv
+ dot -Tpng -Gsize=9.6,2.9\! -Gdpi=200 $^ > $@
+
+if ENABLE_GTK_DOC
+TESTS_ENVIRONMENT = \
+ DOC_MODULE=$(DOC_MODULE) DOC_MAIN_SGML_FILE=$(DOC_MAIN_SGML_FILE) \
+ SRCDIR=$(abs_srcdir) BUILDDIR=$(abs_builddir)
+TESTS = $(GTKDOC_CHECK)
+endif
--- /dev/null
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# -*- mode: makefile -*-
+
+####################################
+# Everything below here is generic #
+####################################
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = docs/reference/libnice
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/as-compiler-flag.m4 \
+ $(top_srcdir)/m4/ax_check_openssl.m4 \
+ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/introspection.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+am__tty_colors_dummy = \
+ mgn= red= grn= lgn= blu= brg= std=; \
+ am__color_tests=no
+am__tty_colors = { \
+ $(am__tty_colors_dummy); \
+ if test "X$(AM_COLOR_TESTS)" = Xno; then \
+ am__color_tests=no; \
+ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
+ am__color_tests=yes; \
+ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
+ am__color_tests=yes; \
+ fi; \
+ if test $$am__color_tests = yes; then \
+ red='\e[0;31m'; \
+ grn='\e[0;32m'; \
+ lgn='\e[1;32m'; \
+ blu='\e[1;34m'; \
+ mgn='\e[0;35m'; \
+ brg='\e[1m'; \
+ std='\e[m'; \
+ fi; \
+}
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__recheck_rx = ^[ ]*:recheck:[ ]*
+am__global_test_result_rx = ^[ ]*:global-test-result:[ ]*
+am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]*
+# A command that, given a newline-separated list of test names on the
+# standard input, print the name of the tests that are to be re-run
+# upon "make recheck".
+am__list_recheck_tests = $(AWK) '{ \
+ recheck = 1; \
+ while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+ { \
+ if (rc < 0) \
+ { \
+ if ((getline line2 < ($$0 ".log")) < 0) \
+ recheck = 0; \
+ break; \
+ } \
+ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \
+ { \
+ recheck = 0; \
+ break; \
+ } \
+ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \
+ { \
+ break; \
+ } \
+ }; \
+ if (recheck) \
+ print $$0; \
+ close ($$0 ".trs"); \
+ close ($$0 ".log"); \
+}'
+# A command that, given a newline-separated list of test names on the
+# standard input, create the global log from their .trs and .log files.
+am__create_global_log = $(AWK) ' \
+function fatal(msg) \
+{ \
+ print "fatal: making $@: " msg | "cat >&2"; \
+ exit 1; \
+} \
+function rst_section(header) \
+{ \
+ print header; \
+ len = length(header); \
+ for (i = 1; i <= len; i = i + 1) \
+ printf "="; \
+ printf "\n\n"; \
+} \
+{ \
+ copy_in_global_log = 1; \
+ global_test_result = "RUN"; \
+ while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+ { \
+ if (rc < 0) \
+ fatal("failed to read from " $$0 ".trs"); \
+ if (line ~ /$(am__global_test_result_rx)/) \
+ { \
+ sub("$(am__global_test_result_rx)", "", line); \
+ sub("[ ]*$$", "", line); \
+ global_test_result = line; \
+ } \
+ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \
+ copy_in_global_log = 0; \
+ }; \
+ if (copy_in_global_log) \
+ { \
+ rst_section(global_test_result ": " $$0); \
+ while ((rc = (getline line < ($$0 ".log"))) != 0) \
+ { \
+ if (rc < 0) \
+ fatal("failed to read from " $$0 ".log"); \
+ print line; \
+ }; \
+ printf "\n"; \
+ }; \
+ close ($$0 ".trs"); \
+ close ($$0 ".log"); \
+}'
+# Restructured Text title.
+am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; }
+# Solaris 10 'make', and several other traditional 'make' implementations,
+# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it
+# by disabling -e (using the XSI extension "set +e") if it's set.
+am__sh_e_setup = case $$- in *e*) set +e;; esac
+# Default flags passed to test drivers.
+am__common_driver_flags = \
+ --color-tests "$$am__color_tests" \
+ --enable-hard-errors "$$am__enable_hard_errors" \
+ --expect-failure "$$am__expect_failure"
+# To be inserted before the command running the test. Creates the
+# directory for the log if needed. Stores in $dir the directory
+# containing $f, in $tst the test, in $log the log. Executes the
+# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and
+# passes TESTS_ENVIRONMENT. Set up options for the wrapper that
+# will run the test scripts (or their associated LOG_COMPILER, if
+# thy have one).
+am__check_pre = \
+$(am__sh_e_setup); \
+$(am__vpath_adj_setup) $(am__vpath_adj) \
+$(am__tty_colors); \
+srcdir=$(srcdir); export srcdir; \
+case "$@" in \
+ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \
+ *) am__odir=.;; \
+esac; \
+test "x$$am__odir" = x"." || test -d "$$am__odir" \
+ || $(MKDIR_P) "$$am__odir" || exit $$?; \
+if test -f "./$$f"; then dir=./; \
+elif test -f "$$f"; then dir=; \
+else dir="$(srcdir)/"; fi; \
+tst=$$dir$$f; log='$@'; \
+if test -n '$(DISABLE_HARD_ERRORS)'; then \
+ am__enable_hard_errors=no; \
+else \
+ am__enable_hard_errors=yes; \
+fi; \
+case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \
+ am__expect_failure=yes;; \
+ *) \
+ am__expect_failure=no;; \
+esac; \
+$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT)
+# A shell command to get the names of the tests scripts with any registered
+# extension removed (i.e., equivalently, the names of the test logs, with
+# the '.log' extension removed). The result is saved in the shell variable
+# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly,
+# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)",
+# since that might cause problem with VPATH rewrites for suffix-less tests.
+# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'.
+am__set_TESTS_bases = \
+ bases='$(TEST_LOGS)'; \
+ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \
+ bases=`echo $$bases`
+RECHECK_LOGS = $(TEST_LOGS)
+AM_RECURSIVE_TARGETS = check recheck
+TEST_SUITE_LOG = test-suite.log
+TEST_EXTENSIONS = @EXEEXT@ .test
+am__test_logs1 = $(TESTS:=.log)
+am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log)
+TEST_LOGS = $(am__test_logs2:.test.log=.log)
+TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver
+TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \
+ $(TEST_LOG_FLAGS)
+am__set_b = \
+ case '$@' in \
+ */*) \
+ case '$*' in \
+ */*) b='$*';; \
+ *) b=`echo '$@' | sed 's/\.log$$//'`; \
+ esac;; \
+ *) \
+ b='$*';; \
+ esac
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/gtk-doc.make \
+ $(top_srcdir)/test-driver
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCACHE_DISABLE = @CCACHE_DISABLE@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GST010_CFLAGS = @GST010_CFLAGS@
+GST010_LIBS = @GST010_LIBS@
+GST_CFLAGS = @GST_CFLAGS@
+GST_CHECK_CFLAGS = @GST_CHECK_CFLAGS@
+GST_CHECK_LIBS = @GST_CHECK_LIBS@
+GST_LIBS = @GST_LIBS@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@
+GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@
+GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@
+GTKDOC_MKPDF = @GTKDOC_MKPDF@
+GTKDOC_REBASE = @GTKDOC_REBASE@
+GUPNP_CFLAGS = @GUPNP_CFLAGS@
+GUPNP_LIBS = @GUPNP_LIBS@
+GUPNP_PACKAGES = @GUPNP_PACKAGES@
+GUPNP_PACKAGES_PRIVATE = @GUPNP_PACKAGES_PRIVATE@
+GUPNP_PACKAGES_PUBLIC = @GUPNP_PACKAGES_PUBLIC@
+HAVE_GUPNP = @HAVE_GUPNP@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@
+INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@
+INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@
+INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@
+INTROSPECTION_LIBS = @INTROSPECTION_LIBS@
+INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@
+INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
+INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBNICE_CFLAGS = @LIBNICE_CFLAGS@
+LIBNICE_LT_LDFLAGS = @LIBNICE_LT_LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBRT = @LIBRT@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NICE_PACKAGES_PRIVATE = @NICE_PACKAGES_PRIVATE@
+NICE_PACKAGES_PUBLIC = @NICE_PACKAGES_PUBLIC@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_INCLUDES = @OPENSSL_INCLUDES@
+OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+UPNP_ENABLED = @UPNP_ENABLED@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gstplugin010dir = @gstplugin010dir@
+gstplugindir = @gstplugindir@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+
+# We require automake 1.6 at least.
+AUTOMAKE_OPTIONS = 1.6
+
+# The name of the module, e.g. 'glib'.
+DOC_MODULE = libnice
+
+# The top-level SGML file. You can change this if you want to.
+DOC_MAIN_SGML_FILE = $(DOC_MODULE)-docs.xml
+
+# The directory containing the source code. Relative to $(srcdir).
+# gtk-doc will search all .c & .h files beneath here for inline comments
+# documenting the functions and macros.
+# e.g. DOC_SOURCE_DIR=../../../gtk
+DOC_SOURCE_DIR = $(top_srcdir)/agent $(top_srcdir)/stun
+
+# Extra options to pass to gtkdoc-scangobj. Not normally needed.
+SCANGOBJ_OPTIONS =
+
+# Extra options to supply to gtkdoc-scan.
+# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
+SCAN_OPTIONS = --rebuild-types
+
+# Extra options to supply to gtkdoc-mkdb.
+# e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml
+MKDB_OPTIONS = --xml-mode --output-format=xml --name-space=Nice
+
+# Extra options to supply to gtkdoc-mktmpl
+# e.g. MKTMPL_OPTIONS=--only-section-tmpl
+MKTMPL_OPTIONS =
+
+# Extra options to supply to gtkdoc-fixref. Not normally needed.
+# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html
+FIXXREF_OPTIONS =
+
+# Used for dependencies. The docs will be rebuilt if any of these change.
+# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h
+# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c
+HFILE_GLOB = $(top_srcdir)/agent/agent.h $(top_srcdir)/agent/address.h \
+ $(top_srcdir)/agent/debug.h $(top_srcdir)/agent/candidate.h \
+ $(top_srcdir)/agent/interfaces.h \
+ $(top_srcdir)/agent/pseudotcp.h \
+ $(top_srcdir)/stun/stunagent.h \
+ $(top_srcdir)/stun/stunmessage.h \
+ $(top_srcdir)/stun/debug.h \
+ $(top_srcdir)/stun/usages/bind.h \
+ $(top_srcdir)/stun/usages/ice.h \
+ $(top_srcdir)/stun/usages/timer.h \
+ $(top_srcdir)/stun/usages/turn.h
+
+CFILE_GLOB = $(top_srcdir)/agent/agent.c \
+ $(top_srcdir)/agent/pseudotcp.c
+
+
+# Header files to ignore when scanning.
+# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h
+IGNORE_HFILES = conncheck.h discovery.h stream.h component.h agent-priv.h \
+ iostream.h inputstream.h outputstream.h \
+ gstnice.h gstnicesrc.h gstnicesink.h \
+ md5.h sha1.h stunhmac.h utils.h rand.h stun5389.h stuncrc32.h \
+ stund.h agent-signals-marshal.h win32_common.h
+
+
+# Images to copy into HTML directory.
+# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
+HTML_IMAGES = states.png
+
+# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
+# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
+content_files =
+
+# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
+# These files must be listed here *and* in content_files
+# e.g. expand_content_files=running.sgml
+expand_content_files =
+
+# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library.
+# Only needed if you are using gtkdoc-scangobj to dynamically query widget
+# signals and properties.
+# e.g. INCLUDES=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
+# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
+AM_CFLAGS = $(LIBNICE_CFLAGS) \
+ $(GLIB_CFLAGS) \
+ -I $(top_srcdir) \
+ -I $(top_srcdir)/random \
+ -I $(top_srcdir)/socket \
+ -I $(top_srcdir)/stun
+
+GTKDOC_LIBS = $(top_builddir)/agent/libagent.la $(GLIB_LIBS) $(top_builddir)/stun/libstun.la \
+ $(GUPNP_LIBS)
+
+@GTK_DOC_USE_LIBTOOL_FALSE@GTKDOC_CC = $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+@GTK_DOC_USE_LIBTOOL_TRUE@GTKDOC_CC = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+@GTK_DOC_USE_LIBTOOL_FALSE@GTKDOC_LD = $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS)
+@GTK_DOC_USE_LIBTOOL_TRUE@GTKDOC_LD = $(LIBTOOL) --tag=CC --mode=link $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS)
+@GTK_DOC_USE_LIBTOOL_FALSE@GTKDOC_RUN =
+@GTK_DOC_USE_LIBTOOL_TRUE@GTKDOC_RUN = $(LIBTOOL) --mode=execute
+
+# We set GPATH here; this gives us semantics for GNU make
+# which are more like other make's VPATH, when it comes to
+# whether a source that is a target of one rule is then
+# searched for in VPATH/GPATH.
+#
+GPATH = $(srcdir)
+TARGET_DIR = $(HTML_DIR)/$(DOC_MODULE)
+SETUP_FILES = \
+ $(content_files) \
+ $(expand_content_files) \
+ $(DOC_MAIN_SGML_FILE) \
+ $(DOC_MODULE)-sections.txt \
+ $(DOC_MODULE)-overrides.txt
+
+
+# This includes the standard gtk-doc make rules, copied by gtkdocize.
+
+# Other files to distribute
+# e.g. EXTRA_DIST += version.xml.in
+EXTRA_DIST = $(HTML_IMAGES) $(SETUP_FILES) states.gv meson.build
+DOC_STAMPS = setup-build.stamp scan-build.stamp sgml-build.stamp \
+ html-build.stamp pdf-build.stamp \
+ sgml.stamp html.stamp pdf.stamp
+
+SCANOBJ_FILES = \
+ $(DOC_MODULE).args \
+ $(DOC_MODULE).hierarchy \
+ $(DOC_MODULE).interfaces \
+ $(DOC_MODULE).prerequisites \
+ $(DOC_MODULE).signals
+
+REPORT_FILES = \
+ $(DOC_MODULE)-undocumented.txt \
+ $(DOC_MODULE)-undeclared.txt \
+ $(DOC_MODULE)-unused.txt
+
+CLEANFILES = $(SCANOBJ_FILES) $(REPORT_FILES) $(DOC_STAMPS) gtkdoc-check.test
+@GTK_DOC_BUILD_HTML_FALSE@HTML_BUILD_STAMP =
+@GTK_DOC_BUILD_HTML_TRUE@HTML_BUILD_STAMP = html-build.stamp
+@GTK_DOC_BUILD_PDF_FALSE@PDF_BUILD_STAMP =
+@GTK_DOC_BUILD_PDF_TRUE@PDF_BUILD_STAMP = pdf-build.stamp
+
+#### setup ####
+GTK_DOC_V_SETUP = $(GTK_DOC_V_SETUP_$(V))
+GTK_DOC_V_SETUP_ = $(GTK_DOC_V_SETUP_$(AM_DEFAULT_VERBOSITY))
+GTK_DOC_V_SETUP_0 = @echo " DOC Preparing build";
+
+#### scan ####
+GTK_DOC_V_SCAN = $(GTK_DOC_V_SCAN_$(V))
+GTK_DOC_V_SCAN_ = $(GTK_DOC_V_SCAN_$(AM_DEFAULT_VERBOSITY))
+GTK_DOC_V_SCAN_0 = @echo " DOC Scanning header files";
+GTK_DOC_V_INTROSPECT = $(GTK_DOC_V_INTROSPECT_$(V))
+GTK_DOC_V_INTROSPECT_ = $(GTK_DOC_V_INTROSPECT_$(AM_DEFAULT_VERBOSITY))
+GTK_DOC_V_INTROSPECT_0 = @echo " DOC Introspecting gobjects";
+
+#### xml ####
+GTK_DOC_V_XML = $(GTK_DOC_V_XML_$(V))
+GTK_DOC_V_XML_ = $(GTK_DOC_V_XML_$(AM_DEFAULT_VERBOSITY))
+GTK_DOC_V_XML_0 = @echo " DOC Building XML";
+
+#### html ####
+GTK_DOC_V_HTML = $(GTK_DOC_V_HTML_$(V))
+GTK_DOC_V_HTML_ = $(GTK_DOC_V_HTML_$(AM_DEFAULT_VERBOSITY))
+GTK_DOC_V_HTML_0 = @echo " DOC Building HTML";
+GTK_DOC_V_XREF = $(GTK_DOC_V_XREF_$(V))
+GTK_DOC_V_XREF_ = $(GTK_DOC_V_XREF_$(AM_DEFAULT_VERBOSITY))
+GTK_DOC_V_XREF_0 = @echo " DOC Fixing cross-references";
+
+#### pdf ####
+GTK_DOC_V_PDF = $(GTK_DOC_V_PDF_$(V))
+GTK_DOC_V_PDF_ = $(GTK_DOC_V_PDF_$(AM_DEFAULT_VERBOSITY))
+GTK_DOC_V_PDF_0 = @echo " DOC Building PDF";
+@ENABLE_GTK_DOC_TRUE@TESTS_ENVIRONMENT = \
+@ENABLE_GTK_DOC_TRUE@ DOC_MODULE=$(DOC_MODULE) DOC_MAIN_SGML_FILE=$(DOC_MAIN_SGML_FILE) \
+@ENABLE_GTK_DOC_TRUE@ SRCDIR=$(abs_srcdir) BUILDDIR=$(abs_builddir)
+
+@ENABLE_GTK_DOC_TRUE@TESTS = $(GTKDOC_CHECK)
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .log .test .test$(EXEEXT) .trs
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/gtk-doc.make $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu docs/reference/libnice/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu docs/reference/libnice/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+$(top_srcdir)/gtk-doc.make $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+tags TAGS:
+
+ctags CTAGS:
+
+cscope cscopelist:
+
+
+# Recover from deleted '.trs' file; this should ensure that
+# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create
+# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells
+# to avoid problems with "make -n".
+.log.trs:
+ rm -f $< $@
+ $(MAKE) $(AM_MAKEFLAGS) $<
+
+# Leading 'am--fnord' is there to ensure the list of targets does not
+# expand to empty, as could happen e.g. with make check TESTS=''.
+am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck)
+am--force-recheck:
+ @:
+
+$(TEST_SUITE_LOG): $(TEST_LOGS)
+ @$(am__set_TESTS_bases); \
+ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \
+ redo_bases=`for i in $$bases; do \
+ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \
+ done`; \
+ if test -n "$$redo_bases"; then \
+ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \
+ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \
+ if $(am__make_dryrun); then :; else \
+ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \
+ fi; \
+ fi; \
+ if test -n "$$am__remaking_logs"; then \
+ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \
+ "recursion detected" >&2; \
+ elif test -n "$$redo_logs"; then \
+ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \
+ fi; \
+ if $(am__make_dryrun); then :; else \
+ st=0; \
+ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \
+ for i in $$redo_bases; do \
+ test -f $$i.trs && test -r $$i.trs \
+ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \
+ test -f $$i.log && test -r $$i.log \
+ || { echo "$$errmsg $$i.log" >&2; st=1; }; \
+ done; \
+ test $$st -eq 0 || exit 1; \
+ fi
+ @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \
+ ws='[ ]'; \
+ results=`for b in $$bases; do echo $$b.trs; done`; \
+ test -n "$$results" || results=/dev/null; \
+ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \
+ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \
+ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \
+ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \
+ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \
+ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \
+ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \
+ if test `expr $$fail + $$xpass + $$error` -eq 0; then \
+ success=true; \
+ else \
+ success=false; \
+ fi; \
+ br='==================='; br=$$br$$br$$br$$br; \
+ result_count () \
+ { \
+ if test x"$$1" = x"--maybe-color"; then \
+ maybe_colorize=yes; \
+ elif test x"$$1" = x"--no-color"; then \
+ maybe_colorize=no; \
+ else \
+ echo "$@: invalid 'result_count' usage" >&2; exit 4; \
+ fi; \
+ shift; \
+ desc=$$1 count=$$2; \
+ if test $$maybe_colorize = yes && test $$count -gt 0; then \
+ color_start=$$3 color_end=$$std; \
+ else \
+ color_start= color_end=; \
+ fi; \
+ echo "$${color_start}# $$desc $$count$${color_end}"; \
+ }; \
+ create_testsuite_report () \
+ { \
+ result_count $$1 "TOTAL:" $$all "$$brg"; \
+ result_count $$1 "PASS: " $$pass "$$grn"; \
+ result_count $$1 "SKIP: " $$skip "$$blu"; \
+ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \
+ result_count $$1 "FAIL: " $$fail "$$red"; \
+ result_count $$1 "XPASS:" $$xpass "$$red"; \
+ result_count $$1 "ERROR:" $$error "$$mgn"; \
+ }; \
+ { \
+ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \
+ $(am__rst_title); \
+ create_testsuite_report --no-color; \
+ echo; \
+ echo ".. contents:: :depth: 2"; \
+ echo; \
+ for b in $$bases; do echo $$b; done \
+ | $(am__create_global_log); \
+ } >$(TEST_SUITE_LOG).tmp || exit 1; \
+ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \
+ if $$success; then \
+ col="$$grn"; \
+ else \
+ col="$$red"; \
+ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \
+ fi; \
+ echo "$${col}$$br$${std}"; \
+ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \
+ echo "$${col}$$br$${std}"; \
+ create_testsuite_report --maybe-color; \
+ echo "$$col$$br$$std"; \
+ if $$success; then :; else \
+ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \
+ if test -n "$(PACKAGE_BUGREPORT)"; then \
+ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \
+ fi; \
+ echo "$$col$$br$$std"; \
+ fi; \
+ $$success || exit 1
+
+check-TESTS:
+ @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list
+ @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list
+ @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+ @set +e; $(am__set_TESTS_bases); \
+ log_list=`for i in $$bases; do echo $$i.log; done`; \
+ trs_list=`for i in $$bases; do echo $$i.trs; done`; \
+ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \
+ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \
+ exit $$?;
+recheck: all
+ @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+ @set +e; $(am__set_TESTS_bases); \
+ bases=`for i in $$bases; do echo $$i; done \
+ | $(am__list_recheck_tests)` || exit 1; \
+ log_list=`for i in $$bases; do echo $$i.log; done`; \
+ log_list=`echo $$log_list`; \
+ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \
+ am__force_recheck=am--force-recheck \
+ TEST_LOGS="$$log_list"; \
+ exit $$?
+.test.log:
+ @p='$<'; \
+ $(am__set_b); \
+ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+@am__EXEEXT_TRUE@.test$(EXEEXT).log:
+@am__EXEEXT_TRUE@ @p='$<'; \
+@am__EXEEXT_TRUE@ $(am__set_b); \
+@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \
+@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT)
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$(top_distdir)" distdir="$(distdir)" \
+ dist-hook
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-am
+@ENABLE_GTK_DOC_FALSE@all-local:
+all-am: Makefile all-local
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+ -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS)
+ -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs)
+ -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-local mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-local
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-data-local
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic \
+ maintainer-clean-local
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-local
+
+.MAKE: check-am install-am install-strip
+
+.PHONY: all all-am all-local check check-TESTS check-am clean \
+ clean-generic clean-libtool clean-local cscopelist-am ctags-am \
+ dist-hook distclean distclean-generic distclean-libtool \
+ distclean-local distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am \
+ install-data-local install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic maintainer-clean-local mostlyclean \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ recheck tags-am uninstall uninstall-am uninstall-local
+
+.PRECIOUS: Makefile
+
+
+gtkdoc-check.test: Makefile
+ $(AM_V_GEN)echo "#!/bin/sh -e" > $@; \
+ echo "$(GTKDOC_CHECK_PATH) || exit 1" >> $@; \
+ chmod +x $@
+
+all-gtk-doc: $(HTML_BUILD_STAMP) $(PDF_BUILD_STAMP)
+.PHONY: all-gtk-doc
+
+@ENABLE_GTK_DOC_TRUE@all-local: all-gtk-doc
+
+docs: $(HTML_BUILD_STAMP) $(PDF_BUILD_STAMP)
+
+$(REPORT_FILES): sgml-build.stamp
+
+setup-build.stamp:
+ -$(GTK_DOC_V_SETUP)if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \
+ files=`echo $(SETUP_FILES) $(DOC_MODULE).types`; \
+ if test "x$$files" != "x" ; then \
+ for file in $$files ; do \
+ destdir=`dirname $(abs_builddir)/$$file`; \
+ test -d "$$destdir" || mkdir -p "$$destdir"; \
+ test -f $(abs_srcdir)/$$file && \
+ cp -pf $(abs_srcdir)/$$file $(abs_builddir)/$$file || true; \
+ done; \
+ fi; \
+ fi
+ $(AM_V_at)touch setup-build.stamp
+
+scan-build.stamp: setup-build.stamp $(HFILE_GLOB) $(CFILE_GLOB)
+ $(GTK_DOC_V_SCAN)_source_dir='' ; \
+ for i in $(DOC_SOURCE_DIR) ; do \
+ _source_dir="$${_source_dir} --source-dir=$$i" ; \
+ done ; \
+ gtkdoc-scan --module=$(DOC_MODULE) --ignore-headers="$(IGNORE_HFILES)" $${_source_dir} $(SCAN_OPTIONS) $(EXTRA_HFILES)
+ $(GTK_DOC_V_INTROSPECT)if grep -l '^..*$$' $(DOC_MODULE).types > /dev/null 2>&1 ; then \
+ scanobj_options=""; \
+ gtkdoc-scangobj 2>&1 --help | grep >/dev/null "\-\-verbose"; \
+ if test "$$?" = "0"; then \
+ if test "x$(V)" = "x1"; then \
+ scanobj_options="--verbose"; \
+ fi; \
+ fi; \
+ CC="$(GTKDOC_CC)" LD="$(GTKDOC_LD)" RUN="$(GTKDOC_RUN)" CFLAGS="$(GTKDOC_CFLAGS) $(CFLAGS)" LDFLAGS="$(GTKDOC_LIBS) $(LDFLAGS)" \
+ gtkdoc-scangobj $(SCANGOBJ_OPTIONS) $$scanobj_options --module=$(DOC_MODULE); \
+ else \
+ for i in $(SCANOBJ_FILES) ; do \
+ test -f $$i || touch $$i ; \
+ done \
+ fi
+ $(AM_V_at)touch scan-build.stamp
+
+$(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt: scan-build.stamp
+ @true
+
+sgml-build.stamp: setup-build.stamp $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(HFILE_GLOB) $(CFILE_GLOB) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt $(expand_content_files) xml/gtkdocentities.ent
+ $(GTK_DOC_V_XML)_source_dir='' ; \
+ for i in $(DOC_SOURCE_DIR) ; do \
+ _source_dir="$${_source_dir} --source-dir=$$i" ; \
+ done ; \
+ gtkdoc-mkdb --module=$(DOC_MODULE) --output-format=xml --expand-content-files="$(expand_content_files)" --main-sgml-file=$(DOC_MAIN_SGML_FILE) $${_source_dir} $(MKDB_OPTIONS)
+ $(AM_V_at)touch sgml-build.stamp
+
+sgml.stamp: sgml-build.stamp
+ @true
+
+xml/gtkdocentities.ent: Makefile
+ $(GTK_DOC_V_XML)$(MKDIR_P) $(@D) && ( \
+ echo "<!ENTITY package \"$(PACKAGE)\">"; \
+ echo "<!ENTITY package_bugreport \"$(PACKAGE_BUGREPORT)\">"; \
+ echo "<!ENTITY package_name \"$(PACKAGE_NAME)\">"; \
+ echo "<!ENTITY package_string \"$(PACKAGE_STRING)\">"; \
+ echo "<!ENTITY package_tarname \"$(PACKAGE_TARNAME)\">"; \
+ echo "<!ENTITY package_url \"$(PACKAGE_URL)\">"; \
+ echo "<!ENTITY package_version \"$(PACKAGE_VERSION)\">"; \
+ ) > $@
+
+html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_content_files)
+ $(GTK_DOC_V_HTML)rm -rf html && mkdir html && \
+ mkhtml_options=""; \
+ gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-verbose"; \
+ if test "$$?" = "0"; then \
+ if test "x$(V)" = "x1"; then \
+ mkhtml_options="$$mkhtml_options --verbose"; \
+ fi; \
+ fi; \
+ gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-path"; \
+ if test "$$?" = "0"; then \
+ mkhtml_options="$$mkhtml_options --path=\"$(abs_srcdir)\""; \
+ fi; \
+ cd html && gtkdoc-mkhtml $$mkhtml_options $(MKHTML_OPTIONS) $(DOC_MODULE) ../$(DOC_MAIN_SGML_FILE)
+ -@test "x$(HTML_IMAGES)" = "x" || \
+ for file in $(HTML_IMAGES) ; do \
+ if test -f $(abs_srcdir)/$$file ; then \
+ cp $(abs_srcdir)/$$file $(abs_builddir)/html; \
+ fi; \
+ if test -f $(abs_builddir)/$$file ; then \
+ cp $(abs_builddir)/$$file $(abs_builddir)/html; \
+ fi; \
+ done;
+ $(GTK_DOC_V_XREF)gtkdoc-fixxref --module=$(DOC_MODULE) --module-dir=html --html-dir=$(HTML_DIR) $(FIXXREF_OPTIONS)
+ $(AM_V_at)touch html-build.stamp
+
+pdf-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_content_files)
+ $(GTK_DOC_V_PDF)rm -f $(DOC_MODULE).pdf && \
+ mkpdf_options=""; \
+ gtkdoc-mkpdf 2>&1 --help | grep >/dev/null "\-\-verbose"; \
+ if test "$$?" = "0"; then \
+ if test "x$(V)" = "x1"; then \
+ mkpdf_options="$$mkpdf_options --verbose"; \
+ fi; \
+ fi; \
+ if test "x$(HTML_IMAGES)" != "x"; then \
+ for img in $(HTML_IMAGES); do \
+ part=`dirname $$img`; \
+ echo $$mkpdf_options | grep >/dev/null "\-\-imgdir=$$part "; \
+ if test $$? != 0; then \
+ mkpdf_options="$$mkpdf_options --imgdir=$$part"; \
+ fi; \
+ done; \
+ fi; \
+ gtkdoc-mkpdf --path="$(abs_srcdir)" $$mkpdf_options $(DOC_MODULE) $(DOC_MAIN_SGML_FILE) $(MKPDF_OPTIONS)
+ $(AM_V_at)touch pdf-build.stamp
+
+##############
+
+clean-local:
+ @rm -f *~ *.bak
+ @rm -rf .libs
+ @if echo $(SCAN_OPTIONS) | grep -q "\-\-rebuild-types" ; then \
+ rm -f $(DOC_MODULE).types; \
+ fi
+ @if echo $(SCAN_OPTIONS) | grep -q "\-\-rebuild-sections" ; then \
+ rm -f $(DOC_MODULE)-sections.txt; \
+ fi
+
+distclean-local:
+ @rm -rf xml html $(REPORT_FILES) $(DOC_MODULE).pdf \
+ $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt
+ @if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \
+ rm -f $(SETUP_FILES) $(DOC_MODULE).types; \
+ fi
+
+maintainer-clean-local:
+ @rm -rf xml html
+
+install-data-local:
+ @installfiles=`echo $(builddir)/html/*`; \
+ if test "$$installfiles" = '$(builddir)/html/*'; \
+ then echo 1>&2 'Nothing to install' ; \
+ else \
+ if test -n "$(DOC_MODULE_VERSION)"; then \
+ installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \
+ else \
+ installdir="$(DESTDIR)$(TARGET_DIR)"; \
+ fi; \
+ $(mkinstalldirs) $${installdir} ; \
+ for i in $$installfiles; do \
+ echo ' $(INSTALL_DATA) '$$i ; \
+ $(INSTALL_DATA) $$i $${installdir}; \
+ done; \
+ if test -n "$(DOC_MODULE_VERSION)"; then \
+ mv -f $${installdir}/$(DOC_MODULE).devhelp2 \
+ $${installdir}/$(DOC_MODULE)-$(DOC_MODULE_VERSION).devhelp2; \
+ fi; \
+ $(GTKDOC_REBASE) --relative --dest-dir=$(DESTDIR) --html-dir=$${installdir}; \
+ fi
+
+uninstall-local:
+ @if test -n "$(DOC_MODULE_VERSION)"; then \
+ installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \
+ else \
+ installdir="$(DESTDIR)$(TARGET_DIR)"; \
+ fi; \
+ rm -rf $${installdir}
+
+#
+# Require gtk-doc when making dist
+#
+@HAVE_GTK_DOC_TRUE@dist-check-gtkdoc: docs
+@HAVE_GTK_DOC_FALSE@dist-check-gtkdoc:
+@HAVE_GTK_DOC_FALSE@ @echo "*** gtk-doc is needed to run 'make dist'. ***"
+@HAVE_GTK_DOC_FALSE@ @echo "*** gtk-doc was not found when 'configure' ran. ***"
+@HAVE_GTK_DOC_FALSE@ @echo "*** please install gtk-doc and rerun 'configure'. ***"
+@HAVE_GTK_DOC_FALSE@ @false
+
+dist-hook: dist-check-gtkdoc all-gtk-doc dist-hook-local
+ @mkdir $(distdir)/html
+ @cp ./html/* $(distdir)/html
+ @-cp ./$(DOC_MODULE).pdf $(distdir)/
+ @-cp ./$(DOC_MODULE).types $(distdir)/
+ @-cp ./$(DOC_MODULE)-sections.txt $(distdir)/
+ @cd $(distdir) && rm -f $(DISTCLEANFILES)
+ @$(GTKDOC_REBASE) --online --relative --html-dir=$(distdir)/html
+
+.PHONY : dist-hook-local docs
+
+# Files not to distribute
+# for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types
+# for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt
+#DISTCLEANFILES +=
+
+# If we ever need to regenerate this diagram.
+# Since it’s not expected to change much, let’s not depend on GraphViz to
+# build the docs.
+states.png: states.gv
+ dot -Tpng -Gsize=9.6,2.9\! -Gdpi=200 $^ > $@
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>NiceAgent: libnice Reference Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets Vsnapshot">
+<link rel="home" href="index.html" title="libnice Reference Manual">
+<link rel="up" href="ch01.html" title="">
+<link rel="prev" href="ch01.html" title="">
+<link rel="next" href="libnice-NiceAddress.html" title="NiceAddress">
+<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts">
+<a href="#" class="shortcut">Top</a><span id="nav_description"> <span class="dim">|</span>
+ <a href="#NiceAgent.description" class="shortcut">Description</a></span><span id="nav_hierarchy"> <span class="dim">|</span>
+ <a href="#NiceAgent.object-hierarchy" class="shortcut">Object Hierarchy</a></span><span id="nav_properties"> <span class="dim">|</span>
+ <a href="#NiceAgent.properties" class="shortcut">Properties</a></span><span id="nav_signals"> <span class="dim">|</span>
+ <a href="#NiceAgent.signals" class="shortcut">Signals</a></span>
+</td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="ch01.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="ch01.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="libnice-NiceAddress.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="refentry">
+<a name="NiceAgent"></a><div class="titlepage"></div>
+<div class="refnamediv"><table width="100%"><tr>
+<td valign="top">
+<h2><span class="refentrytitle"><a name="NiceAgent.top_of_page"></a>NiceAgent</span></h2>
+<p>NiceAgent — ICE agent API implementation</p>
+</td>
+<td class="gallery_image" valign="top" align="right"></td>
+</tr></table></div>
+<div class="refsect1">
+<a name="NiceAgent.stability-level"></a><h2>Stability Level</h2>
+<acronym title="The intention of a Stable interface is to enable arbitrary third parties to
+develop applications to these interfaces, release them, and have confidence that
+they will run on all minor releases of the product (after the one in which the
+interface was introduced, and within the same major release). Even at a major
+release, incompatible changes are expected to be rare, and to have strong
+justifications.
+"><span class="acronym">Stable</span></acronym>, unless otherwise indicated
+</div>
+<div class="refsect1">
+<a name="NiceAgent.functions"></a><h2>Functions</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="functions_return">
+<col class="functions_name">
+</colgroup>
+<tbody>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<span class="c_punctuation">(</span><a class="link" href="NiceAgent.html#NiceAgentRecvFunc" title="NiceAgentRecvFunc ()">*NiceAgentRecvFunc</a><span class="c_punctuation">)</span> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="NiceAgent.html" title="NiceAgent"><span class="returnvalue">NiceAgent</span></a> *
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-new" title="nice_agent_new ()">nice_agent_new</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="NiceAgent.html" title="NiceAgent"><span class="returnvalue">NiceAgent</span></a> *
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-new-reliable" title="nice_agent_new_reliable ()">nice_agent_new_reliable</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="NiceAgent.html" title="NiceAgent"><span class="returnvalue">NiceAgent</span></a> *
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-new-full" title="nice_agent_new_full ()">nice_agent_new_full</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-add-local-address" title="nice_agent_add_local_address ()">nice_agent_add_local_address</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-set-port-range" title="nice_agent_set_port_range ()">nice_agent_set_port_range</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="returnvalue">guint</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-add-stream" title="nice_agent_add_stream ()">nice_agent_add_stream</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-remove-stream" title="nice_agent_remove_stream ()">nice_agent_remove_stream</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-set-relay-info" title="nice_agent_set_relay_info ()">nice_agent_set_relay_info</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-forget-relays" title="nice_agent_forget_relays ()">nice_agent_forget_relays</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-gather-candidates" title="nice_agent_gather_candidates ()">nice_agent_gather_candidates</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-set-remote-credentials" title="nice_agent_set_remote_credentials ()">nice_agent_set_remote_credentials</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-get-local-credentials" title="nice_agent_get_local_credentials ()">nice_agent_get_local_credentials</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-set-local-credentials" title="nice_agent_set_local_credentials ()">nice_agent_set_local_credentials</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">int</span>
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-set-remote-candidates" title="nice_agent_set_remote_candidates ()">nice_agent_set_remote_candidates</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Singly-Linked-Lists.html#GSList"><span class="returnvalue">GSList</span></a> *
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-get-remote-candidates" title="nice_agent_get_remote_candidates ()">nice_agent_get_remote_candidates</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Singly-Linked-Lists.html#GSList"><span class="returnvalue">GSList</span></a> *
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-get-local-candidates" title="nice_agent_get_local_candidates ()">nice_agent_get_local_candidates</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-get-selected-pair" title="nice_agent_get_selected_pair ()">nice_agent_get_selected_pair</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-peer-candidate-gathering-done" title="nice_agent_peer_candidate_gathering_done ()">nice_agent_peer_candidate_gathering_done</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gint"><span class="returnvalue">gint</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-send" title="nice_agent_send ()">nice_agent_send</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gint"><span class="returnvalue">gint</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-send-messages-nonblocking" title="nice_agent_send_messages_nonblocking ()">nice_agent_send_messages_nonblocking</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gssize"><span class="returnvalue">gssize</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-recv" title="nice_agent_recv ()">nice_agent_recv</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gint"><span class="returnvalue">gint</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-recv-messages" title="nice_agent_recv_messages ()">nice_agent_recv_messages</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gssize"><span class="returnvalue">gssize</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-recv-nonblocking" title="nice_agent_recv_nonblocking ()">nice_agent_recv_nonblocking</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gint"><span class="returnvalue">gint</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-recv-messages-nonblocking" title="nice_agent_recv_messages_nonblocking ()">nice_agent_recv_messages_nonblocking</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-attach-recv" title="nice_agent_attach_recv ()">nice_agent_attach_recv</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-set-selected-pair" title="nice_agent_set_selected_pair ()">nice_agent_set_selected_pair</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-set-selected-remote-candidate" title="nice_agent_set_selected_remote_candidate ()">nice_agent_set_selected_remote_candidate</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-set-stream-tos" title="nice_agent_set_stream_tos ()">nice_agent_set_stream_tos</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-set-software" title="nice_agent_set_software ()">nice_agent_set_software</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-restart" title="nice_agent_restart ()">nice_agent_restart</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-restart-stream" title="nice_agent_restart_stream ()">nice_agent_restart_stream</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-set-stream-name" title="nice_agent_set_stream_name ()">nice_agent_set_stream_name</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">const <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="returnvalue">gchar</span></a> *
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-get-stream-name" title="nice_agent_get_stream_name ()">nice_agent_get_stream_name</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="NiceCandidate.html" title="NiceCandidate"><span class="returnvalue">NiceCandidate</span></a> *
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-get-default-local-candidate" title="nice_agent_get_default_local_candidate ()">nice_agent_get_default_local_candidate</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="returnvalue">gchar</span></a> *
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-generate-local-sdp" title="nice_agent_generate_local_sdp ()">nice_agent_generate_local_sdp</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="returnvalue">gchar</span></a> *
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-generate-local-stream-sdp" title="nice_agent_generate_local_stream_sdp ()">nice_agent_generate_local_stream_sdp</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="returnvalue">gchar</span></a> *
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-generate-local-candidate-sdp" title="nice_agent_generate_local_candidate_sdp ()">nice_agent_generate_local_candidate_sdp</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">int</span>
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-parse-remote-sdp" title="nice_agent_parse_remote_sdp ()">nice_agent_parse_remote_sdp</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Singly-Linked-Lists.html#GSList"><span class="returnvalue">GSList</span></a> *
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-parse-remote-stream-sdp" title="nice_agent_parse_remote_stream_sdp ()">nice_agent_parse_remote_stream_sdp</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="NiceCandidate.html" title="NiceCandidate"><span class="returnvalue">NiceCandidate</span></a> *
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-parse-remote-candidate-sdp" title="nice_agent_parse_remote_candidate_sdp ()">nice_agent_parse_remote_candidate_sdp</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/gio/GIOStream.html#GIOStream-struct"><span class="returnvalue">GIOStream</span></a> *
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-get-io-stream" title="nice_agent_get_io_stream ()">nice_agent_get_io_stream</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/gio/GSocket.html#GSocket-struct"><span class="returnvalue">GSocket</span></a> *
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-get-selected-socket" title="nice_agent_get_selected_socket ()">nice_agent_get_selected_socket</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="NiceAgent.html#NiceComponentState" title="enum NiceComponentState"><span class="returnvalue">NiceComponentState</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-get-component-state" title="nice_agent_get_component_state ()">nice_agent_get_component_state</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-agent-close-async" title="nice_agent_close_async ()">nice_agent_close_async</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">const <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="returnvalue">gchar</span></a> *
+</td>
+<td class="function_name">
+<a class="link" href="NiceAgent.html#nice-component-state-to-string" title="nice_component_state_to_string ()">nice_component_state_to_string</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect1">
+<a name="NiceAgent.properties"></a><h2>Properties</h2>
+<div class="informaltable"><table class="informaltable" border="0">
+<colgroup>
+<col width="150px" class="properties_type">
+<col width="300px" class="properties_name">
+<col width="200px" class="properties_flags">
+</colgroup>
+<tbody>
+<tr>
+<td class="property_type"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="type">gboolean</span></a></td>
+<td class="property_name"><a class="link" href="NiceAgent.html#NiceAgent--bytestream-tcp" title="The “bytestream-tcp” property">bytestream-tcp</a></td>
+<td class="property_flags">Read</td>
+</tr>
+<tr>
+<td class="property_type"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a></td>
+<td class="property_name"><a class="link" href="NiceAgent.html#NiceAgent--compatibility" title="The “compatibility” property">compatibility</a></td>
+<td class="property_flags">Read / Write / Construct Only</td>
+</tr>
+<tr>
+<td class="property_type"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="type">gboolean</span></a></td>
+<td class="property_name"><a class="link" href="NiceAgent.html#NiceAgent--controlling-mode" title="The “controlling-mode” property">controlling-mode</a></td>
+<td class="property_flags">Read / Write</td>
+</tr>
+<tr>
+<td class="property_type"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="type">gboolean</span></a></td>
+<td class="property_name"><a class="link" href="NiceAgent.html#NiceAgent--force-relay" title="The “force-relay” property">force-relay</a></td>
+<td class="property_flags">Read / Write</td>
+</tr>
+<tr>
+<td class="property_type"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="type">gboolean</span></a></td>
+<td class="property_name"><a class="link" href="NiceAgent.html#NiceAgent--full-mode" title="The “full-mode” property">full-mode</a></td>
+<td class="property_flags">Read / Write / Construct Only</td>
+</tr>
+<tr>
+<td class="property_type"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="type">gboolean</span></a></td>
+<td class="property_name"><a class="link" href="NiceAgent.html#NiceAgent--ice-tcp" title="The “ice-tcp” property">ice-tcp</a></td>
+<td class="property_flags">Read / Write</td>
+</tr>
+<tr>
+<td class="property_type"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="type">gboolean</span></a></td>
+<td class="property_name"><a class="link" href="NiceAgent.html#NiceAgent--ice-trickle" title="The “ice-trickle” property">ice-trickle</a></td>
+<td class="property_flags">Read / Write</td>
+</tr>
+<tr>
+<td class="property_type"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="type">gboolean</span></a></td>
+<td class="property_name"><a class="link" href="NiceAgent.html#NiceAgent--ice-udp" title="The “ice-udp” property">ice-udp</a></td>
+<td class="property_flags">Read / Write</td>
+</tr>
+<tr>
+<td class="property_type"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="type">gboolean</span></a></td>
+<td class="property_name"><a class="link" href="NiceAgent.html#NiceAgent--keepalive-conncheck" title="The “keepalive-conncheck” property">keepalive-conncheck</a></td>
+<td class="property_flags">Read / Write</td>
+</tr>
+<tr>
+<td class="property_type"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gpointer"><span class="type">gpointer</span></a></td>
+<td class="property_name"><a class="link" href="NiceAgent.html#NiceAgent--main-context" title="The “main-context” property">main-context</a></td>
+<td class="property_flags">Read / Write / Construct Only</td>
+</tr>
+<tr>
+<td class="property_type"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a></td>
+<td class="property_name"><a class="link" href="NiceAgent.html#NiceAgent--max-connectivity-checks" title="The “max-connectivity-checks” property">max-connectivity-checks</a></td>
+<td class="property_flags">Read / Write</td>
+</tr>
+<tr>
+<td class="property_type"><a class="link" href="NiceAgent.html#NiceNominationMode" title="enum NiceNominationMode"><span class="type">NiceNominationMode</span></a></td>
+<td class="property_name"><a class="link" href="NiceAgent.html#NiceAgent--nomination-mode" title="The “nomination-mode” property">nomination-mode</a></td>
+<td class="property_flags">Read / Write / Construct Only</td>
+</tr>
+<tr>
+<td class="property_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *</td>
+<td class="property_name"><a class="link" href="NiceAgent.html#NiceAgent--proxy-ip" title="The “proxy-ip” property">proxy-ip</a></td>
+<td class="property_flags">Read / Write</td>
+</tr>
+<tr>
+<td class="property_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *</td>
+<td class="property_name"><a class="link" href="NiceAgent.html#NiceAgent--proxy-password" title="The “proxy-password” property">proxy-password</a></td>
+<td class="property_flags">Read / Write</td>
+</tr>
+<tr>
+<td class="property_type"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a></td>
+<td class="property_name"><a class="link" href="NiceAgent.html#NiceAgent--proxy-port" title="The “proxy-port” property">proxy-port</a></td>
+<td class="property_flags">Read / Write</td>
+</tr>
+<tr>
+<td class="property_type"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a></td>
+<td class="property_name"><a class="link" href="NiceAgent.html#NiceAgent--proxy-type" title="The “proxy-type” property">proxy-type</a></td>
+<td class="property_flags">Read / Write</td>
+</tr>
+<tr>
+<td class="property_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *</td>
+<td class="property_name"><a class="link" href="NiceAgent.html#NiceAgent--proxy-username" title="The “proxy-username” property">proxy-username</a></td>
+<td class="property_flags">Read / Write</td>
+</tr>
+<tr>
+<td class="property_type"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="type">gboolean</span></a></td>
+<td class="property_name"><a class="link" href="NiceAgent.html#NiceAgent--reliable" title="The “reliable” property">reliable</a></td>
+<td class="property_flags">Read / Write / Construct Only</td>
+</tr>
+<tr>
+<td class="property_type"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a></td>
+<td class="property_name"><a class="link" href="NiceAgent.html#NiceAgent--stun-initial-timeout" title="The “stun-initial-timeout” property">stun-initial-timeout</a></td>
+<td class="property_flags">Read / Write / Construct</td>
+</tr>
+<tr>
+<td class="property_type"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a></td>
+<td class="property_name"><a class="link" href="NiceAgent.html#NiceAgent--stun-max-retransmissions" title="The “stun-max-retransmissions” property">stun-max-retransmissions</a></td>
+<td class="property_flags">Read / Write / Construct</td>
+</tr>
+<tr>
+<td class="property_type"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a></td>
+<td class="property_name"><a class="link" href="NiceAgent.html#NiceAgent--stun-pacing-timer" title="The “stun-pacing-timer” property">stun-pacing-timer</a></td>
+<td class="property_flags">Read / Write / Construct</td>
+</tr>
+<tr>
+<td class="property_type"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a></td>
+<td class="property_name"><a class="link" href="NiceAgent.html#NiceAgent--stun-reliable-timeout" title="The “stun-reliable-timeout” property">stun-reliable-timeout</a></td>
+<td class="property_flags">Read / Write / Construct</td>
+</tr>
+<tr>
+<td class="property_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *</td>
+<td class="property_name"><a class="link" href="NiceAgent.html#NiceAgent--stun-server" title="The “stun-server” property">stun-server</a></td>
+<td class="property_flags">Read / Write</td>
+</tr>
+<tr>
+<td class="property_type"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a></td>
+<td class="property_name"><a class="link" href="NiceAgent.html#NiceAgent--stun-server-port" title="The “stun-server-port” property">stun-server-port</a></td>
+<td class="property_flags">Read / Write</td>
+</tr>
+<tr>
+<td class="property_type"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="type">gboolean</span></a></td>
+<td class="property_name"><a class="link" href="NiceAgent.html#NiceAgent--support-renomination" title="The “support-renomination” property">support-renomination</a></td>
+<td class="property_flags">Read / Write</td>
+</tr>
+<tr>
+<td class="property_type"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="type">gboolean</span></a></td>
+<td class="property_name"><a class="link" href="NiceAgent.html#NiceAgent--upnp" title="The “upnp” property">upnp</a></td>
+<td class="property_flags">Read / Write / Construct</td>
+</tr>
+<tr>
+<td class="property_type"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a></td>
+<td class="property_name"><a class="link" href="NiceAgent.html#NiceAgent--upnp-timeout" title="The “upnp-timeout” property">upnp-timeout</a></td>
+<td class="property_flags">Read / Write / Construct</td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect1">
+<a name="NiceAgent.signals"></a><h2>Signals</h2>
+<div class="informaltable"><table class="informaltable" border="0">
+<colgroup>
+<col width="150px" class="signals_return">
+<col width="300px" class="signals_name">
+<col width="200px" class="signals_flags">
+</colgroup>
+<tbody>
+<tr>
+<td class="signal_type"><span class="returnvalue">void</span></td>
+<td class="signal_name"><a class="link" href="NiceAgent.html#NiceAgent-candidate-gathering-done" title="The “candidate-gathering-done” signal">candidate-gathering-done</a></td>
+<td class="signal_flags"><a href="/usr/share/gtk-doc/html/gobject/gobject-Signals.html#G-SIGNAL-RUN-LAST:CAPS">Run Last</a></td>
+</tr>
+<tr>
+<td class="signal_type"><span class="returnvalue">void</span></td>
+<td class="signal_name"><a class="link" href="NiceAgent.html#NiceAgent-component-state-changed" title="The “component-state-changed” signal">component-state-changed</a></td>
+<td class="signal_flags"><a href="/usr/share/gtk-doc/html/gobject/gobject-Signals.html#G-SIGNAL-RUN-LAST:CAPS">Run Last</a></td>
+</tr>
+<tr>
+<td class="signal_type"><span class="returnvalue">void</span></td>
+<td class="signal_name"><a class="link" href="NiceAgent.html#NiceAgent-initial-binding-request-received" title="The “initial-binding-request-received” signal">initial-binding-request-received</a></td>
+<td class="signal_flags"><a href="/usr/share/gtk-doc/html/gobject/gobject-Signals.html#G-SIGNAL-RUN-LAST:CAPS">Run Last</a></td>
+</tr>
+<tr>
+<td class="signal_type"><span class="returnvalue">void</span></td>
+<td class="signal_name"><a class="link" href="NiceAgent.html#NiceAgent-new-candidate" title="The “new-candidate” signal">new-candidate</a></td>
+<td class="signal_flags"><a href="/usr/share/gtk-doc/html/gobject/gobject-Signals.html#G-SIGNAL-RUN-LAST:CAPS">Run Last</a></td>
+</tr>
+<tr>
+<td class="signal_type"><span class="returnvalue">void</span></td>
+<td class="signal_name"><a class="link" href="NiceAgent.html#NiceAgent-new-candidate-full" title="The “new-candidate-full” signal">new-candidate-full</a></td>
+<td class="signal_flags"><a href="/usr/share/gtk-doc/html/gobject/gobject-Signals.html#G-SIGNAL-RUN-LAST:CAPS">Run Last</a></td>
+</tr>
+<tr>
+<td class="signal_type"><span class="returnvalue">void</span></td>
+<td class="signal_name"><a class="link" href="NiceAgent.html#NiceAgent-new-remote-candidate" title="The “new-remote-candidate” signal">new-remote-candidate</a></td>
+<td class="signal_flags"><a href="/usr/share/gtk-doc/html/gobject/gobject-Signals.html#G-SIGNAL-RUN-LAST:CAPS">Run Last</a></td>
+</tr>
+<tr>
+<td class="signal_type"><span class="returnvalue">void</span></td>
+<td class="signal_name"><a class="link" href="NiceAgent.html#NiceAgent-new-remote-candidate-full" title="The “new-remote-candidate-full” signal">new-remote-candidate-full</a></td>
+<td class="signal_flags"><a href="/usr/share/gtk-doc/html/gobject/gobject-Signals.html#G-SIGNAL-RUN-LAST:CAPS">Run Last</a></td>
+</tr>
+<tr>
+<td class="signal_type"><span class="returnvalue">void</span></td>
+<td class="signal_name"><a class="link" href="NiceAgent.html#NiceAgent-new-selected-pair" title="The “new-selected-pair” signal">new-selected-pair</a></td>
+<td class="signal_flags"><a href="/usr/share/gtk-doc/html/gobject/gobject-Signals.html#G-SIGNAL-RUN-LAST:CAPS">Run Last</a></td>
+</tr>
+<tr>
+<td class="signal_type"><span class="returnvalue">void</span></td>
+<td class="signal_name"><a class="link" href="NiceAgent.html#NiceAgent-new-selected-pair-full" title="The “new-selected-pair-full” signal">new-selected-pair-full</a></td>
+<td class="signal_flags"><a href="/usr/share/gtk-doc/html/gobject/gobject-Signals.html#G-SIGNAL-RUN-LAST:CAPS">Run Last</a></td>
+</tr>
+<tr>
+<td class="signal_type"><span class="returnvalue">void</span></td>
+<td class="signal_name"><a class="link" href="NiceAgent.html#NiceAgent-reliable-transport-writable" title="The “reliable-transport-writable” signal">reliable-transport-writable</a></td>
+<td class="signal_flags"><a href="/usr/share/gtk-doc/html/gobject/gobject-Signals.html#G-SIGNAL-RUN-LAST:CAPS">Run Last</a></td>
+</tr>
+<tr>
+<td class="signal_type"><span class="returnvalue">void</span></td>
+<td class="signal_name"><a class="link" href="NiceAgent.html#NiceAgent-streams-removed" title="The “streams-removed” signal">streams-removed</a></td>
+<td class="signal_flags"><a href="/usr/share/gtk-doc/html/gobject/gobject-Signals.html#G-SIGNAL-RUN-LAST:CAPS">Run Last</a></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect1">
+<a name="NiceAgent.other"></a><h2>Types and Values</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="name">
+<col class="description">
+</colgroup>
+<tbody>
+<tr>
+<td class="datatype_keyword"> </td>
+<td class="function_name"><a class="link" href="NiceAgent.html#NiceAgent-struct" title="NiceAgent">NiceAgent</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="NiceAgent.html#NiceComponentState" title="enum NiceComponentState">NiceComponentState</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="NiceAgent.html#NiceComponentType" title="enum NiceComponentType">NiceComponentType</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="NiceAgent.html#NiceProxyType" title="enum NiceProxyType">NiceProxyType</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="NiceAgent.html#NiceNominationMode" title="enum NiceNominationMode">NiceNominationMode</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="NiceAgent.html#NiceCompatibility" title="enum NiceCompatibility">NiceCompatibility</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword"> </td>
+<td class="function_name"><a class="link" href="NiceAgent.html#NiceInputMessage" title="NiceInputMessage">NiceInputMessage</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword"> </td>
+<td class="function_name"><a class="link" href="NiceAgent.html#NiceOutputMessage" title="NiceOutputMessage">NiceOutputMessage</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="NiceAgent.html#NICE-AGENT-MAX-REMOTE-CANDIDATES:CAPS" title="NICE_AGENT_MAX_REMOTE_CANDIDATES">NICE_AGENT_MAX_REMOTE_CANDIDATES</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="NiceAgent.html#NiceAgentOption" title="enum NiceAgentOption">NiceAgentOption</a></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect1">
+<a name="NiceAgent.object-hierarchy"></a><h2>Object Hierarchy</h2>
+<pre class="screen"> <a href="/usr/share/gtk-doc/html/gobject/gobject-Enumeration-and-Flag-Types.html">GEnum</a>
+ <span class="lineart">├──</span> NiceCompatibility
+ <span class="lineart">├──</span> NiceComponentState
+ <span class="lineart">├──</span> NiceComponentType
+ <span class="lineart">├──</span> NiceNominationMode
+ <span class="lineart">╰──</span> NiceProxyType
+ <a href="/usr/share/gtk-doc/html/gobject/gobject-Enumeration-and-Flag-Types.html">GFlags</a>
+ <span class="lineart">╰──</span> NiceAgentOption
+ <a href="/usr/share/gtk-doc/html/gobject/gobject-The-Base-Object-Type.html#GObject-struct">GObject</a>
+ <span class="lineart">╰──</span> NiceAgent
+</pre>
+</div>
+<div class="refsect1">
+<a name="NiceAgent.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include <agent.h>
+</pre>
+</div>
+<div class="refsect1">
+<a name="NiceAgent.description"></a><h2>Description</h2>
+<p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> is your main object when using libnice.
+It is the agent that will take care of everything relating to ICE.
+It will take care of discovering your local candidates and do
+ connectivity checks to create a stream of data between you and your peer.</p>
+<p>A <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> must always be used with a <a href="/usr/share/gtk-doc/html/glib/glib-The-Main-Event-Loop.html#GMainLoop"><span class="type">GMainLoop</span></a> running the <a href="/usr/share/gtk-doc/html/glib/glib-The-Main-Event-Loop.html#GMainContext"><span class="type">GMainContext</span></a>
+passed into <a class="link" href="NiceAgent.html#nice-agent-new" title="nice_agent_new ()"><code class="function">nice_agent_new()</code></a> (or <a class="link" href="NiceAgent.html#nice-agent-new-reliable" title="nice_agent_new_reliable ()"><code class="function">nice_agent_new_reliable()</code></a>). Without the
+<a href="/usr/share/gtk-doc/html/glib/glib-The-Main-Event-Loop.html#GMainContext"><span class="type">GMainContext</span></a> being iterated, the agent’s timers will not fire, etc.</p>
+<p>Streams and their components are referenced by integer IDs (with respect to a
+given <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a>). These IDs are guaranteed to be positive (i.e. non-zero)
+for valid streams/components.</p>
+<p>To complete the ICE connectivity checks, the user must either register
+an I/O callback (with <a class="link" href="NiceAgent.html#nice-agent-attach-recv" title="nice_agent_attach_recv ()"><code class="function">nice_agent_attach_recv()</code></a>) or call <a class="link" href="NiceAgent.html#nice-agent-recv-messages" title="nice_agent_recv_messages ()"><code class="function">nice_agent_recv_messages()</code></a>
+in a loop on a dedicated thread.
+Technically, <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> does not poll the streams on its own, since
+user data could arrive at any time; to receive STUN packets
+required for establishing ICE connectivity, it is backpiggying
+on the facility chosen by the user. <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> will handle all STUN
+packets internally; they're never actually passed to the I/O callback
+or returned from <a class="link" href="NiceAgent.html#nice-agent-recv-messages" title="nice_agent_recv_messages ()"><code class="function">nice_agent_recv_messages()</code></a> and related functions.</p>
+<p>Each stream can receive data in one of two ways: using
+<a class="link" href="NiceAgent.html#nice-agent-attach-recv" title="nice_agent_attach_recv ()"><code class="function">nice_agent_attach_recv()</code></a> or <a class="link" href="NiceAgent.html#nice-agent-recv-messages" title="nice_agent_recv_messages ()"><code class="function">nice_agent_recv_messages()</code></a> (and the derived
+<span class="type">NiceInputStream</span> and <span class="type">NiceIOStream</span> classes accessible using
+<a class="link" href="NiceAgent.html#nice-agent-get-io-stream" title="nice_agent_get_io_stream ()"><code class="function">nice_agent_get_io_stream()</code></a>). <a class="link" href="NiceAgent.html#nice-agent-attach-recv" title="nice_agent_attach_recv ()"><code class="function">nice_agent_attach_recv()</code></a> is non-blocking: it
+takes a user-provided callback function and attaches the stream’s socket to
+the provided <a href="/usr/share/gtk-doc/html/glib/glib-The-Main-Event-Loop.html#GMainContext"><span class="type">GMainContext</span></a>, invoking the callback in that context for every
+packet received. <a class="link" href="NiceAgent.html#nice-agent-recv-messages" title="nice_agent_recv_messages ()"><code class="function">nice_agent_recv_messages()</code></a> instead blocks on receiving a
+packet, and writes it directly into a user-provided buffer. This reduces the
+number of callback invokations and (potentially) buffer copies required to
+receive packets. <a class="link" href="NiceAgent.html#nice-agent-recv-messages" title="nice_agent_recv_messages ()"><code class="function">nice_agent_recv_messages()</code></a> (or <span class="type">NiceInputStream</span>) is designed
+to be used in a blocking loop in a separate thread.</p>
+<div class="example">
+<a name="id-1.2.2.1.10.7"></a><p class="title"><b>Example 1. Simple example on how to use libnice</b></p>
+<div class="example-contents">
+ <table class="listing_frame" border="0" cellpadding="0" cellspacing="0">
+ <tbody>
+ <tr>
+ <td class="listing_lines" align="right"><pre>1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49</pre></td>
+ <td class="listing_code"><pre class="programlisting"><span class="usertype">guint</span><span class="normal"> stream_id</span><span class="symbol">;</span>
+<span class="usertype">gchar</span><span class="normal"> buffer</span><span class="symbol">[]</span><span class="normal"> </span><span class="symbol">=</span><span class="normal"> </span><span class="string">"hello world!"</span><span class="symbol">;</span>
+<span class="usertype">gchar</span><span class="normal"> </span><span class="symbol">*</span><span class="normal">ufrag </span><span class="symbol">=</span><span class="normal"> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS">NULL</a></span><span class="symbol">,</span><span class="normal"> </span><span class="symbol">*</span><span class="normal">pwd </span><span class="symbol">=</span><span class="normal"> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS">NULL</a></span><span class="symbol">;</span>
+<span class="usertype">gchar</span><span class="normal"> </span><span class="symbol">*</span><span class="normal">remote_ufrag</span><span class="symbol">,</span><span class="normal"> </span><span class="symbol">*</span><span class="normal">remote_pwd</span><span class="symbol">;</span>
+<span class="usertype">GSList</span><span class="normal"> </span><span class="symbol">*</span><span class="normal">lcands </span><span class="symbol">=</span><span class="normal"> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS">NULL</a></span><span class="symbol">;</span>
+
+<span class="comment">// Create a nice agent, passing in the global default GMainContext.</span>
+<span class="usertype">NiceAgent</span><span class="normal"> </span><span class="symbol">*</span><span class="normal">agent </span><span class="symbol">=</span><span class="normal"> </span><span class="function"><a href="NiceAgent.html#nice-agent-new">nice_agent_new</a></span><span class="normal"> </span><span class="symbol">(</span><span class="normal"><a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS">NULL</a></span><span class="symbol">,</span><span class="normal"> <a href="NiceAgent.html#NICE-COMPATIBILITY-RFC5245:CAPS">NICE_COMPATIBILITY_RFC5245</a></span><span class="symbol">);</span>
+<span class="function">spawn_thread_to_run_main_loop</span><span class="normal"> </span><span class="symbol">(</span><span class="function"><a href="/usr/share/gtk-doc/html/glib/glib-The-Main-Event-Loop.html#g-main-loop-new">g_main_loop_new</a></span><span class="normal"> </span><span class="symbol">(</span><span class="normal"><a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS">NULL</a></span><span class="symbol">,</span><span class="normal"> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS">FALSE</a></span><span class="symbol">));</span>
+
+<span class="comment">// Connect the signals</span>
+<span class="function"><a href="/usr/share/gtk-doc/html/gobject/gobject-Signals.html#g-signal-connect">g_signal_connect</a></span><span class="normal"> </span><span class="symbol">(</span><span class="function"><a href="/usr/share/gtk-doc/html/gobject/gobject-The-Base-Object-Type.html#G-OBJECT:CAPS">G_OBJECT</a></span><span class="normal"> </span><span class="symbol">(</span><span class="normal">agent</span><span class="symbol">),</span><span class="normal"> </span><span class="string">"candidate-gathering-done"</span><span class="symbol">,</span>
+<span class="normal"> </span><span class="function"><a href="/usr/share/gtk-doc/html/gobject/gobject-Closures.html#G-CALLBACK:CAPS">G_CALLBACK</a></span><span class="normal"> </span><span class="symbol">(</span><span class="normal">cb_candidate_gathering_done</span><span class="symbol">),</span><span class="normal"> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS">NULL</a></span><span class="symbol">);</span>
+<span class="function"><a href="/usr/share/gtk-doc/html/gobject/gobject-Signals.html#g-signal-connect">g_signal_connect</a></span><span class="normal"> </span><span class="symbol">(</span><span class="function"><a href="/usr/share/gtk-doc/html/gobject/gobject-The-Base-Object-Type.html#G-OBJECT:CAPS">G_OBJECT</a></span><span class="normal"> </span><span class="symbol">(</span><span class="normal">agent</span><span class="symbol">),</span><span class="normal"> </span><span class="string">"component-state-changed"</span><span class="symbol">,</span>
+<span class="normal"> </span><span class="function"><a href="/usr/share/gtk-doc/html/gobject/gobject-Closures.html#G-CALLBACK:CAPS">G_CALLBACK</a></span><span class="normal"> </span><span class="symbol">(</span><span class="normal">cb_component_state_changed</span><span class="symbol">),</span><span class="normal"> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS">NULL</a></span><span class="symbol">);</span>
+<span class="function"><a href="/usr/share/gtk-doc/html/gobject/gobject-Signals.html#g-signal-connect">g_signal_connect</a></span><span class="normal"> </span><span class="symbol">(</span><span class="function"><a href="/usr/share/gtk-doc/html/gobject/gobject-The-Base-Object-Type.html#G-OBJECT:CAPS">G_OBJECT</a></span><span class="normal"> </span><span class="symbol">(</span><span class="normal">agent</span><span class="symbol">),</span><span class="normal"> </span><span class="string">"new-selected-pair"</span><span class="symbol">,</span>
+<span class="normal"> </span><span class="function"><a href="/usr/share/gtk-doc/html/gobject/gobject-Closures.html#G-CALLBACK:CAPS">G_CALLBACK</a></span><span class="normal"> </span><span class="symbol">(</span><span class="normal">cb_new_selected_pair</span><span class="symbol">),</span><span class="normal"> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS">NULL</a></span><span class="symbol">);</span>
+
+<span class="comment">// Create a new stream with one component and start gathering candidates</span>
+<span class="normal">stream_id </span><span class="symbol">=</span><span class="normal"> </span><span class="function"><a href="NiceAgent.html#nice-agent-add-stream">nice_agent_add_stream</a></span><span class="normal"> </span><span class="symbol">(</span><span class="normal">agent</span><span class="symbol">,</span><span class="normal"> </span><span class="number">1</span><span class="symbol">);</span>
+<span class="function"><a href="NiceAgent.html#nice-agent-gather-candidates">nice_agent_gather_candidates</a></span><span class="normal"> </span><span class="symbol">(</span><span class="normal">agent</span><span class="symbol">,</span><span class="normal"> stream_id</span><span class="symbol">);</span>
+
+<span class="comment">// Attach I/O callback the component to ensure that:</span>
+<span class="comment">// 1) agent gets its STUN packets (not delivered to cb_nice_recv)</span>
+<span class="comment">// 2) you get your own data</span>
+<span class="function"><a href="NiceAgent.html#nice-agent-attach-recv">nice_agent_attach_recv</a></span><span class="normal"> </span><span class="symbol">(</span><span class="normal">agent</span><span class="symbol">,</span><span class="normal"> stream_id</span><span class="symbol">,</span><span class="normal"> </span><span class="number">1</span><span class="symbol">,</span><span class="normal"> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS">NULL</a></span><span class="symbol">,</span>
+<span class="normal"> cb_nice_recv</span><span class="symbol">,</span><span class="normal"> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS">NULL</a></span><span class="symbol">);</span>
+
+<span class="comment">// ... Wait until the signal candidate-gathering-done is fired ...</span>
+<span class="normal">lcands </span><span class="symbol">=</span><span class="normal"> </span><span class="function"><a href="NiceAgent.html#nice-agent-get-local-candidates">nice_agent_get_local_candidates</a></span><span class="symbol">(</span><span class="normal">agent</span><span class="symbol">,</span><span class="normal"> stream_id</span><span class="symbol">,</span><span class="normal"> </span><span class="number">1</span><span class="symbol">);</span>
+
+<span class="function"><a href="NiceAgent.html#nice-agent-get-local-credentials">nice_agent_get_local_credentials</a></span><span class="symbol">(</span><span class="normal">agent</span><span class="symbol">,</span><span class="normal"> stream_id</span><span class="symbol">,</span><span class="normal"> </span><span class="symbol">&</span><span class="normal">ufrag</span><span class="symbol">,</span><span class="normal"> </span><span class="symbol">&</span><span class="normal">pwd</span><span class="symbol">);</span>
+
+<span class="comment">// ... Send local candidates and credentials to the peer</span>
+
+<span class="comment">// Set the peer's remote credentials and remote candidates</span>
+<span class="function"><a href="NiceAgent.html#nice-agent-set-remote-credentials">nice_agent_set_remote_credentials</a></span><span class="normal"> </span><span class="symbol">(</span><span class="normal">agent</span><span class="symbol">,</span><span class="normal"> stream_id</span><span class="symbol">,</span><span class="normal"> remote_ufrag</span><span class="symbol">,</span><span class="normal"> remote_pwd</span><span class="symbol">);</span>
+<span class="function"><a href="NiceAgent.html#nice-agent-set-remote-candidates">nice_agent_set_remote_candidates</a></span><span class="normal"> </span><span class="symbol">(</span><span class="normal">agent</span><span class="symbol">,</span><span class="normal"> stream_id</span><span class="symbol">,</span><span class="normal"> </span><span class="number">1</span><span class="symbol">,</span><span class="normal"> rcands</span><span class="symbol">);</span>
+
+<span class="comment">// ... Wait until the signal new-selected-pair is fired ...</span>
+<span class="comment">// Send our message!</span>
+<span class="function"><a href="NiceAgent.html#nice-agent-send">nice_agent_send</a></span><span class="normal"> </span><span class="symbol">(</span><span class="normal">agent</span><span class="symbol">,</span><span class="normal"> stream_id</span><span class="symbol">,</span><span class="normal"> </span><span class="number">1</span><span class="symbol">,</span><span class="normal"> </span><span class="keyword">sizeof</span><span class="symbol">(</span><span class="normal">buffer</span><span class="symbol">),</span><span class="normal"> buffer</span><span class="symbol">);</span>
+
+<span class="comment">// Anything received will be received through the cb_nice_recv callback.</span>
+<span class="comment">// You must be running a GMainLoop on the global default GMainContext in</span>
+<span class="comment">// another thread for this to work.</span>
+
+<span class="comment">// Destroy the object</span>
+<span class="function"><a href="/usr/share/gtk-doc/html/gobject/gobject-The-Base-Object-Type.html#g-object-unref">g_object_unref</a></span><span class="symbol">(</span><span class="normal">agent</span><span class="symbol">);</span></pre></td>
+ </tr>
+ </tbody>
+ </table>
+</div>
+
+</div>
+<br class="example-break"><p>Refer to the examples in the examples/ subdirectory of the libnice source for
+more complete examples.</p>
+</div>
+<div class="refsect1">
+<a name="NiceAgent.functions_details"></a><h2>Functions</h2>
+<div class="refsect2">
+<a name="NiceAgentRecvFunc"></a><h3>NiceAgentRecvFunc ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+<span class="c_punctuation">(</span>*NiceAgentRecvFunc<span class="c_punctuation">)</span> (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> component_id</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> len</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *buf</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gpointer"><span class="type">gpointer</span></a> user_data</code></em>);</pre>
+<p>Callback function when data is received on a component</p>
+<div class="refsect3">
+<a name="NiceAgentRecvFunc.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> Object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The id of the stream</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>component_id</p></td>
+<td class="parameter_description"><p>The id of the component of the stream
+which received the data</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>len</p></td>
+<td class="parameter_description"><p>The length of the data</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buf</p></td>
+<td class="parameter_description"><p>The buffer containing the data received</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>user_data</p></td>
+<td class="parameter_description"><p>The user data set in <a class="link" href="NiceAgent.html#nice-agent-attach-recv" title="nice_agent_attach_recv ()"><code class="function">nice_agent_attach_recv()</code></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-new"></a><h3>nice_agent_new ()</h3>
+<pre class="programlisting"><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="returnvalue">NiceAgent</span></a> *
+nice_agent_new (<em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-The-Main-Event-Loop.html#GMainContext"><span class="type">GMainContext</span></a> *ctx</code></em>,
+ <em class="parameter"><code><a class="link" href="NiceAgent.html#NiceCompatibility" title="enum NiceCompatibility"><span class="type">NiceCompatibility</span></a> compat</code></em>);</pre>
+<p>Create a new <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a>.
+The returned object must be freed with <a href="/usr/share/gtk-doc/html/gobject/gobject-The-Base-Object-Type.html#g-object-unref"><code class="function">g_object_unref()</code></a></p>
+<div class="refsect3">
+<a name="nice-agent-new.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>ctx</p></td>
+<td class="parameter_description"><p>The Glib Mainloop Context to use for timers</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>compat</p></td>
+<td class="parameter_description"><p>The compatibility mode of the agent</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-new.returns"></a><h4>Returns</h4>
+<p> The new agent GObject</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-new-reliable"></a><h3>nice_agent_new_reliable ()</h3>
+<pre class="programlisting"><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="returnvalue">NiceAgent</span></a> *
+nice_agent_new_reliable (<em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-The-Main-Event-Loop.html#GMainContext"><span class="type">GMainContext</span></a> *ctx</code></em>,
+ <em class="parameter"><code><a class="link" href="NiceAgent.html#NiceCompatibility" title="enum NiceCompatibility"><span class="type">NiceCompatibility</span></a> compat</code></em>);</pre>
+<p>Create a new <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> in reliable mode. If the connectivity is established
+through ICE-UDP, then a <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> will be transparently used to
+ensure reliability of the messages.
+The returned object must be freed with <a href="/usr/share/gtk-doc/html/gobject/gobject-The-Base-Object-Type.html#g-object-unref"><code class="function">g_object_unref()</code></a></p>
+<p> See also: <a class="link" href="NiceAgent.html#NiceAgent-reliable-transport-writable" title="The “reliable-transport-writable” signal"><span class="type">“reliable-transport-writable”</span></a> </p>
+<div class="refsect3">
+<a name="nice-agent-new-reliable.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>ctx</p></td>
+<td class="parameter_description"><p>The Glib Mainloop Context to use for timers</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>compat</p></td>
+<td class="parameter_description"><p>The compatibility mode of the agent</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-new-reliable.returns"></a><h4>Returns</h4>
+<p> The new agent GObject</p>
+</div>
+<p class="since">Since: <a class="link" href="ix08.html#api-index-0.0.11">0.0.11</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-new-full"></a><h3>nice_agent_new_full ()</h3>
+<pre class="programlisting"><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="returnvalue">NiceAgent</span></a> *
+nice_agent_new_full (<em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-The-Main-Event-Loop.html#GMainContext"><span class="type">GMainContext</span></a> *ctx</code></em>,
+ <em class="parameter"><code><a class="link" href="NiceAgent.html#NiceCompatibility" title="enum NiceCompatibility"><span class="type">NiceCompatibility</span></a> compat</code></em>,
+ <em class="parameter"><code><a class="link" href="NiceAgent.html#NiceAgentOption" title="enum NiceAgentOption"><span class="type">NiceAgentOption</span></a> flags</code></em>);</pre>
+<p>Create a new <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> with parameters that must be be defined at
+construction time.
+The returned object must be freed with <a href="/usr/share/gtk-doc/html/gobject/gobject-The-Base-Object-Type.html#g-object-unref"><code class="function">g_object_unref()</code></a></p>
+<p> See also: <a class="link" href="NiceAgent.html#NiceNominationMode" title="enum NiceNominationMode"><span class="type">NiceNominationMode</span></a> and <a class="link" href="NiceAgent.html#NiceAgentOption" title="enum NiceAgentOption"><span class="type">NiceAgentOption</span></a></p>
+<div class="refsect3">
+<a name="nice-agent-new-full.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>ctx</p></td>
+<td class="parameter_description"><p>The Glib Mainloop Context to use for timers</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>compat</p></td>
+<td class="parameter_description"><p>The compatibility mode of the agent</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>flags</p></td>
+<td class="parameter_description"><p>Flags to set the properties</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-new-full.returns"></a><h4>Returns</h4>
+<p> The new agent GObject</p>
+</div>
+<p class="since">Since: <a class="link" href="ix14.html#api-index-0.1.15">0.1.15</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-add-local-address"></a><h3>nice_agent_add_local_address ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+nice_agent_add_local_address (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> *addr</code></em>);</pre>
+<p>Add a local address from which to derive local host candidates for
+candidate gathering.</p>
+<p>
+Since 0.0.5, if this method is not called, libnice will automatically
+discover the local addresses available
+</p>
+<p>See also: <a class="link" href="NiceAgent.html#nice-agent-gather-candidates" title="nice_agent_gather_candidates ()"><code class="function">nice_agent_gather_candidates()</code></a></p>
+<div class="refsect3">
+<a name="nice-agent-add-local-address.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> Object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>addr</p></td>
+<td class="parameter_description"><p>The address to listen to
+If the port is 0, then a random port will be chosen by the system</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-add-local-address.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> on success, <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> on fatal (memory allocation) errors</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-set-port-range"></a><h3>nice_agent_set_port_range ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+nice_agent_set_port_range (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> component_id</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> min_port</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> max_port</code></em>);</pre>
+<p>Sets a preferred port range for allocating host candidates.</p>
+<p>
+If a local host candidate cannot be created on that port
+range, then the <a class="link" href="NiceAgent.html#nice-agent-gather-candidates" title="nice_agent_gather_candidates ()"><code class="function">nice_agent_gather_candidates()</code></a> call will fail.
+</p>
+<p>
+This MUST be called before <a class="link" href="NiceAgent.html#nice-agent-gather-candidates" title="nice_agent_gather_candidates ()"><code class="function">nice_agent_gather_candidates()</code></a>
+</p>
+<div class="refsect3">
+<a name="nice-agent-set-port-range.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> Object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The ID of the stream</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>component_id</p></td>
+<td class="parameter_description"><p>The ID of the component</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>min_port</p></td>
+<td class="parameter_description"><p>The minimum port to use</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>max_port</p></td>
+<td class="parameter_description"><p>The maximum port to use</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-add-stream"></a><h3>nice_agent_add_stream ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="returnvalue">guint</span></a>
+nice_agent_add_stream (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> n_components</code></em>);</pre>
+<p>Adds a data stream to <em class="parameter"><code>agent</code></em>
+ containing <em class="parameter"><code>n_components</code></em>
+ components. The
+returned stream ID is guaranteed to be positive on success.</p>
+<div class="refsect3">
+<a name="nice-agent-add-stream.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> Object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>n_components</p></td>
+<td class="parameter_description"><p>The number of components to add to the stream</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-add-stream.returns"></a><h4>Returns</h4>
+<p> The ID of the new stream, 0 on failure</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-remove-stream"></a><h3>nice_agent_remove_stream ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+nice_agent_remove_stream (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id</code></em>);</pre>
+<p>Remove and free a previously created data stream from <em class="parameter"><code>agent</code></em>
+. If any I/O
+streams have been created using <a class="link" href="NiceAgent.html#nice-agent-get-io-stream" title="nice_agent_get_io_stream ()"><code class="function">nice_agent_get_io_stream()</code></a>, they should be
+closed completely using <a href="/usr/share/gtk-doc/html/gio/GIOStream.html#g-io-stream-close"><code class="function">g_io_stream_close()</code></a> before this is called, or they
+will get broken pipe errors.</p>
+<div class="refsect3">
+<a name="nice-agent-remove-stream.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> Object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The ID of the stream to remove</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-set-relay-info"></a><h3>nice_agent_set_relay_info ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+nice_agent_set_relay_info (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> component_id</code></em>,
+ <em class="parameter"><code>const <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *server_ip</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> server_port</code></em>,
+ <em class="parameter"><code>const <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *username</code></em>,
+ <em class="parameter"><code>const <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *password</code></em>,
+ <em class="parameter"><code><a class="link" href="NiceCandidate.html#NiceRelayType" title="enum NiceRelayType"><span class="type">NiceRelayType</span></a> type</code></em>);</pre>
+<p>Sets the settings for using a relay server during the candidate discovery.
+This may be called multiple times to add multiple relay servers to the
+discovery process; one TCP and one UDP, for example.</p>
+<div class="refsect3">
+<a name="nice-agent-set-relay-info.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> Object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The ID of the stream</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>component_id</p></td>
+<td class="parameter_description"><p>The ID of the component</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>server_ip</p></td>
+<td class="parameter_description"><p>The IP address of the TURN server</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>server_port</p></td>
+<td class="parameter_description"><p>The port of the TURN server</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>username</p></td>
+<td class="parameter_description"><p>The TURN username to use for the allocate</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>password</p></td>
+<td class="parameter_description"><p>The TURN password to use for the allocate</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>type</p></td>
+<td class="parameter_description"><p>The type of relay to use</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-set-relay-info.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> if the TURN settings were accepted.
+<a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> if the address was invalid.</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-forget-relays"></a><h3>nice_agent_forget_relays ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+nice_agent_forget_relays (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> component_id</code></em>);</pre>
+<p>Forget all the relay servers previously added using
+<a class="link" href="NiceAgent.html#nice-agent-set-relay-info" title="nice_agent_set_relay_info ()"><code class="function">nice_agent_set_relay_info()</code></a>. Currently connected streams will keep
+using the relay as long as they have not been restarted and haven't
+succesfully negotiated a different path.</p>
+<div class="refsect3">
+<a name="nice-agent-forget-relays.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> Object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The ID of the stream</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>component_id</p></td>
+<td class="parameter_description"><p>The ID of the component</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-forget-relays.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> if the component could not be found, <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> otherwise</p>
+</div>
+<p class="since">Since: <a class="link" href="ix11.html#api-index-0.1.6">0.1.6</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-gather-candidates"></a><h3>nice_agent_gather_candidates ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+nice_agent_gather_candidates (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id</code></em>);</pre>
+<p>Allocate and start listening on local candidate ports and start the remote
+candidate gathering process.
+Once done, <a class="link" href="NiceAgent.html#NiceAgent-candidate-gathering-done" title="The “candidate-gathering-done” signal"><span class="type">“candidate-gathering-done”</span></a> is called for the stream.
+As soon as this function is called, <a class="link" href="NiceAgent.html#NiceAgent-new-candidate" title="The “new-candidate” signal"><span class="type">“new-candidate”</span></a> signals may be
+emitted, even before this function returns.</p>
+<p>nice_agent_get_local_candidates() will only return non-empty results after
+calling this function.</p>
+<p>See also: <a class="link" href="NiceAgent.html#nice-agent-add-local-address" title="nice_agent_add_local_address ()"><code class="function">nice_agent_add_local_address()</code></a></p>
+<p>See also: <a class="link" href="NiceAgent.html#nice-agent-set-port-range" title="nice_agent_set_port_range ()"><code class="function">nice_agent_set_port_range()</code></a></p>
+<div class="refsect3">
+<a name="nice-agent-gather-candidates.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The ID of the stream to start</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-gather-candidates.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> if the stream ID is invalid or if a host candidate couldn't
+be allocated on the requested interfaces/ports; <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> otherwise</p>
+<div class="note">
+<p>
+Local addresses can be previously set with <a class="link" href="NiceAgent.html#nice-agent-add-local-address" title="nice_agent_add_local_address ()"><code class="function">nice_agent_add_local_address()</code></a>
+</p>
+<p>
+Since 0.0.5, If no local address was previously added, then the nice agent
+will automatically detect the local address using
+<a class="link" href="libnice-Network-interfaces-discovery.html#nice-interfaces-get-local-ips" title="nice_interfaces_get_local_ips ()"><code class="function">nice_interfaces_get_local_ips()</code></a>
+</p>
+</div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-set-remote-credentials"></a><h3>nice_agent_set_remote_credentials ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+nice_agent_set_remote_credentials (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id</code></em>,
+ <em class="parameter"><code>const <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *ufrag</code></em>,
+ <em class="parameter"><code>const <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *pwd</code></em>);</pre>
+<p>Sets the remote credentials for stream <em class="parameter"><code>stream_id</code></em>
+.</p>
+<div class="note">
+<p>
+ Stream credentials do not override per-candidate credentials if set
+ </p>
+<p>
+ Due to the native of peer-reflexive candidates, any agent using a per-stream
+ credentials (RFC5245, WLM2009, OC2007R2 and DRAFT19) instead of
+ per-candidate credentials (GOOGLE, MSN, OC2007), must
+ use the <a class="link" href="NiceAgent.html#nice-agent-set-remote-credentials" title="nice_agent_set_remote_credentials ()"><code class="function">nice_agent_set_remote_credentials()</code></a> API instead of setting the
+ username and password on the candidates.
+ </p>
+</div>
+<div class="refsect3">
+<a name="nice-agent-set-remote-credentials.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> Object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The ID of the stream</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>ufrag</p></td>
+<td class="parameter_description"><p>nul-terminated string containing an ICE username fragment
+(length must be between 22 and 256 chars)</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>pwd</p></td>
+<td class="parameter_description"><p>nul-terminated string containing an ICE password
+(length must be between 4 and 256 chars)</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-set-remote-credentials.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> on success, <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> on error.</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-get-local-credentials"></a><h3>nice_agent_get_local_credentials ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+nice_agent_get_local_credentials (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> **ufrag</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> **pwd</code></em>);</pre>
+<p>Gets the local credentials for stream <em class="parameter"><code>stream_id</code></em>
+. This may be called any time
+after creating a stream using <a class="link" href="NiceAgent.html#nice-agent-add-stream" title="nice_agent_add_stream ()"><code class="function">nice_agent_add_stream()</code></a>.</p>
+<p>An error will be returned if this is called for a non-existent stream, or if
+either of <em class="parameter"><code>ufrag</code></em>
+ or <em class="parameter"><code>pwd</code></em>
+ are <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS"><code class="literal">NULL</code></a>.</p>
+<div class="refsect3">
+<a name="nice-agent-get-local-credentials.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> Object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The ID of the stream</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>ufrag</p></td>
+<td class="parameter_description"><p>return location for a nul-terminated string
+containing an ICE username fragment; must be freed with <a href="/usr/share/gtk-doc/html/glib/glib-Memory-Allocation.html#g-free"><code class="function">g_free()</code></a>. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Out parameter, where caller must allocate storage."><span class="acronym">out callee-allocates</span></acronym>]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>pwd</p></td>
+<td class="parameter_description"><p>return location for a nul-terminated string
+containing an ICE password; must be freed with <a href="/usr/share/gtk-doc/html/glib/glib-Memory-Allocation.html#g-free"><code class="function">g_free()</code></a>. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Out parameter, where caller must allocate storage."><span class="acronym">out callee-allocates</span></acronym>]</span></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-get-local-credentials.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> on success, <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> on error.</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-set-local-credentials"></a><h3>nice_agent_set_local_credentials ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+nice_agent_set_local_credentials (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id</code></em>,
+ <em class="parameter"><code>const <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *ufrag</code></em>,
+ <em class="parameter"><code>const <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *pwd</code></em>);</pre>
+<p>Sets the local credentials for stream <em class="parameter"><code>stream_id</code></em>
+.</p>
+<div class="note"><p>
+ This is only effective before ICE negotiation has started.
+ </p></div>
+<p>Since 0.1.11</p>
+<div class="refsect3">
+<a name="nice-agent-set-local-credentials.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> Object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The ID of the stream</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>ufrag</p></td>
+<td class="parameter_description"><p>nul-terminated string containing an ICE username fragment
+(length must be between 22 and 256 chars)</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>pwd</p></td>
+<td class="parameter_description"><p>nul-terminated string containing an ICE password
+(length must be between 4 and 256 chars)</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-set-local-credentials.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> on success, <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> on error.</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-set-remote-candidates"></a><h3>nice_agent_set_remote_candidates ()</h3>
+<pre class="programlisting"><span class="returnvalue">int</span>
+nice_agent_set_remote_candidates (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> component_id</code></em>,
+ <em class="parameter"><code>const <a href="/usr/share/gtk-doc/html/glib/glib-Singly-Linked-Lists.html#GSList"><span class="type">GSList</span></a> *candidates</code></em>);</pre>
+<p>Sets, adds or updates the remote candidates for a component of a stream.</p>
+<div class="note">
+<p>
+ NICE_AGENT_MAX_REMOTE_CANDIDATES is the absolute maximum limit
+ for remote candidates.
+ </p>
+<p>
+ You must first call <a class="link" href="NiceAgent.html#nice-agent-gather-candidates" title="nice_agent_gather_candidates ()"><code class="function">nice_agent_gather_candidates()</code></a> and wait for the
+ <a class="link" href="NiceAgent.html#NiceAgent-candidate-gathering-done" title="The “candidate-gathering-done” signal"><span class="type">“candidate-gathering-done”</span></a> signale before
+ calling <a class="link" href="NiceAgent.html#nice-agent-set-remote-candidates" title="nice_agent_set_remote_candidates ()"><code class="function">nice_agent_set_remote_candidates()</code></a>
+ </p>
+<p>
+ Since 0.1.3, there is no need to wait for the candidate-gathering-done signal.
+ Remote candidates can be set even while gathering local candidates.
+ Newly discovered local candidates will automatically be paired with
+ existing remote candidates.
+ </p>
+</div>
+<div class="refsect3">
+<a name="nice-agent-set-remote-candidates.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> Object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The ID of the stream the candidates are for</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>component_id</p></td>
+<td class="parameter_description"><p>The ID of the component the candidates are for</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>candidates</p></td>
+<td class="parameter_description"><p>a <a href="/usr/share/gtk-doc/html/glib/glib-Singly-Linked-Lists.html#GSList"><span class="type">GSList</span></a> of
+<a class="link" href="NiceCandidate.html" title="NiceCandidate"><span class="type">NiceCandidate</span></a> items describing each candidate to add. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Generics and defining elements of containers and arrays."><span class="acronym">element-type</span></acronym> NiceCandidate][<acronym title="Don't free data after the code is done."><span class="acronym">transfer none</span></acronym>]</span></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-set-remote-candidates.returns"></a><h4>Returns</h4>
+<p> The number of candidates added, negative on errors (memory
+allocation error or invalid component)</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-get-remote-candidates"></a><h3>nice_agent_get_remote_candidates ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Singly-Linked-Lists.html#GSList"><span class="returnvalue">GSList</span></a> *
+nice_agent_get_remote_candidates (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> component_id</code></em>);</pre>
+<p>Get a list of the remote candidates set on a stream's component</p>
+<div class="note">
+<p>
+ The caller owns the returned GSList as well as the candidates contained
+ within it.
+ </p>
+<p>
+ The list of remote candidates can change during processing.
+ The client should register for the <a class="link" href="NiceAgent.html#NiceAgent-new-remote-candidate" title="The “new-remote-candidate” signal"><span class="type">“new-remote-candidate”</span></a> signal
+ to get notified of new remote candidates.
+ </p>
+</div>
+<div class="refsect3">
+<a name="nice-agent-get-remote-candidates.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> Object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The ID of the stream</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>component_id</p></td>
+<td class="parameter_description"><p>The ID of the component</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-get-remote-candidates.returns"></a><h4>Returns</h4>
+<p>a <a href="/usr/share/gtk-doc/html/glib/glib-Singly-Linked-Lists.html#GSList"><span class="type">GSList</span></a> of
+<a href="NiceCandidate.html#NiceCandidate-struct"><span class="type">NiceCandidates</span></a> objects representing the remote candidates set on the <em class="parameter"><code>agent</code></em>
+. </p>
+<p><span class="annotation">[<acronym title="Generics and defining elements of containers and arrays."><span class="acronym">element-type</span></acronym> NiceCandidate][<acronym title="Free data after the code is done."><span class="acronym">transfer full</span></acronym>]</span></p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-get-local-candidates"></a><h3>nice_agent_get_local_candidates ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Singly-Linked-Lists.html#GSList"><span class="returnvalue">GSList</span></a> *
+nice_agent_get_local_candidates (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> component_id</code></em>);</pre>
+<p>Retrieve from the agent the list of all local candidates
+for a stream's component</p>
+<div class="note"><p>
+ The caller owns the returned GSList as well as the candidates contained
+ within it.
+ To get full results, the client should wait for the
+ <a class="link" href="NiceAgent.html#NiceAgent-candidate-gathering-done" title="The “candidate-gathering-done” signal"><span class="type">“candidate-gathering-done”</span></a> signal.
+ </p></div>
+<div class="refsect3">
+<a name="nice-agent-get-local-candidates.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> Object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The ID of the stream</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>component_id</p></td>
+<td class="parameter_description"><p>The ID of the component</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-get-local-candidates.returns"></a><h4>Returns</h4>
+<p>a <a href="/usr/share/gtk-doc/html/glib/glib-Singly-Linked-Lists.html#GSList"><span class="type">GSList</span></a> of
+<a class="link" href="NiceCandidate.html" title="NiceCandidate"><span class="type">NiceCandidate</span></a> objects representing the local candidates of <em class="parameter"><code>agent</code></em>
+. </p>
+<p><span class="annotation">[<acronym title="Generics and defining elements of containers and arrays."><span class="acronym">element-type</span></acronym> NiceCandidate][<acronym title="Free data after the code is done."><span class="acronym">transfer full</span></acronym>]</span></p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-get-selected-pair"></a><h3>nice_agent_get_selected_pair ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+nice_agent_get_selected_pair (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> component_id</code></em>,
+ <em class="parameter"><code><a class="link" href="NiceCandidate.html" title="NiceCandidate"><span class="type">NiceCandidate</span></a> **local</code></em>,
+ <em class="parameter"><code><a class="link" href="NiceCandidate.html" title="NiceCandidate"><span class="type">NiceCandidate</span></a> **remote</code></em>);</pre>
+<p>Retreive the selected candidate pair for media transmission
+for a given stream's component.</p>
+<div class="refsect3">
+<a name="nice-agent-get-selected-pair.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> Object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The ID of the stream</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>component_id</p></td>
+<td class="parameter_description"><p>The ID of the component</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>local</p></td>
+<td class="parameter_description"><p>The local selected candidate</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>remote</p></td>
+<td class="parameter_description"><p>The remote selected candidate</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-get-selected-pair.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> on success, <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> if there is no selected candidate pair</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-peer-candidate-gathering-done"></a><h3>nice_agent_peer_candidate_gathering_done ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+nice_agent_peer_candidate_gathering_done
+ (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id</code></em>);</pre>
+<p>Notifies the agent that the remote peer has concluded candidate gathering and
+thus no more remote candidates are expected to arrive for <em class="parameter"><code>stream_id</code></em>
+.</p>
+<p>This will allow the stream components without a successful connectivity check
+to stop waiting for more candidates to come and finally transit into
+<a class="link" href="NiceAgent.html#NICE-COMPONENT-STATE-FAILED:CAPS"><code class="literal">NICE_COMPONENT_STATE_FAILED</code></a>.</p>
+<p>Calling the function has an effect only when <span class="type">“trickle-ice”</span> is <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a>.</p>
+<div class="refsect3">
+<a name="nice-agent-peer-candidate-gathering-done.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> Object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The ID of the stream</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-peer-candidate-gathering-done.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> if the stream could not be found, <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> otherwise</p>
+</div>
+<p class="since">Since: <a class="link" href="ix15.html#api-index-0.1.16">0.1.16</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-send"></a><h3>nice_agent_send ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gint"><span class="returnvalue">gint</span></a>
+nice_agent_send (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> component_id</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> len</code></em>,
+ <em class="parameter"><code>const <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *buf</code></em>);</pre>
+<p>Sends a data payload over a stream's component.</p>
+<div class="note">
+<p>
+ Component state MUST be NICE_COMPONENT_STATE_READY, or as a special case,
+ in any state if component was in READY state before and was then restarted
+ </p>
+<p>
+ In reliable mode, the -1 error value means either that you are not yet
+ connected or that the send buffer is full (equivalent to EWOULDBLOCK).
+ In both cases, you simply need to wait for the
+ <a class="link" href="NiceAgent.html#NiceAgent-reliable-transport-writable" title="The “reliable-transport-writable” signal"><span class="type">“reliable-transport-writable”</span></a> signal to be fired before resending
+ the data.
+ </p>
+<p>
+ In non-reliable mode, it will virtually never happen with UDP sockets, but
+ it might happen if the active candidate is a TURN-TCP connection that got
+ disconnected.
+ </p>
+<p>
+ In both reliable and non-reliable mode, a -1 error code could also mean that
+ the stream_id and/or component_id are invalid.
+ </p>
+</div>
+<div class="refsect3">
+<a name="nice-agent-send.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> Object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The ID of the stream to send to</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>component_id</p></td>
+<td class="parameter_description"><p>The ID of the component to send to</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>len</p></td>
+<td class="parameter_description"><p>The length of the buffer to send</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buf</p></td>
+<td class="parameter_description"><p>The buffer of data to send</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-send.returns"></a><h4>Returns</h4>
+<p> The number of bytes sent, or negative error code</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-send-messages-nonblocking"></a><h3>nice_agent_send_messages_nonblocking ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gint"><span class="returnvalue">gint</span></a>
+nice_agent_send_messages_nonblocking (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> component_id</code></em>,
+ <em class="parameter"><code>const <a class="link" href="NiceAgent.html#NiceOutputMessage" title="NiceOutputMessage"><span class="type">NiceOutputMessage</span></a> *messages</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> n_messages</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/gio/GCancellable.html#GCancellable-struct"><span class="type">GCancellable</span></a> *cancellable</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Error-Reporting.html#GError"><span class="type">GError</span></a> **error</code></em>);</pre>
+<p>Sends multiple messages on the socket identified by the given
+stream/component pair. Transmission is non-blocking, so a
+<a href="/usr/share/gtk-doc/html/gio/gio-GIOError.html#G-IO-ERROR-WOULD-BLOCK:CAPS"><code class="literal">G_IO_ERROR_WOULD_BLOCK</code></a> error may be returned if the send buffer is full.</p>
+<p>As with <a class="link" href="NiceAgent.html#nice-agent-send" title="nice_agent_send ()"><code class="function">nice_agent_send()</code></a>, the given component must be in
+<a class="link" href="NiceAgent.html#NICE-COMPONENT-STATE-READY:CAPS"><code class="literal">NICE_COMPONENT_STATE_READY</code></a> or, as a special case, in any state if it was
+previously ready and was then restarted.</p>
+<p>On success, the number of messages written to the socket will be returned,
+which may be less than <em class="parameter"><code>n_messages</code></em>
+ if transmission would have blocked
+part-way through. Zero will be returned if <em class="parameter"><code>n_messages</code></em>
+ is zero, or if
+transmission would have blocked on the first message.</p>
+<p>In reliable mode, it is instead recommended to use
+<a class="link" href="NiceAgent.html#nice-agent-send" title="nice_agent_send ()"><code class="function">nice_agent_send()</code></a>. The return value can be less than <em class="parameter"><code>n_messages</code></em>
+
+or 0 even if it is still possible to send a partial message. In
+this case, "nice-agent-writable" will never be triggered, so the
+application would have to use <code class="function">nice_agent_sent()</code> to fill the buffer or have
+to retry sending at a later point.</p>
+<p>On failure, -1 will be returned and <em class="parameter"><code>error</code></em>
+ will be set. If the <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> is
+reliable and the socket is not yet connected, <a href="/usr/share/gtk-doc/html/gio/gio-GIOError.html#G-IO-ERROR-BROKEN-PIPE:CAPS"><code class="literal">G_IO_ERROR_BROKEN_PIPE</code></a> will be
+returned; if the write buffer is full, <a href="/usr/share/gtk-doc/html/gio/gio-GIOError.html#G-IO-ERROR-WOULD-BLOCK:CAPS"><code class="literal">G_IO_ERROR_WOULD_BLOCK</code></a> will be
+returned. In both cases, wait for the <a class="link" href="NiceAgent.html#NiceAgent-reliable-transport-writable" title="The “reliable-transport-writable” signal"><span class="type">“reliable-transport-writable”</span></a>
+signal before trying again. If the given <em class="parameter"><code>stream_id</code></em>
+ or <em class="parameter"><code>component_id</code></em>
+ are
+invalid or not yet connected, <a href="/usr/share/gtk-doc/html/gio/gio-GIOError.html#G-IO-ERROR-BROKEN-PIPE:CAPS"><code class="literal">G_IO_ERROR_BROKEN_PIPE</code></a> will be returned.
+<a href="/usr/share/gtk-doc/html/gio/gio-GIOError.html#G-IO-ERROR-FAILED:CAPS"><code class="literal">G_IO_ERROR_FAILED</code></a> will be returned for other errors.</p>
+<div class="refsect3">
+<a name="nice-agent-send-messages-nonblocking.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>a <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>the ID of the stream to send to</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>component_id</p></td>
+<td class="parameter_description"><p>the ID of the component to send to</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>messages</p></td>
+<td class="parameter_description"><p>array of messages to send, of at least
+<em class="parameter"><code>n_messages</code></em>
+entries in length. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=n_messages]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>n_messages</p></td>
+<td class="parameter_description"><p>number of entries in <em class="parameter"><code>messages</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>cancellable</p></td>
+<td class="parameter_description"><p>a <a href="/usr/share/gtk-doc/html/gio/GCancellable.html#GCancellable-struct"><span class="type">GCancellable</span></a> to cancel the operation from
+another thread, or <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS"><code class="literal">NULL</code></a>. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>error</p></td>
+<td class="parameter_description"><p>return location for a <a href="/usr/share/gtk-doc/html/glib/glib-Error-Reporting.html#GError"><span class="type">GError</span></a>, or <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS"><code class="literal">NULL</code></a>. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-send-messages-nonblocking.returns"></a><h4>Returns</h4>
+<p> the number of messages sent (may be zero), or -1 on error</p>
+</div>
+<p class="since">Since: <a class="link" href="ix10.html#api-index-0.1.5">0.1.5</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-recv"></a><h3>nice_agent_recv ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gssize"><span class="returnvalue">gssize</span></a>
+nice_agent_recv (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> component_id</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint8"><span class="type">guint8</span></a> *buf</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gsize"><span class="type">gsize</span></a> buf_len</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/gio/GCancellable.html#GCancellable-struct"><span class="type">GCancellable</span></a> *cancellable</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Error-Reporting.html#GError"><span class="type">GError</span></a> **error</code></em>);</pre>
+<p>A single-message version of <a class="link" href="NiceAgent.html#nice-agent-recv-messages" title="nice_agent_recv_messages ()"><code class="function">nice_agent_recv_messages()</code></a>.</p>
+<div class="refsect3">
+<a name="nice-agent-recv.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>a <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>the ID of the stream to receive on</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>component_id</p></td>
+<td class="parameter_description"><p>the ID of the component to receive on</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buf</p></td>
+<td class="parameter_description"><p>caller-allocated buffer
+to write the received data into, of length at least <em class="parameter"><code>buf_len</code></em>
+. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=buf_len][<acronym title="Out parameter, where caller must allocate storage."><span class="acronym">out caller-allocates</span></acronym>]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buf_len</p></td>
+<td class="parameter_description"><p>length of <em class="parameter"><code>buf</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>cancellable</p></td>
+<td class="parameter_description"><p>a <a href="/usr/share/gtk-doc/html/gio/GCancellable.html#GCancellable-struct"><span class="type">GCancellable</span></a> to allow the operation to be
+cancelled from another thread, or <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS"><code class="literal">NULL</code></a>. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>error</p></td>
+<td class="parameter_description"><p>return location for a <a href="/usr/share/gtk-doc/html/glib/glib-Error-Reporting.html#GError"><span class="type">GError</span></a>, or <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS"><code class="literal">NULL</code></a>. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-recv.returns"></a><h4>Returns</h4>
+<p> the number of bytes written to <em class="parameter"><code>buf</code></em>
+on success (guaranteed to be
+greater than 0 unless <em class="parameter"><code>buf_len</code></em>
+is 0), 0 if in reliable mode and the remote
+peer closed the stream, or -1 on error</p>
+</div>
+<p class="since">Since: <a class="link" href="ix10.html#api-index-0.1.5">0.1.5</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-recv-messages"></a><h3>nice_agent_recv_messages ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gint"><span class="returnvalue">gint</span></a>
+nice_agent_recv_messages (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> component_id</code></em>,
+ <em class="parameter"><code><a class="link" href="NiceAgent.html#NiceInputMessage" title="NiceInputMessage"><span class="type">NiceInputMessage</span></a> *messages</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> n_messages</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/gio/GCancellable.html#GCancellable-struct"><span class="type">GCancellable</span></a> *cancellable</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Error-Reporting.html#GError"><span class="type">GError</span></a> **error</code></em>);</pre>
+<p>Block on receiving data from the given stream/component combination on
+<em class="parameter"><code>agent</code></em>
+, returning only once exactly <em class="parameter"><code>n_messages</code></em>
+ messages have been received
+and written into <em class="parameter"><code>messages</code></em>
+, the stream is closed by the other end or by
+calling <a class="link" href="NiceAgent.html#nice-agent-remove-stream" title="nice_agent_remove_stream ()"><code class="function">nice_agent_remove_stream()</code></a>, or <em class="parameter"><code>cancellable</code></em>
+ is cancelled.</p>
+<p>Any STUN packets received will not be added to <em class="parameter"><code>messages</code></em>
+; instead,
+they'll be passed for processing to <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> itself. Since <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a>
+does not poll for messages on its own, it's therefore essential to keep
+calling this function for ICE connection establishment to work.</p>
+<p>In the non-error case, in reliable mode, this will block until all buffers in
+all <em class="parameter"><code>n_messages</code></em>
+ have been filled with received data (i.e. <em class="parameter"><code>messages</code></em>
+ is
+treated as a large, flat array of buffers). In non-reliable mode, it will
+block until <em class="parameter"><code>n_messages</code></em>
+ messages have been received, each of which does not
+have to fill all the buffers in its <a class="link" href="NiceAgent.html#NiceInputMessage" title="NiceInputMessage"><span class="type">NiceInputMessage</span></a>. In the non-reliable
+case, each <a class="link" href="NiceAgent.html#NiceInputMessage" title="NiceInputMessage"><span class="type">NiceInputMessage</span></a> must have enough buffers to contain an entire
+message (65536 bytes), or any excess data may be silently dropped.</p>
+<p>For each received message, <span class="type">“length”</span> will be set to the
+number of valid bytes stored in the message’s buffers. The bytes are stored
+sequentially in the buffers; there are no gaps apart from at the end of the
+buffer array (in non-reliable mode). If non-<a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS"><code class="literal">NULL</code></a> on input,
+<span class="type">“from”</span> will have the address of the sending peer stored in
+it. The base addresses, sizes, and number of buffers in each message will not
+be modified in any case.</p>
+<p>This must not be used in combination with <a class="link" href="NiceAgent.html#nice-agent-attach-recv" title="nice_agent_attach_recv ()"><code class="function">nice_agent_attach_recv()</code></a> on the
+same stream/component pair.</p>
+<p>If the stream/component pair doesn’t exist, or if a suitable candidate socket
+hasn’t yet been selected for it, a <a href="/usr/share/gtk-doc/html/gio/gio-GIOError.html#G-IO-ERROR-BROKEN-PIPE:CAPS"><code class="literal">G_IO_ERROR_BROKEN_PIPE</code></a> error will be
+returned. A <a href="/usr/share/gtk-doc/html/gio/gio-GIOError.html#G-IO-ERROR-CANCELLED:CAPS"><code class="literal">G_IO_ERROR_CANCELLED</code></a> error will be returned if the operation was
+cancelled. <a href="/usr/share/gtk-doc/html/gio/gio-GIOError.html#G-IO-ERROR-FAILED:CAPS"><code class="literal">G_IO_ERROR_FAILED</code></a> will be returned for other errors.</p>
+<div class="refsect3">
+<a name="nice-agent-recv-messages.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>a <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>the ID of the stream to receive on</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>component_id</p></td>
+<td class="parameter_description"><p>the ID of the component to receive on</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>messages</p></td>
+<td class="parameter_description"><p>caller-allocated
+array of <a href="NiceAgent.html#NiceInputMessage"><span class="type">NiceInputMessages</span></a> to write the received messages into, of length at
+least <em class="parameter"><code>n_messages</code></em>
+. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=n_messages][<acronym title="Out parameter, where caller must allocate storage."><span class="acronym">out caller-allocates</span></acronym>]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>n_messages</p></td>
+<td class="parameter_description"><p>number of entries in <em class="parameter"><code>messages</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>cancellable</p></td>
+<td class="parameter_description"><p>a <a href="/usr/share/gtk-doc/html/gio/GCancellable.html#GCancellable-struct"><span class="type">GCancellable</span></a> to allow the operation to be
+cancelled from another thread, or <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS"><code class="literal">NULL</code></a>. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>error</p></td>
+<td class="parameter_description"><p>return location for a <a href="/usr/share/gtk-doc/html/glib/glib-Error-Reporting.html#GError"><span class="type">GError</span></a>, or <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS"><code class="literal">NULL</code></a>. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-recv-messages.returns"></a><h4>Returns</h4>
+<p> the number of valid messages written to <em class="parameter"><code>messages</code></em>
+on success
+(guaranteed to be greater than 0 unless <em class="parameter"><code>n_messages</code></em>
+is 0), 0 if the remote
+peer closed the stream, or -1 on error</p>
+</div>
+<p class="since">Since: <a class="link" href="ix10.html#api-index-0.1.5">0.1.5</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-recv-nonblocking"></a><h3>nice_agent_recv_nonblocking ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gssize"><span class="returnvalue">gssize</span></a>
+nice_agent_recv_nonblocking (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> component_id</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint8"><span class="type">guint8</span></a> *buf</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gsize"><span class="type">gsize</span></a> buf_len</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/gio/GCancellable.html#GCancellable-struct"><span class="type">GCancellable</span></a> *cancellable</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Error-Reporting.html#GError"><span class="type">GError</span></a> **error</code></em>);</pre>
+<p>A single-message version of <a class="link" href="NiceAgent.html#nice-agent-recv-messages-nonblocking" title="nice_agent_recv_messages_nonblocking ()"><code class="function">nice_agent_recv_messages_nonblocking()</code></a>.</p>
+<div class="refsect3">
+<a name="nice-agent-recv-nonblocking.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>a <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>the ID of the stream to receive on</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>component_id</p></td>
+<td class="parameter_description"><p>the ID of the component to receive on</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buf</p></td>
+<td class="parameter_description"><p>caller-allocated buffer
+to write the received data into, of length at least <em class="parameter"><code>buf_len</code></em>
+. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=buf_len][<acronym title="Out parameter, where caller must allocate storage."><span class="acronym">out caller-allocates</span></acronym>]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buf_len</p></td>
+<td class="parameter_description"><p>length of <em class="parameter"><code>buf</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>cancellable</p></td>
+<td class="parameter_description"><p>a <a href="/usr/share/gtk-doc/html/gio/GCancellable.html#GCancellable-struct"><span class="type">GCancellable</span></a> to allow the operation to be
+cancelled from another thread, or <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS"><code class="literal">NULL</code></a>. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>error</p></td>
+<td class="parameter_description"><p>return location for a <a href="/usr/share/gtk-doc/html/glib/glib-Error-Reporting.html#GError"><span class="type">GError</span></a>, or <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS"><code class="literal">NULL</code></a>. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-recv-nonblocking.returns"></a><h4>Returns</h4>
+<p> the number of bytes received into <em class="parameter"><code>buf</code></em>
+on success (guaranteed to be
+greater than 0 unless <em class="parameter"><code>buf_len</code></em>
+is 0), 0 if in reliable mode and the remote
+peer closed the stream, or -1 on error</p>
+</div>
+<p class="since">Since: <a class="link" href="ix10.html#api-index-0.1.5">0.1.5</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-recv-messages-nonblocking"></a><h3>nice_agent_recv_messages_nonblocking ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gint"><span class="returnvalue">gint</span></a>
+nice_agent_recv_messages_nonblocking (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> component_id</code></em>,
+ <em class="parameter"><code><a class="link" href="NiceAgent.html#NiceInputMessage" title="NiceInputMessage"><span class="type">NiceInputMessage</span></a> *messages</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> n_messages</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/gio/GCancellable.html#GCancellable-struct"><span class="type">GCancellable</span></a> *cancellable</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Error-Reporting.html#GError"><span class="type">GError</span></a> **error</code></em>);</pre>
+<p>Try to receive data from the given stream/component combination on <em class="parameter"><code>agent</code></em>
+,
+without blocking. If receiving data would block, -1 is returned and
+<a href="/usr/share/gtk-doc/html/gio/gio-GIOError.html#G-IO-ERROR-WOULD-BLOCK:CAPS"><code class="literal">G_IO_ERROR_WOULD_BLOCK</code></a> is set in <em class="parameter"><code>error</code></em>
+. If any other error occurs, -1 is
+returned and <em class="parameter"><code>error</code></em>
+ is set accordingly. Otherwise, 0 is returned if (and only
+if) <em class="parameter"><code>n_messages</code></em>
+ is 0. In all other cases, the number of valid messages stored
+in <em class="parameter"><code>messages</code></em>
+ is returned, and will be greater than 0.</p>
+<p>This function behaves similarly to <a class="link" href="NiceAgent.html#nice-agent-recv-messages" title="nice_agent_recv_messages ()"><code class="function">nice_agent_recv_messages()</code></a>, except that it
+will not block on filling (in reliable mode) or receiving (in non-reliable
+mode) exactly <em class="parameter"><code>n_messages</code></em>
+ messages. In reliable mode, it will receive bytes
+into <em class="parameter"><code>messages</code></em>
+ until it would block; in non-reliable mode, it will receive
+messages until it would block.</p>
+<p>Any STUN packets received will not be added to <em class="parameter"><code>messages</code></em>
+; instead,
+they'll be passed for processing to <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> itself. Since <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a>
+does not poll for messages on its own, it's therefore essential to keep
+calling this function for ICE connection establishment to work.</p>
+<p>As this function is non-blocking, <em class="parameter"><code>cancellable</code></em>
+ is included only for parity
+with <a class="link" href="NiceAgent.html#nice-agent-recv-messages" title="nice_agent_recv_messages ()"><code class="function">nice_agent_recv_messages()</code></a>. If <em class="parameter"><code>cancellable</code></em>
+ is cancelled before this
+function is called, a <a href="/usr/share/gtk-doc/html/gio/gio-GIOError.html#G-IO-ERROR-CANCELLED:CAPS"><code class="literal">G_IO_ERROR_CANCELLED</code></a> error will be returned
+immediately.</p>
+<p>This must not be used in combination with <a class="link" href="NiceAgent.html#nice-agent-attach-recv" title="nice_agent_attach_recv ()"><code class="function">nice_agent_attach_recv()</code></a> on the
+same stream/component pair.</p>
+<div class="refsect3">
+<a name="nice-agent-recv-messages-nonblocking.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>a <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>the ID of the stream to receive on</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>component_id</p></td>
+<td class="parameter_description"><p>the ID of the component to receive on</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>messages</p></td>
+<td class="parameter_description"><p>caller-allocated
+array of <a href="NiceAgent.html#NiceInputMessage"><span class="type">NiceInputMessages</span></a> to write the received messages into, of length at
+least <em class="parameter"><code>n_messages</code></em>
+. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=n_messages][<acronym title="Out parameter, where caller must allocate storage."><span class="acronym">out caller-allocates</span></acronym>]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>n_messages</p></td>
+<td class="parameter_description"><p>number of entries in <em class="parameter"><code>messages</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>cancellable</p></td>
+<td class="parameter_description"><p>a <a href="/usr/share/gtk-doc/html/gio/GCancellable.html#GCancellable-struct"><span class="type">GCancellable</span></a> to allow the operation to be
+cancelled from another thread, or <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS"><code class="literal">NULL</code></a>. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>error</p></td>
+<td class="parameter_description"><p>return location for a <a href="/usr/share/gtk-doc/html/glib/glib-Error-Reporting.html#GError"><span class="type">GError</span></a>, or <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS"><code class="literal">NULL</code></a>. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-recv-messages-nonblocking.returns"></a><h4>Returns</h4>
+<p> the number of valid messages written to <em class="parameter"><code>messages</code></em>
+on success
+(guaranteed to be greater than 0 unless <em class="parameter"><code>n_messages</code></em>
+is 0), 0 if in reliable
+mode and the remote peer closed the stream, or -1 on error</p>
+</div>
+<p class="since">Since: <a class="link" href="ix10.html#api-index-0.1.5">0.1.5</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-attach-recv"></a><h3>nice_agent_attach_recv ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+nice_agent_attach_recv (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> component_id</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-The-Main-Event-Loop.html#GMainContext"><span class="type">GMainContext</span></a> *ctx</code></em>,
+ <em class="parameter"><code><a class="link" href="NiceAgent.html#NiceAgentRecvFunc" title="NiceAgentRecvFunc ()"><span class="type">NiceAgentRecvFunc</span></a> func</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gpointer"><span class="type">gpointer</span></a> data</code></em>);</pre>
+<p>Attaches the stream's component's sockets to the Glib Mainloop Context in
+order to be notified whenever data becomes available for a component,
+and to enable <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> to receive STUN messages (during the
+establishment of ICE connectivity).</p>
+<p>This must not be used in combination with <a class="link" href="NiceAgent.html#nice-agent-recv-messages" title="nice_agent_recv_messages ()"><code class="function">nice_agent_recv_messages()</code></a> (or
+<span class="type">NiceIOStream</span> or <span class="type">NiceInputStream</span>) on the same stream/component pair.</p>
+<p>Calling <a class="link" href="NiceAgent.html#nice-agent-attach-recv" title="nice_agent_attach_recv ()"><code class="function">nice_agent_attach_recv()</code></a> with a <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS"><code class="literal">NULL</code></a> <em class="parameter"><code>func</code></em>
+ will detach any existing
+callback and cause reception to be paused for the given stream/component
+pair. You must iterate the previously specified <a href="/usr/share/gtk-doc/html/glib/glib-The-Main-Event-Loop.html#GMainContext"><span class="type">GMainContext</span></a> sufficiently to
+ensure all pending I/O callbacks have been received before calling this
+function to unset <em class="parameter"><code>func</code></em>
+, otherwise data loss of received packets may occur.</p>
+<p><span class="annotation">[<acronym title="Exposed in C code, not necessarily available in other languages."><span class="acronym">skip</span></acronym>]</span></p>
+<div class="refsect3">
+<a name="nice-agent-attach-recv.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> Object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The ID of stream</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>component_id</p></td>
+<td class="parameter_description"><p>The ID of the component</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>ctx</p></td>
+<td class="parameter_description"><p>The Glib Mainloop Context to use for listening on the component</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>func</p></td>
+<td class="parameter_description"><p>The callback function to be called when data is received on
+the stream's component (will not be called for STUN messages that
+should be handled by <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> itself)</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>data</p></td>
+<td class="parameter_description"><p>user data associated with the callback</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-attach-recv.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> on success, <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> if the stream or component IDs are invalid.</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-set-selected-pair"></a><h3>nice_agent_set_selected_pair ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+nice_agent_set_selected_pair (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> component_id</code></em>,
+ <em class="parameter"><code>const <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *lfoundation</code></em>,
+ <em class="parameter"><code>const <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *rfoundation</code></em>);</pre>
+<p>Sets the selected candidate pair for media transmission
+for a given stream's component. Calling this function will
+disable all further ICE processing (connection check,
+state machine updates, etc). Note that keepalives will
+continue to be sent.</p>
+<div class="refsect3">
+<a name="nice-agent-set-selected-pair.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> Object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The ID of the stream</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>component_id</p></td>
+<td class="parameter_description"><p>The ID of the component</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>lfoundation</p></td>
+<td class="parameter_description"><p>The local foundation of the candidate to use</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>rfoundation</p></td>
+<td class="parameter_description"><p>The remote foundation of the candidate to use</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-set-selected-pair.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> on success, <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> if the candidate pair cannot be found</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-set-selected-remote-candidate"></a><h3>nice_agent_set_selected_remote_candidate ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+nice_agent_set_selected_remote_candidate
+ (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> component_id</code></em>,
+ <em class="parameter"><code><a class="link" href="NiceCandidate.html" title="NiceCandidate"><span class="type">NiceCandidate</span></a> *candidate</code></em>);</pre>
+<p>Sets the selected remote candidate for media transmission
+for a given stream's component. This is used to force the selection of
+a specific remote candidate even when connectivity checks are failing
+(e.g. non-ICE compatible candidates).
+Calling this function will disable all further ICE processing
+(connection check, state machine updates, etc). Note that keepalives will
+continue to be sent.</p>
+<div class="refsect3">
+<a name="nice-agent-set-selected-remote-candidate.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> Object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The ID of the stream</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>component_id</p></td>
+<td class="parameter_description"><p>The ID of the component</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>candidate</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceCandidate.html" title="NiceCandidate"><span class="type">NiceCandidate</span></a> to select</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-set-selected-remote-candidate.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> on success, <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> on failure</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-set-stream-tos"></a><h3>nice_agent_set_stream_tos ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+nice_agent_set_stream_tos (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gint"><span class="type">gint</span></a> tos</code></em>);</pre>
+<p>Sets the IP_TOS and/or IPV6_TCLASS field on the stream's sockets' options</p>
+<div class="refsect3">
+<a name="nice-agent-set-stream-tos.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> Object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The ID of the stream</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>tos</p></td>
+<td class="parameter_description"><p>The ToS to set</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="ix06.html#api-index-0.0.9">0.0.9</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-set-software"></a><h3>nice_agent_set_software ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+nice_agent_set_software (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code>const <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *software</code></em>);</pre>
+<p>This function will set the value of the SOFTWARE attribute to be added to
+STUN requests, responses and error responses sent during connectivity checks.</p>
+<p>
+The SOFTWARE attribute will only be added in the <a class="link" href="NiceAgent.html#NICE-COMPATIBILITY-RFC5245:CAPS"><span class="type">NICE_COMPATIBILITY_RFC5245</span></a>
+and <a class="link" href="NiceAgent.html#NICE-COMPATIBILITY-WLM2009:CAPS"><span class="type">NICE_COMPATIBILITY_WLM2009</span></a> compatibility modes.
+
+</p>
+<div class="note">
+<p>
+ The <em class="parameter"><code>software</code></em> argument will be appended with the libnice version before
+ being sent.
+ </p>
+<p>
+ The <em class="parameter"><code>software</code></em> argument must be in UTF-8 encoding and only the first
+ 128 characters will be sent.
+ </p>
+</div>
+<div class="refsect3">
+<a name="nice-agent-set-software.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> Object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>software</p></td>
+<td class="parameter_description"><p>The value of the SOFTWARE attribute to add.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="ix07.html#api-index-0.0.10">0.0.10</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-restart"></a><h3>nice_agent_restart ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+nice_agent_restart (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>);</pre>
+<p>Restarts the session as defined in ICE draft 19. This function
+needs to be called both when initiating (ICE spec section 9.1.1.1.
+"ICE Restarts"), as well as when reacting (spec section 9.2.1.1.
+"Detecting ICE Restart") to a restart.</p>
+<div class="refsect3">
+<a name="nice-agent-restart.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> Object</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-restart.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> on success <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> on error</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-restart-stream"></a><h3>nice_agent_restart_stream ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+nice_agent_restart_stream (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id</code></em>);</pre>
+<p>Restarts a single stream as defined in RFC 5245. This function
+needs to be called both when initiating (ICE spec section 9.1.1.1.
+"ICE Restarts"), as well as when reacting (spec section 9.2.1.1.
+"Detecting ICE Restart") to a restart.</p>
+<p>Unlike <a class="link" href="NiceAgent.html#nice-agent-restart" title="nice_agent_restart ()"><code class="function">nice_agent_restart()</code></a>, this applies to a single stream. It also
+does not generate a new tie breaker.</p>
+<div class="refsect3">
+<a name="nice-agent-restart-stream.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> Object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The ID of the stream</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-restart-stream.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> on success <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> on error</p>
+</div>
+<p class="since">Since: <a class="link" href="ix11.html#api-index-0.1.6">0.1.6</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-set-stream-name"></a><h3>nice_agent_set_stream_name ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+nice_agent_set_stream_name (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id</code></em>,
+ <em class="parameter"><code>const <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *name</code></em>);</pre>
+<p>This function will assign a media type to a stream. The only values
+that can be used to produce a valid SDP are: "audio", "video",
+"text", "application", "image" and "message".</p>
+<p>This is only useful when parsing and generating an SDP of the
+candidates.</p>
+<p>See also: <a class="link" href="NiceAgent.html#nice-agent-generate-local-sdp" title="nice_agent_generate_local_sdp ()"><code class="function">nice_agent_generate_local_sdp()</code></a></p>
+<p>See also: <a class="link" href="NiceAgent.html#nice-agent-parse-remote-sdp" title="nice_agent_parse_remote_sdp ()"><code class="function">nice_agent_parse_remote_sdp()</code></a></p>
+<p>See also: <a class="link" href="NiceAgent.html#nice-agent-get-stream-name" title="nice_agent_get_stream_name ()"><code class="function">nice_agent_get_stream_name()</code></a></p>
+<div class="refsect3">
+<a name="nice-agent-set-stream-name.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> Object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The ID of the stream to change</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>name</p></td>
+<td class="parameter_description"><p>The new name of the stream or <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS"><code class="literal">NULL</code></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-set-stream-name.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> if the name has been set. <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> in case of error
+(invalid stream or duplicate name).</p>
+</div>
+<p class="since">Since: <a class="link" href="ix09.html#api-index-0.1.4">0.1.4</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-get-stream-name"></a><h3>nice_agent_get_stream_name ()</h3>
+<pre class="programlisting">const <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="returnvalue">gchar</span></a> *
+nice_agent_get_stream_name (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id</code></em>);</pre>
+<p>This function will return the name assigned to a stream.</p>
+<p>See also: <a class="link" href="NiceAgent.html#nice-agent-set-stream-name" title="nice_agent_set_stream_name ()"><code class="function">nice_agent_set_stream_name()</code></a></p>
+<div class="refsect3">
+<a name="nice-agent-get-stream-name.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> Object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The ID of the stream to change</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-get-stream-name.returns"></a><h4>Returns</h4>
+<p> The name of the stream. The name is only valid while the stream
+exists or until it changes through a call to <a class="link" href="NiceAgent.html#nice-agent-set-stream-name" title="nice_agent_set_stream_name ()"><code class="function">nice_agent_set_stream_name()</code></a>.</p>
+</div>
+<p class="since">Since: <a class="link" href="ix09.html#api-index-0.1.4">0.1.4</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-get-default-local-candidate"></a><h3>nice_agent_get_default_local_candidate ()</h3>
+<pre class="programlisting"><a class="link" href="NiceCandidate.html" title="NiceCandidate"><span class="returnvalue">NiceCandidate</span></a> *
+nice_agent_get_default_local_candidate
+ (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> component_id</code></em>);</pre>
+<p>This helper function will return the recommended default candidate to be
+used for non-ICE compatible clients. This will usually be the candidate
+with the lowest priority, since it will be the longest path but the one with
+the most chances of success.</p>
+<div class="note"><p>
+ This function is only useful in order to manually generate the
+ local SDP
+ </p></div>
+<div class="refsect3">
+<a name="nice-agent-get-default-local-candidate.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> Object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The ID of the stream</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>component_id</p></td>
+<td class="parameter_description"><p>The ID of the component</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-get-default-local-candidate.returns"></a><h4>Returns</h4>
+<p> The candidate to be used as the default candidate, or <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS"><code class="literal">NULL</code></a> in case
+of error. Must be freed with <a class="link" href="NiceCandidate.html#nice-candidate-free" title="nice_candidate_free ()"><code class="function">nice_candidate_free()</code></a> once done.</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-generate-local-sdp"></a><h3>nice_agent_generate_local_sdp ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="returnvalue">gchar</span></a> *
+nice_agent_generate_local_sdp (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>);</pre>
+<p>Generate an SDP string containing the local candidates and credentials for
+all streams and components in the agent.</p>
+<div class="note">
+<p>
+ The SDP will not contain any codec lines and the 'm' line will not list
+ any payload types.
+ </p>
+<p>
+ It is highly recommended to set names on the streams prior to calling this
+ function. Unnamed streams will show up as '-' in the 'm' line, but the SDP
+ will not be parseable with <a class="link" href="NiceAgent.html#nice-agent-parse-remote-sdp" title="nice_agent_parse_remote_sdp ()"><code class="function">nice_agent_parse_remote_sdp()</code></a> if a stream is
+ unnamed.
+ </p>
+<p>
+ The default candidate in the SDP will be selected based on the lowest
+ priority candidate for the first component.
+ </p>
+</div>
+<p>See also: <a class="link" href="NiceAgent.html#nice-agent-set-stream-name" title="nice_agent_set_stream_name ()"><code class="function">nice_agent_set_stream_name()</code></a> </p>
+<p>See also: <a class="link" href="NiceAgent.html#nice-agent-parse-remote-sdp" title="nice_agent_parse_remote_sdp ()"><code class="function">nice_agent_parse_remote_sdp()</code></a> </p>
+<p>See also: <a class="link" href="NiceAgent.html#nice-agent-generate-local-stream-sdp" title="nice_agent_generate_local_stream_sdp ()"><code class="function">nice_agent_generate_local_stream_sdp()</code></a> </p>
+<p>See also: <a class="link" href="NiceAgent.html#nice-agent-generate-local-candidate-sdp" title="nice_agent_generate_local_candidate_sdp ()"><code class="function">nice_agent_generate_local_candidate_sdp()</code></a> </p>
+<p>See also: <a class="link" href="NiceAgent.html#nice-agent-get-default-local-candidate" title="nice_agent_get_default_local_candidate ()"><code class="function">nice_agent_get_default_local_candidate()</code></a> </p>
+<div class="refsect3">
+<a name="nice-agent-generate-local-sdp.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> Object</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-generate-local-sdp.returns"></a><h4>Returns</h4>
+<p> A string representing the local SDP. Must be freed with <a href="/usr/share/gtk-doc/html/glib/glib-Memory-Allocation.html#g-free"><code class="function">g_free()</code></a>
+once done.</p>
+</div>
+<p class="since">Since: <a class="link" href="ix09.html#api-index-0.1.4">0.1.4</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-generate-local-stream-sdp"></a><h3>nice_agent_generate_local_stream_sdp ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="returnvalue">gchar</span></a> *
+nice_agent_generate_local_stream_sdp (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="type">gboolean</span></a> include_non_ice</code></em>);</pre>
+<p>Generate an SDP string containing the local candidates and credentials
+for a stream.</p>
+<div class="note">
+<p>
+ The SDP will not contain any codec lines and the 'm' line will not list
+ any payload types.
+ </p>
+<p>
+ It is highly recommended to set the name of the stream prior to calling this
+ function. Unnamed streams will show up as '-' in the 'm' line.
+ </p>
+<p>
+ The default candidate in the SDP will be selected based on the lowest
+ priority candidate.
+ </p>
+</div>
+<p>See also: <a class="link" href="NiceAgent.html#nice-agent-set-stream-name" title="nice_agent_set_stream_name ()"><code class="function">nice_agent_set_stream_name()</code></a> </p>
+<p>See also: <a class="link" href="NiceAgent.html#nice-agent-parse-remote-stream-sdp" title="nice_agent_parse_remote_stream_sdp ()"><code class="function">nice_agent_parse_remote_stream_sdp()</code></a> </p>
+<p>See also: <a class="link" href="NiceAgent.html#nice-agent-generate-local-sdp" title="nice_agent_generate_local_sdp ()"><code class="function">nice_agent_generate_local_sdp()</code></a> </p>
+<p>See also: <a class="link" href="NiceAgent.html#nice-agent-generate-local-candidate-sdp" title="nice_agent_generate_local_candidate_sdp ()"><code class="function">nice_agent_generate_local_candidate_sdp()</code></a> </p>
+<p>See also: <a class="link" href="NiceAgent.html#nice-agent-get-default-local-candidate" title="nice_agent_get_default_local_candidate ()"><code class="function">nice_agent_get_default_local_candidate()</code></a> </p>
+<div class="refsect3">
+<a name="nice-agent-generate-local-stream-sdp.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> Object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The ID of the stream</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>include_non_ice</p></td>
+<td class="parameter_description"><p>Whether or not to include non ICE specific lines
+(m=, c= and a=rtcp: lines)</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-generate-local-stream-sdp.returns"></a><h4>Returns</h4>
+<p> A string representing the local SDP for the stream. Must be freed
+with <a href="/usr/share/gtk-doc/html/glib/glib-Memory-Allocation.html#g-free"><code class="function">g_free()</code></a> once done.</p>
+</div>
+<p class="since">Since: <a class="link" href="ix09.html#api-index-0.1.4">0.1.4</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-generate-local-candidate-sdp"></a><h3>nice_agent_generate_local_candidate_sdp ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="returnvalue">gchar</span></a> *
+nice_agent_generate_local_candidate_sdp
+ (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a class="link" href="NiceCandidate.html" title="NiceCandidate"><span class="type">NiceCandidate</span></a> *candidate</code></em>);</pre>
+<p>Generate an SDP string representing a local candidate.</p>
+<p>See also: <a class="link" href="NiceAgent.html#nice-agent-parse-remote-candidate-sdp" title="nice_agent_parse_remote_candidate_sdp ()"><code class="function">nice_agent_parse_remote_candidate_sdp()</code></a> </p>
+<p>See also: <a class="link" href="NiceAgent.html#nice-agent-generate-local-sdp" title="nice_agent_generate_local_sdp ()"><code class="function">nice_agent_generate_local_sdp()</code></a> </p>
+<p>See also: <a class="link" href="NiceAgent.html#nice-agent-generate-local-stream-sdp" title="nice_agent_generate_local_stream_sdp ()"><code class="function">nice_agent_generate_local_stream_sdp()</code></a> </p>
+<div class="refsect3">
+<a name="nice-agent-generate-local-candidate-sdp.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> Object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>candidate</p></td>
+<td class="parameter_description"><p>The candidate to generate</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-generate-local-candidate-sdp.returns"></a><h4>Returns</h4>
+<p> A string representing the SDP for the candidate. Must be freed
+with <a href="/usr/share/gtk-doc/html/glib/glib-Memory-Allocation.html#g-free"><code class="function">g_free()</code></a> once done.</p>
+</div>
+<p class="since">Since: <a class="link" href="ix09.html#api-index-0.1.4">0.1.4</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-parse-remote-sdp"></a><h3>nice_agent_parse_remote_sdp ()</h3>
+<pre class="programlisting"><span class="returnvalue">int</span>
+nice_agent_parse_remote_sdp (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code>const <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *sdp</code></em>);</pre>
+<p>Parse an SDP string and extracts candidates and credentials from it and sets
+them on the agent.</p>
+<p>See also: <a class="link" href="NiceAgent.html#nice-agent-set-stream-name" title="nice_agent_set_stream_name ()"><code class="function">nice_agent_set_stream_name()</code></a> </p>
+<p>See also: <a class="link" href="NiceAgent.html#nice-agent-generate-local-sdp" title="nice_agent_generate_local_sdp ()"><code class="function">nice_agent_generate_local_sdp()</code></a> </p>
+<p>See also: <a class="link" href="NiceAgent.html#nice-agent-parse-remote-stream-sdp" title="nice_agent_parse_remote_stream_sdp ()"><code class="function">nice_agent_parse_remote_stream_sdp()</code></a> </p>
+<p>See also: <a class="link" href="NiceAgent.html#nice-agent-parse-remote-candidate-sdp" title="nice_agent_parse_remote_candidate_sdp ()"><code class="function">nice_agent_parse_remote_candidate_sdp()</code></a> </p>
+<div class="refsect3">
+<a name="nice-agent-parse-remote-sdp.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> Object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>sdp</p></td>
+<td class="parameter_description"><p>The remote SDP to parse</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-parse-remote-sdp.returns"></a><h4>Returns</h4>
+<p> The number of candidates added, negative on errors</p>
+</div>
+<p class="since">Since: <a class="link" href="ix09.html#api-index-0.1.4">0.1.4</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-parse-remote-stream-sdp"></a><h3>nice_agent_parse_remote_stream_sdp ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Singly-Linked-Lists.html#GSList"><span class="returnvalue">GSList</span></a> *
+nice_agent_parse_remote_stream_sdp (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id</code></em>,
+ <em class="parameter"><code>const <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *sdp</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> **ufrag</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> **pwd</code></em>);</pre>
+<p>Parse an SDP string representing a single stream and extracts candidates
+and credentials from it.</p>
+<p>See also: <a class="link" href="NiceAgent.html#nice-agent-generate-local-stream-sdp" title="nice_agent_generate_local_stream_sdp ()"><code class="function">nice_agent_generate_local_stream_sdp()</code></a> </p>
+<p>See also: <a class="link" href="NiceAgent.html#nice-agent-parse-remote-sdp" title="nice_agent_parse_remote_sdp ()"><code class="function">nice_agent_parse_remote_sdp()</code></a> </p>
+<p>See also: <a class="link" href="NiceAgent.html#nice-agent-parse-remote-candidate-sdp" title="nice_agent_parse_remote_candidate_sdp ()"><code class="function">nice_agent_parse_remote_candidate_sdp()</code></a> </p>
+<div class="refsect3">
+<a name="nice-agent-parse-remote-stream-sdp.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> Object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The ID of the stream to parse</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>sdp</p></td>
+<td class="parameter_description"><p>The remote SDP to parse</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>ufrag</p></td>
+<td class="parameter_description"><p>Pointer to store the ice ufrag if non <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS"><code class="literal">NULL</code></a>. Must be freed with
+<a href="/usr/share/gtk-doc/html/glib/glib-Memory-Allocation.html#g-free"><code class="function">g_free()</code></a> after use</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>pwd</p></td>
+<td class="parameter_description"><p>Pointer to store the ice password if non <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS"><code class="literal">NULL</code></a>. Must be freed with
+<a href="/usr/share/gtk-doc/html/glib/glib-Memory-Allocation.html#g-free"><code class="function">g_free()</code></a> after use</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-parse-remote-stream-sdp.returns"></a><h4>Returns</h4>
+<p>A <a href="/usr/share/gtk-doc/html/glib/glib-Singly-Linked-Lists.html#GSList"><span class="type">GSList</span></a> of
+candidates parsed from the SDP, or <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS"><code class="literal">NULL</code></a> in case of errors. </p>
+<p><span class="annotation">[<acronym title="Generics and defining elements of containers and arrays."><span class="acronym">element-type</span></acronym> NiceCandidate][<acronym title="Free data after the code is done."><span class="acronym">transfer full</span></acronym>]</span></p>
+</div>
+<p class="since">Since: <a class="link" href="ix09.html#api-index-0.1.4">0.1.4</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-parse-remote-candidate-sdp"></a><h3>nice_agent_parse_remote_candidate_sdp ()</h3>
+<pre class="programlisting"><a class="link" href="NiceCandidate.html" title="NiceCandidate"><span class="returnvalue">NiceCandidate</span></a> *
+nice_agent_parse_remote_candidate_sdp (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id</code></em>,
+ <em class="parameter"><code>const <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *sdp</code></em>);</pre>
+<p>Parse an SDP string and extracts the candidate from it.</p>
+<p>See also: <a class="link" href="NiceAgent.html#nice-agent-generate-local-candidate-sdp" title="nice_agent_generate_local_candidate_sdp ()"><code class="function">nice_agent_generate_local_candidate_sdp()</code></a> </p>
+<p>See also: <a class="link" href="NiceAgent.html#nice-agent-parse-remote-sdp" title="nice_agent_parse_remote_sdp ()"><code class="function">nice_agent_parse_remote_sdp()</code></a> </p>
+<p>See also: <a class="link" href="NiceAgent.html#nice-agent-parse-remote-stream-sdp" title="nice_agent_parse_remote_stream_sdp ()"><code class="function">nice_agent_parse_remote_stream_sdp()</code></a> </p>
+<div class="refsect3">
+<a name="nice-agent-parse-remote-candidate-sdp.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> Object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The ID of the stream the candidate belongs to</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>sdp</p></td>
+<td class="parameter_description"><p>The remote SDP to parse</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-parse-remote-candidate-sdp.returns"></a><h4>Returns</h4>
+<p> The parsed candidate or <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS"><code class="literal">NULL</code></a> if there was an error.</p>
+</div>
+<p class="since">Since: <a class="link" href="ix09.html#api-index-0.1.4">0.1.4</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-get-io-stream"></a><h3>nice_agent_get_io_stream ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/gio/GIOStream.html#GIOStream-struct"><span class="returnvalue">GIOStream</span></a> *
+nice_agent_get_io_stream (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> component_id</code></em>);</pre>
+<p>Gets a <a href="/usr/share/gtk-doc/html/gio/GIOStream.html#GIOStream-struct"><span class="type">GIOStream</span></a> wrapper around the given stream and component in
+<em class="parameter"><code>agent</code></em>
+. The I/O stream will be valid for as long as <em class="parameter"><code>stream_id</code></em>
+ is valid.
+The <a href="/usr/share/gtk-doc/html/gio/GInputStream.html#GInputStream-struct"><span class="type">GInputStream</span></a> and <a href="/usr/share/gtk-doc/html/gio/GOutputStream.html#GOutputStream-struct"><span class="type">GOutputStream</span></a> implement <a href="/usr/share/gtk-doc/html/gio/GPollableInputStream.html#GPollableInputStream-struct"><span class="type">GPollableInputStream</span></a> and
+<a href="/usr/share/gtk-doc/html/gio/GPollableOutputStream.html#GPollableOutputStream-struct"><span class="type">GPollableOutputStream</span></a>.</p>
+<p>This function may only be called on reliable <a href="NiceAgent.html#NiceAgent-struct"><span class="type">NiceAgents</span></a>. It is a
+programming error to try and create an I/O stream wrapper for an
+unreliable stream.</p>
+<div class="refsect3">
+<a name="nice-agent-get-io-stream.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>A <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The ID of the stream to wrap</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>component_id</p></td>
+<td class="parameter_description"><p>The ID of the component to wrap</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-get-io-stream.returns"></a><h4>Returns</h4>
+<p>A <a href="/usr/share/gtk-doc/html/gio/GIOStream.html#GIOStream-struct"><span class="type">GIOStream</span></a>. </p>
+<p><span class="annotation">[<acronym title="Free data after the code is done."><span class="acronym">transfer full</span></acronym>]</span></p>
+</div>
+<p class="since">Since: <a class="link" href="ix10.html#api-index-0.1.5">0.1.5</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-get-selected-socket"></a><h3>nice_agent_get_selected_socket ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/gio/GSocket.html#GSocket-struct"><span class="returnvalue">GSocket</span></a> *
+nice_agent_get_selected_socket (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> component_id</code></em>);</pre>
+<p>Retreive the local socket associated with the selected candidate pair
+for media transmission for a given stream's component.</p>
+<p>This is useful for adding ICE support to legacy applications that already
+have a protocol that maintains a connection. If the socket is duplicated
+before unrefing the agent, the application can take over and continue to use
+it. New applications are encouraged to use the built in libnice stream
+handling instead and let libnice handle the connection maintenance.</p>
+<p>Users of this method are encouraged to not use a TURN relay or any kind
+of proxy, as in this case, the socket will not be available to the
+application because the packets are encapsulated.</p>
+<div class="refsect3">
+<a name="nice-agent-get-selected-socket.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> Object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The ID of the stream</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>component_id</p></td>
+<td class="parameter_description"><p>The ID of the component</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-get-selected-socket.returns"></a><h4>Returns</h4>
+<p>pointer to the <a href="/usr/share/gtk-doc/html/gio/GSocket.html#GSocket-struct"><span class="type">GSocket</span></a>, or <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS"><code class="literal">NULL</code></a> if
+there is no selected candidate or if the selected candidate is a relayed
+candidate. </p>
+<p><span class="annotation">[<acronym title="Free data after the code is done."><span class="acronym">transfer full</span></acronym>][<acronym title="NULL may be passed as the value in, out, in-out; or as a return value."><span class="acronym">nullable</span></acronym>]</span></p>
+</div>
+<p class="since">Since: <a class="link" href="ix10.html#api-index-0.1.5">0.1.5</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-get-component-state"></a><h3>nice_agent_get_component_state ()</h3>
+<pre class="programlisting"><a class="link" href="NiceAgent.html#NiceComponentState" title="enum NiceComponentState"><span class="returnvalue">NiceComponentState</span></a>
+nice_agent_get_component_state (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> component_id</code></em>);</pre>
+<p>Retrieves the current state of a component.</p>
+<div class="refsect3">
+<a name="nice-agent-get-component-state.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> Object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The ID of the stream</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>component_id</p></td>
+<td class="parameter_description"><p>The ID of the component</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-agent-get-component-state.returns"></a><h4>Returns</h4>
+<p> the <a class="link" href="NiceAgent.html#NiceComponentState" title="enum NiceComponentState"><span class="type">NiceComponentState</span></a> of the component and
+<a class="link" href="NiceAgent.html#NICE-COMPONENT-STATE-FAILED:CAPS"><code class="literal">NICE_COMPONENT_STATE_FAILED</code></a> if the component was invalid.</p>
+</div>
+<p class="since">Since: <a class="link" href="ix12.html#api-index-0.1.8">0.1.8</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-agent-close-async"></a><h3>nice_agent_close_async ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+nice_agent_close_async (<em class="parameter"><code><a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/gio/GAsyncResult.html#GAsyncReadyCallback"><span class="type">GAsyncReadyCallback</span></a> callback</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gpointer"><span class="type">gpointer</span></a> callback_data</code></em>);</pre>
+<p>Asynchronously closes resources the agent has allocated on remote servers.</p>
+<p>The agent will call the callback in the current <a href="/usr/share/gtk-doc/html/glib/glib-The-Main-Event-Loop.html#GMainContext"><span class="type">GMainContext</span></a> in
+which this function is called. The <a href="/usr/share/gtk-doc/html/gio/GAsyncResult.html#GAsyncResult-struct"><span class="type">GAsyncResult</span></a> in the callback
+can be ignored as this operation never fails.</p>
+<p>Calling this function before freeing the agent makes sure the allocated relay
+ports aren't left behind on TURN server but properly removed.</p>
+<div class="refsect3">
+<a name="nice-agent-close-async.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>callback</p></td>
+<td class="parameter_description"><p>A callback that will be called when the closing is
+complete. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="NULL may be passed as the value in, out, in-out; or as a return value."><span class="acronym">nullable</span></acronym>]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>callback_data</p></td>
+<td class="parameter_description"><p>A pointer that will be passed to the callback. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="NULL may be passed as the value in, out, in-out; or as a return value."><span class="acronym">nullable</span></acronym>]</span></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="ix15.html#api-index-0.1.16">0.1.16</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-component-state-to-string"></a><h3>nice_component_state_to_string ()</h3>
+<pre class="programlisting">const <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="returnvalue">gchar</span></a> *
+nice_component_state_to_string (<em class="parameter"><code><a class="link" href="NiceAgent.html#NiceComponentState" title="enum NiceComponentState"><span class="type">NiceComponentState</span></a> state</code></em>);</pre>
+<p>Returns a string representation of the state, generally to use in debug
+messages.</p>
+<div class="refsect3">
+<a name="nice-component-state-to-string.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>state</p></td>
+<td class="parameter_description"><p>a <a class="link" href="NiceAgent.html#NiceComponentState" title="enum NiceComponentState"><span class="type">NiceComponentState</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-component-state-to-string.returns"></a><h4>Returns</h4>
+<p>a string representation of <em class="parameter"><code>state</code></em>
+. </p>
+<p><span class="annotation">[<acronym title="Don't free data after the code is done."><span class="acronym">transfer none</span></acronym>]</span></p>
+</div>
+<p class="since">Since: <a class="link" href="ix11.html#api-index-0.1.6">0.1.6</a></p>
+</div>
+</div>
+<div class="refsect1">
+<a name="NiceAgent.other_details"></a><h2>Types and Values</h2>
+<div class="refsect2">
+<a name="NiceAgent-struct"></a><h3>NiceAgent</h3>
+<pre class="programlisting">typedef struct _NiceAgent NiceAgent;</pre>
+<p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> is the main GObject of the libnice library and represents
+the ICE agent.</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceComponentState"></a><h3>enum NiceComponentState</h3>
+<p>An enum representing the state of a component.</p>
+<p> See also: <a class="link" href="NiceAgent.html#NiceAgent-component-state-changed" title="The “component-state-changed” signal"><span class="type">“component-state-changed”</span></a> </p>
+<div class="refsect3">
+<a name="NiceComponentState.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-COMPONENT-STATE-DISCONNECTED:CAPS"></a>NICE_COMPONENT_STATE_DISCONNECTED</p></td>
+<td class="enum_member_description">
+<p>No activity scheduled</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-COMPONENT-STATE-GATHERING:CAPS"></a>NICE_COMPONENT_STATE_GATHERING</p></td>
+<td class="enum_member_description">
+<p>Gathering local candidates</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-COMPONENT-STATE-CONNECTING:CAPS"></a>NICE_COMPONENT_STATE_CONNECTING</p></td>
+<td class="enum_member_description">
+<p>Establishing connectivity</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-COMPONENT-STATE-CONNECTED:CAPS"></a>NICE_COMPONENT_STATE_CONNECTED</p></td>
+<td class="enum_member_description">
+<p>At least one working candidate pair</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-COMPONENT-STATE-READY:CAPS"></a>NICE_COMPONENT_STATE_READY</p></td>
+<td class="enum_member_description">
+<p>ICE concluded, candidate pair selection
+is now final</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-COMPONENT-STATE-FAILED:CAPS"></a>NICE_COMPONENT_STATE_FAILED</p></td>
+<td class="enum_member_description">
+<p>Connectivity checks have been completed,
+but connectivity was not established</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-COMPONENT-STATE-LAST:CAPS"></a>NICE_COMPONENT_STATE_LAST</p></td>
+<td class="enum_member_description">
+<p>Dummy state</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceComponentType"></a><h3>enum NiceComponentType</h3>
+<p>Convenience enum representing the type of a component for use as the
+component_id for RTP/RTCP usages.</p>
+<div class="example">
+<a name="id-1.2.2.1.12.4.4"></a><p class="title"><b>Example 2. Example of use.</b></p>
+<div class="example-contents">
+ <table class="listing_frame" border="0" cellpadding="0" cellspacing="0">
+ <tbody>
+ <tr>
+ <td class="listing_lines" align="right"><pre>1</pre></td>
+ <td class="listing_code"><pre class="programlisting"><span class="function"><a href="NiceAgent.html#nice-agent-send">nice_agent_send</a></span><span class="normal"> </span><span class="symbol">(</span><span class="normal">agent</span><span class="symbol">,</span><span class="normal"> stream_id</span><span class="symbol">,</span><span class="normal"> <a href="NiceAgent.html#NICE-COMPONENT-TYPE-RTP:CAPS">NICE_COMPONENT_TYPE_RTP</a></span><span class="symbol">,</span><span class="normal"> len</span><span class="symbol">,</span><span class="normal"> buf</span><span class="symbol">);</span></pre></td>
+ </tr>
+ </tbody>
+ </table>
+</div>
+
+</div>
+<br class="example-break"><div class="refsect3">
+<a name="NiceComponentType.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-COMPONENT-TYPE-RTP:CAPS"></a>NICE_COMPONENT_TYPE_RTP</p></td>
+<td class="enum_member_description">
+<p>RTP Component type</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-COMPONENT-TYPE-RTCP:CAPS"></a>NICE_COMPONENT_TYPE_RTCP</p></td>
+<td class="enum_member_description">
+<p>RTCP Component type</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceProxyType"></a><h3>enum NiceProxyType</h3>
+<p>An enum to specify which proxy type to use for relaying.
+Note that the proxies will only be used with TCP TURN relaying.</p>
+<p> See also: <a class="link" href="NiceAgent.html#NiceAgent--proxy-type" title="The “proxy-type” property"><span class="type">“proxy-type”</span></a> </p>
+<div class="refsect3">
+<a name="NiceProxyType.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-PROXY-TYPE-NONE:CAPS"></a>NICE_PROXY_TYPE_NONE</p></td>
+<td class="enum_member_description">
+<p>Do not use a proxy</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-PROXY-TYPE-SOCKS5:CAPS"></a>NICE_PROXY_TYPE_SOCKS5</p></td>
+<td class="enum_member_description">
+<p>Use a SOCKS5 proxy</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-PROXY-TYPE-HTTP:CAPS"></a>NICE_PROXY_TYPE_HTTP</p></td>
+<td class="enum_member_description">
+<p>Use an HTTP proxy</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-PROXY-TYPE-LAST:CAPS"></a>NICE_PROXY_TYPE_LAST</p></td>
+<td class="enum_member_description">
+<p>Dummy last proxy type</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="ix03.html#api-index-0.0.4">0.0.4</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceNominationMode"></a><h3>enum NiceNominationMode</h3>
+<p>An enum to specity the kind of nomination mode to use by
+the agent, as described in RFC 5245. Two modes exists,
+regular and aggressive. They differ by the way the controlling
+agent chooses to put the USE-CANDIDATE attribute in its STUN
+messages. The aggressive mode is supposed to nominate a pair
+faster, than the regular mode, potentially causing the nominated
+pair to change until the connection check completes.</p>
+<div class="refsect3">
+<a name="NiceNominationMode.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-NOMINATION-MODE-REGULAR:CAPS"></a>NICE_NOMINATION_MODE_REGULAR</p></td>
+<td class="enum_member_description">
+<p>Regular nomination mode</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-NOMINATION-MODE-AGGRESSIVE:CAPS"></a>NICE_NOMINATION_MODE_AGGRESSIVE</p></td>
+<td class="enum_member_description">
+<p>Aggressive nomination mode</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="ix14.html#api-index-0.1.15">0.1.15</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceCompatibility"></a><h3>enum NiceCompatibility</h3>
+<p>An enum to specify which compatible specifications the <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> should use.
+Use with <a class="link" href="NiceAgent.html#nice-agent-new" title="nice_agent_new ()"><code class="function">nice_agent_new()</code></a></p>
+<div class="warning">
+<em class="parameter"><code>NICE_COMPATIBILITY_DRAFT19</code></em> is deprecated and should not be used
+in newly-written code. It is kept for compatibility reasons and
+represents the same compatibility as <em class="parameter"><code>NICE_COMPATIBILITY_RFC5245</code></em>
+</div>
+<div class="note"><p>
+ If <em class="parameter"><code>NICE_COMPATIBILITY_RFC5245</code></em> compatibility mode is used for a non-reliable
+ agent, then ICE-UDP will be used with higher priority and ICE-TCP will also
+ be used when the UDP connectivity fails. If it is used with a reliable agent,
+ then ICE-UDP will be used with the TCP-Over-UDP (<a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a>) if ICE-TCP
+ fails and ICE-UDP succeeds.
+ </p></div>
+<div class="refsect3">
+<a name="NiceCompatibility.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-COMPATIBILITY-RFC5245:CAPS"></a>NICE_COMPATIBILITY_RFC5245</p></td>
+<td class="enum_member_description">
+<p>Use compatibility with the RFC5245 ICE-UDP specs
+and RFC6544 ICE-TCP specs</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-COMPATIBILITY-DRAFT19:CAPS"></a>NICE_COMPATIBILITY_DRAFT19</p></td>
+<td class="enum_member_description">
+<p>Use compatibility for ICE Draft 19 specs</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-COMPATIBILITY-GOOGLE:CAPS"></a>NICE_COMPATIBILITY_GOOGLE</p></td>
+<td class="enum_member_description">
+<p>Use compatibility for Google Talk specs</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-COMPATIBILITY-MSN:CAPS"></a>NICE_COMPATIBILITY_MSN</p></td>
+<td class="enum_member_description">
+<p>Use compatibility for MSN Messenger specs</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-COMPATIBILITY-WLM2009:CAPS"></a>NICE_COMPATIBILITY_WLM2009</p></td>
+<td class="enum_member_description">
+<p>Use compatibility with Windows Live Messenger
+2009</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-COMPATIBILITY-OC2007:CAPS"></a>NICE_COMPATIBILITY_OC2007</p></td>
+<td class="enum_member_description">
+<p>Use compatibility with Microsoft Office Communicator 2007</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-COMPATIBILITY-OC2007R2:CAPS"></a>NICE_COMPATIBILITY_OC2007R2</p></td>
+<td class="enum_member_description">
+<p>Use compatibility with Microsoft Office Communicator 2007 R2</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-COMPATIBILITY-LAST:CAPS"></a>NICE_COMPATIBILITY_LAST</p></td>
+<td class="enum_member_description">
+<p>Dummy last compatibility mode</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceInputMessage"></a><h3>NiceInputMessage</h3>
+<pre class="programlisting">typedef struct {
+ GInputVector *buffers;
+ gint n_buffers; /* may be -1 to indicate @buffers is NULL-terminated */
+ NiceAddress *from; /* return location for address of message sender */
+ gsize length; /* sum of the lengths of @buffers */
+} NiceInputMessage;
+</pre>
+<p>Represents a single message received off the network. For reliable
+connections, this is essentially just an array of buffers (specifically,
+<em class="parameter"><code>from</code></em>
+ can be ignored). for non-reliable connections, it represents a single
+packet as received from the OS.</p>
+<p><em class="parameter"><code>n_buffers</code></em>
+ may be -1 to indicate that <em class="parameter"><code>buffers</code></em>
+ is terminated by a
+<a href="/usr/share/gtk-doc/html/gio/GSocket.html#GInputVector"><span class="type">GInputVector</span></a> with a <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS"><code class="literal">NULL</code></a> buffer pointer.</p>
+<p>By providing arrays of <a href="NiceAgent.html#NiceInputMessage"><span class="type">NiceInputMessages</span></a> to functions like
+<a class="link" href="NiceAgent.html#nice-agent-recv-messages" title="nice_agent_recv_messages ()"><code class="function">nice_agent_recv_messages()</code></a>, multiple messages may be received with a single
+call, which is more efficient than making multiple calls in a loop. In this
+manner, <a class="link" href="NiceAgent.html#nice-agent-recv-messages" title="nice_agent_recv_messages ()"><code class="function">nice_agent_recv_messages()</code></a> is analogous to <code class="function">recvmmsg()</code>; and
+<a class="link" href="NiceAgent.html#NiceInputMessage" title="NiceInputMessage"><span class="type">NiceInputMessage</span></a> to struct mmsghdr.</p>
+<div class="refsect3">
+<a name="NiceInputMessage.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="struct_members_name">
+<col class="struct_members_description">
+<col width="200px" class="struct_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="struct_member_name"><p><a href="/usr/share/gtk-doc/html/gio/GSocket.html#GInputVector"><span class="type">GInputVector</span></a> *<em class="structfield"><code><a name="NiceInputMessage.buffers"></a>buffers</code></em>;</p></td>
+<td class="struct_member_description"><p>unowned array of <a href="/usr/share/gtk-doc/html/gio/GSocket.html#GInputVector"><span class="type">GInputVector</span></a> buffers to
+store data in for this message. </p></td>
+<td class="struct_member_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=n_buffers]</span></td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gint"><span class="type">gint</span></a> <em class="structfield"><code><a name="NiceInputMessage.n-buffers"></a>n_buffers</code></em>;</p></td>
+<td class="struct_member_description"><p>number of <a href="/usr/share/gtk-doc/html/gio/GSocket.html#GInputVector"><span class="type">GInputVectors</span></a> in <em class="parameter"><code>buffers</code></em>
+, or -1 to indicate <em class="parameter"><code>buffers</code></em>
+is <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS"><code class="literal">NULL</code></a>-terminated</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> *<em class="structfield"><code><a name="NiceInputMessage.from"></a>from</code></em>;</p></td>
+<td class="struct_member_description"><p>return location to store the address of the peer who
+transmitted the message, or <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS"><code class="literal">NULL</code></a>. </p></td>
+<td class="struct_member_annotations"><span class="annotation">[<acronym title="NULL is OK, both for passing and for returning."><span class="acronym">allow-none</span></acronym>]</span></td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gsize"><span class="type">gsize</span></a> <em class="structfield"><code><a name="NiceInputMessage.length"></a>length</code></em>;</p></td>
+<td class="struct_member_description"><p>total number of valid bytes contiguously stored in <em class="parameter"><code>buffers</code></em>
+</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="ix10.html#api-index-0.1.5">0.1.5</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceOutputMessage"></a><h3>NiceOutputMessage</h3>
+<pre class="programlisting">typedef struct {
+ GOutputVector *buffers;
+ gint n_buffers;
+} NiceOutputMessage;
+</pre>
+<p>Represents a single message to transmit on the network. For
+reliable connections, this is essentially just an array of
+buffer. for non-reliable connections, it represents a single packet
+to send to the OS.</p>
+<p><em class="parameter"><code>n_buffers</code></em>
+ may be -1 to indicate that <em class="parameter"><code>buffers</code></em>
+ is terminated by a
+<a href="/usr/share/gtk-doc/html/gio/GSocket.html#GOutputVector"><span class="type">GOutputVector</span></a> with a <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS"><code class="literal">NULL</code></a> buffer pointer.</p>
+<p>By providing arrays of <a href="NiceAgent.html#NiceOutputMessage"><span class="type">NiceOutputMessages</span></a> to functions like
+<a class="link" href="NiceAgent.html#nice-agent-send-messages-nonblocking" title="nice_agent_send_messages_nonblocking ()"><code class="function">nice_agent_send_messages_nonblocking()</code></a>, multiple messages may be transmitted
+with a single call, which is more efficient than making multiple calls in a
+loop. In this manner, <a class="link" href="NiceAgent.html#nice-agent-send-messages-nonblocking" title="nice_agent_send_messages_nonblocking ()"><code class="function">nice_agent_send_messages_nonblocking()</code></a> is analogous to
+<code class="function">sendmmsg()</code>; and <a class="link" href="NiceAgent.html#NiceOutputMessage" title="NiceOutputMessage"><span class="type">NiceOutputMessage</span></a> to struct mmsghdr.</p>
+<div class="refsect3">
+<a name="NiceOutputMessage.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="struct_members_name">
+<col class="struct_members_description">
+<col width="200px" class="struct_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="struct_member_name"><p><a href="/usr/share/gtk-doc/html/gio/GSocket.html#GOutputVector"><span class="type">GOutputVector</span></a> *<em class="structfield"><code><a name="NiceOutputMessage.buffers"></a>buffers</code></em>;</p></td>
+<td class="struct_member_description"><p>unowned array of <a href="/usr/share/gtk-doc/html/gio/GSocket.html#GOutputVector"><span class="type">GOutputVector</span></a> buffers
+which contain data to transmit for this message. </p></td>
+<td class="struct_member_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=n_buffers]</span></td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gint"><span class="type">gint</span></a> <em class="structfield"><code><a name="NiceOutputMessage.n-buffers"></a>n_buffers</code></em>;</p></td>
+<td class="struct_member_description"><p>number of <a href="/usr/share/gtk-doc/html/gio/GSocket.html#GOutputVector"><span class="type">GOutputVectors</span></a> in <em class="parameter"><code>buffers</code></em>
+, or -1 to indicate <em class="parameter"><code>buffers</code></em>
+is <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS"><code class="literal">NULL</code></a>-terminated</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="ix10.html#api-index-0.1.5">0.1.5</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NICE-AGENT-MAX-REMOTE-CANDIDATES:CAPS"></a><h3>NICE_AGENT_MAX_REMOTE_CANDIDATES</h3>
+<pre class="programlisting">#define NICE_AGENT_MAX_REMOTE_CANDIDATES 25
+</pre>
+<p>A hard limit for the number of remote candidates. This
+limit is enforced to protect against malevolent remote
+clients.</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgentOption"></a><h3>enum NiceAgentOption</h3>
+<p>These are options that can be passed to <a class="link" href="NiceAgent.html#nice-agent-new-full" title="nice_agent_new_full ()"><code class="function">nice_agent_new_full()</code></a>. They set
+various properties on the agent. Not including them sets the property to
+the other value.</p>
+<div class="refsect3">
+<a name="NiceAgentOption.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-AGENT-OPTION-REGULAR-NOMINATION:CAPS"></a>NICE_AGENT_OPTION_REGULAR_NOMINATION</p></td>
+<td class="enum_member_description">
+<p>Enables regular nomination, default
+ is aggrssive mode (see <a class="link" href="NiceAgent.html#NiceNominationMode" title="enum NiceNominationMode"><span class="type">NiceNominationMode</span></a>).</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-AGENT-OPTION-RELIABLE:CAPS"></a>NICE_AGENT_OPTION_RELIABLE</p></td>
+<td class="enum_member_description">
+<p>Enables reliable mode, possibly using PseudoTCP, * see <a class="link" href="NiceAgent.html#nice-agent-new-reliable" title="nice_agent_new_reliable ()"><code class="function">nice_agent_new_reliable()</code></a>.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-AGENT-OPTION-LITE-MODE:CAPS"></a>NICE_AGENT_OPTION_LITE_MODE</p></td>
+<td class="enum_member_description">
+<p>Enable lite mode</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-AGENT-OPTION-ICE-TRICKLE:CAPS"></a>NICE_AGENT_OPTION_ICE_TRICKLE</p></td>
+<td class="enum_member_description">
+<p>Enable ICE trickle mode</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-AGENT-OPTION-SUPPORT-RENOMINATION:CAPS"></a>NICE_AGENT_OPTION_SUPPORT_RENOMINATION</p></td>
+<td class="enum_member_description">
+<p>Enable renomination triggered by NOMINATION STUN attribute
+proposed here: https://tools.ietf.org/html/draft-thatcher-ice-renomination-00</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="ix14.html#api-index-0.1.15">0.1.15</a></p>
+</div>
+</div>
+<div class="refsect1">
+<a name="NiceAgent.property-details"></a><h2>Property Details</h2>
+<div class="refsect2">
+<a name="NiceAgent--bytestream-tcp"></a><h3>The <code class="literal">“bytestream-tcp”</code> property</h3>
+<pre class="programlisting"> “bytestream-tcp” <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="type">gboolean</span></a></pre>
+<p>This property defines whether receive/send over a TCP or pseudo-TCP, in
+reliable mode, are considered as packetized or as bytestream.
+In unreliable mode, every send/recv is considered as packetized, and
+this property is ignored and cannot be set.</p>
+<p>
+In reliable mode, this property will always return <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> in the
+<a class="link" href="NiceAgent.html#NICE-COMPATIBILITY-GOOGLE:CAPS"><code class="literal">NICE_COMPATIBILITY_GOOGLE</code></a> compatibility mode.
+</p>
+<p>If the property is <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a>, the stream is considered in bytestream mode
+and data can be read with any receive size. If the property is <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a>, then
+the stream is considred packetized and each receive will return one packet
+of the same size as what was sent from the peer. If in packetized mode,
+then doing a receive with a size smaller than the packet, will cause the
+remaining bytes in the packet to be dropped, breaking the reliability
+of the stream.</p>
+<p>
+This property is currently read-only, and will become read/write once
+bytestream mode will be supported.
+</p>
+<p>Flags: Read</p>
+<p>Default value: FALSE</p>
+<p class="since">Since: <a class="link" href="ix12.html#api-index-0.1.8">0.1.8</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgent--compatibility"></a><h3>The <code class="literal">“compatibility”</code> property</h3>
+<pre class="programlisting"> “compatibility” <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a></pre>
+<p>The Nice agent can work in various compatibility modes depending on
+what the application/peer needs.</p>
+<p> See also: <a class="link" href="NiceAgent.html#NiceCompatibility" title="enum NiceCompatibility"><span class="type">NiceCompatibility</span></a></p>
+<p>Flags: Read / Write / Construct Only</p>
+<p>Allowed values: <= 5</p>
+<p>Default value: 0</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgent--controlling-mode"></a><h3>The <code class="literal">“controlling-mode”</code> property</h3>
+<pre class="programlisting"> “controlling-mode” <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="type">gboolean</span></a></pre>
+<p>Whether the agent has the controlling role. This property should
+be modified before gathering candidates, any modification occuring
+later will be hold until ICE is restarted.</p>
+<p>Flags: Read / Write</p>
+<p>Default value: FALSE</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgent--force-relay"></a><h3>The <code class="literal">“force-relay”</code> property</h3>
+<pre class="programlisting"> “force-relay” <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="type">gboolean</span></a></pre>
+<p>Force all traffic to go through a relay for added privacy, this
+allows hiding the local IP address. When this is enabled, so
+local candidates are available before relay servers have been set
+with <a class="link" href="NiceAgent.html#nice-agent-set-relay-info" title="nice_agent_set_relay_info ()"><code class="function">nice_agent_set_relay_info()</code></a>.</p>
+<p>Flags: Read / Write</p>
+<p>Default value: FALSE</p>
+<p class="since">Since: <a class="link" href="ix13.html#api-index-0.1.14">0.1.14</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgent--full-mode"></a><h3>The <code class="literal">“full-mode”</code> property</h3>
+<pre class="programlisting"> “full-mode” <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="type">gboolean</span></a></pre>
+<p>Whether agent runs in ICE full mode.</p>
+<p>Flags: Read / Write / Construct Only</p>
+<p>Default value: TRUE</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgent--ice-tcp"></a><h3>The <code class="literal">“ice-tcp”</code> property</h3>
+<pre class="programlisting"> “ice-tcp” <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="type">gboolean</span></a></pre>
+<p>Whether the agent should use ICE-TCP when gathering candidates.
+If the option is disabled, no TCP candidates will be generated. If the
+agent is in reliable mode, then pseudotcp will need to be used over UDP
+candidates.</p>
+<p>
+This option should be set before gathering candidates and should not be
+modified afterwards.
+</p>
+<p>The <a class="link" href="NiceAgent.html#NiceAgent--ice-tcp" title="The “ice-tcp” property"><span class="type">“ice-tcp”</span></a> property can be set at the same time as the
+<a class="link" href="NiceAgent.html#NiceAgent--ice-udp" title="The “ice-udp” property"><span class="type">“ice-udp”</span></a> property, but both cannot be unset at the same time.
+If <a class="link" href="NiceAgent.html#NiceAgent--ice-udp" title="The “ice-udp” property"><span class="type">“ice-udp”</span></a> is set to <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a>, then this property cannot be set
+to <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> as well.</p>
+<div class="note"><p>
+ ICE-TCP is only supported for <a class="link" href="NiceAgent.html#NICE-COMPATIBILITY-RFC5245:CAPS"><code class="literal">NICE_COMPATIBILITY_RFC5245</code></a>,
+ <a class="link" href="NiceAgent.html#NICE-COMPATIBILITY-OC2007:CAPS"><code class="literal">NICE_COMPATIBILITY_OC2007</code></a> and <a class="link" href="NiceAgent.html#NICE-COMPATIBILITY-OC2007R2:CAPS"><code class="literal">NICE_COMPATIBILITY_OC2007R2</code></a> compatibility
+ modes.
+ </p></div>
+<p>Flags: Read / Write</p>
+<p>Default value: TRUE</p>
+<p class="since">Since: <a class="link" href="ix12.html#api-index-0.1.8">0.1.8</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgent--ice-trickle"></a><h3>The <code class="literal">“ice-trickle”</code> property</h3>
+<pre class="programlisting"> “ice-trickle” <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="type">gboolean</span></a></pre>
+<p>Whether to perform Trickle ICE as per draft-ietf-ice-trickle-ice-21.
+When <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a>, the agent will postpone changing a component state to
+<a class="link" href="NiceAgent.html#NICE-COMPONENT-STATE-FAILED:CAPS"><code class="literal">NICE_COMPONENT_STATE_FAILED</code></a> until <a class="link" href="NiceAgent.html#nice-agent-peer-candidate-gathering-done" title="nice_agent_peer_candidate_gathering_done ()"><code class="function">nice_agent_peer_candidate_gathering_done()</code></a>
+has been called with the ID of the component's stream.</p>
+<p>Flags: Read / Write</p>
+<p>Default value: FALSE</p>
+<p class="since">Since: <a class="link" href="ix15.html#api-index-0.1.16">0.1.16</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgent--ice-udp"></a><h3>The <code class="literal">“ice-udp”</code> property</h3>
+<pre class="programlisting"> “ice-udp” <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="type">gboolean</span></a></pre>
+<p>Whether the agent should use ICE-UDP when gathering candidates.
+If the option is disabled, no UDP candidates will be generated. If the
+agent is in reliable mode, then pseudotcp will not be used since pseudotcp
+works on top of UDP candidates.</p>
+<p>
+This option should be set before gathering candidates and should not be
+modified afterwards.
+</p>
+<p>The <a class="link" href="NiceAgent.html#NiceAgent--ice-udp" title="The “ice-udp” property"><span class="type">“ice-udp”</span></a> property can be set at the same time as the
+<a class="link" href="NiceAgent.html#NiceAgent--ice-tcp" title="The “ice-tcp” property"><span class="type">“ice-tcp”</span></a> property, but both cannot be unset at the same time.
+If <a class="link" href="NiceAgent.html#NiceAgent--ice-tcp" title="The “ice-tcp” property"><span class="type">“ice-tcp”</span></a> is set to <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a>, then this property cannot be set
+to <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> as well.</p>
+<p>Flags: Read / Write</p>
+<p>Default value: TRUE</p>
+<p class="since">Since: <a class="link" href="ix12.html#api-index-0.1.8">0.1.8</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgent--keepalive-conncheck"></a><h3>The <code class="literal">“keepalive-conncheck”</code> property</h3>
+<pre class="programlisting"> “keepalive-conncheck” <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="type">gboolean</span></a></pre>
+<p>Use binding requests as keepalives instead of binding
+indications. This means that the keepalives may time out which
+will change the component state to <a class="link" href="NiceAgent.html#NICE-COMPONENT-STATE-FAILED:CAPS"><code class="literal">NICE_COMPONENT_STATE_FAILED</code></a>.</p>
+<p>Enabing this is a slight violation of RFC 5245 section 10 which
+recommends using Binding Indications for keepalives.</p>
+<p>This is always enabled if the compatibility mode is
+<a class="link" href="NiceAgent.html#NICE-COMPATIBILITY-GOOGLE:CAPS"><code class="literal">NICE_COMPATIBILITY_GOOGLE</code></a>.</p>
+<p>Flags: Read / Write</p>
+<p>Default value: FALSE</p>
+<p class="since">Since: <a class="link" href="ix12.html#api-index-0.1.8">0.1.8</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgent--main-context"></a><h3>The <code class="literal">“main-context”</code> property</h3>
+<pre class="programlisting"> “main-context” <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gpointer"><span class="type">gpointer</span></a></pre>
+<p>A GLib main context is needed for all timeouts used by libnice.
+This is a property being set by the <a class="link" href="NiceAgent.html#nice-agent-new" title="nice_agent_new ()"><code class="function">nice_agent_new()</code></a> call.</p>
+<p>Flags: Read / Write / Construct Only</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgent--max-connectivity-checks"></a><h3>The <code class="literal">“max-connectivity-checks”</code> property</h3>
+<pre class="programlisting"> “max-connectivity-checks” <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a></pre>
+<p>Upper limit for the total number of connectivity checks performed.</p>
+<p>Flags: Read / Write</p>
+<p>Default value: 0</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgent--nomination-mode"></a><h3>The <code class="literal">“nomination-mode”</code> property</h3>
+<pre class="programlisting"> “nomination-mode” <a class="link" href="NiceAgent.html#NiceNominationMode" title="enum NiceNominationMode"><span class="type">NiceNominationMode</span></a></pre>
+<p>The nomination mode used in the ICE specification for describing
+the selection of valid pairs to be used upstream.</p>
+<p> See also: <a class="link" href="NiceAgent.html#NiceNominationMode" title="enum NiceNominationMode"><span class="type">NiceNominationMode</span></a> </p>
+<p>Flags: Read / Write / Construct Only</p>
+<p>Default value: NICE_NOMINATION_MODE_AGGRESSIVE</p>
+<p class="since">Since: <a class="link" href="ix14.html#api-index-0.1.15">0.1.15</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgent--proxy-ip"></a><h3>The <code class="literal">“proxy-ip”</code> property</h3>
+<pre class="programlisting"> “proxy-ip” <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *</pre>
+<p>The proxy server IP used to bypass a proxy firewall</p>
+<p>Flags: Read / Write</p>
+<p>Default value: NULL</p>
+<p class="since">Since: <a class="link" href="ix03.html#api-index-0.0.4">0.0.4</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgent--proxy-password"></a><h3>The <code class="literal">“proxy-password”</code> property</h3>
+<pre class="programlisting"> “proxy-password” <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *</pre>
+<p>The password used to authenticate with the proxy</p>
+<p>Flags: Read / Write</p>
+<p>Default value: NULL</p>
+<p class="since">Since: <a class="link" href="ix03.html#api-index-0.0.4">0.0.4</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgent--proxy-port"></a><h3>The <code class="literal">“proxy-port”</code> property</h3>
+<pre class="programlisting"> “proxy-port” <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a></pre>
+<p>The proxy server port used to bypass a proxy firewall</p>
+<p>Flags: Read / Write</p>
+<p>Allowed values: [1,65536]</p>
+<p>Default value: 1</p>
+<p class="since">Since: <a class="link" href="ix03.html#api-index-0.0.4">0.0.4</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgent--proxy-type"></a><h3>The <code class="literal">“proxy-type”</code> property</h3>
+<pre class="programlisting"> “proxy-type” <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a></pre>
+<p>The type of proxy set in the proxy-ip property</p>
+<p>Flags: Read / Write</p>
+<p>Allowed values: <= 2</p>
+<p>Default value: 0</p>
+<p class="since">Since: <a class="link" href="ix03.html#api-index-0.0.4">0.0.4</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgent--proxy-username"></a><h3>The <code class="literal">“proxy-username”</code> property</h3>
+<pre class="programlisting"> “proxy-username” <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *</pre>
+<p>The username used to authenticate with the proxy</p>
+<p>Flags: Read / Write</p>
+<p>Default value: NULL</p>
+<p class="since">Since: <a class="link" href="ix03.html#api-index-0.0.4">0.0.4</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgent--reliable"></a><h3>The <code class="literal">“reliable”</code> property</h3>
+<pre class="programlisting"> “reliable” <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="type">gboolean</span></a></pre>
+<p>Whether the agent is providing a reliable transport of messages (through
+ICE-TCP or PseudoTCP over ICE-UDP)</p>
+<p>Flags: Read / Write / Construct Only</p>
+<p>Default value: FALSE</p>
+<p class="since">Since: <a class="link" href="ix08.html#api-index-0.0.11">0.0.11</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgent--stun-initial-timeout"></a><h3>The <code class="literal">“stun-initial-timeout”</code> property</h3>
+<pre class="programlisting"> “stun-initial-timeout” <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a></pre>
+<p>The initial timeout (msecs) of the STUN binding requests
+used in the gathering stage, to find our local candidates.
+This property is described as 'RTO' in the RFC 5389 and RFC 5245.
+This timeout is doubled for each retransmission, until
+<a class="link" href="NiceAgent.html#NiceAgent--stun-max-retransmissions" title="The “stun-max-retransmissions” property"><span class="type">“stun-max-retransmissions”</span></a> have been done,
+with an exception for the last restransmission, where the timeout is
+divided by two instead (RFC 5389 indicates that a customisable
+multiplier 'Rm' to 'RTO' should be used).</p>
+<p>Flags: Read / Write / Construct</p>
+<p>Allowed values: [20,9999]</p>
+<p>Default value: 200</p>
+<p class="since">Since: <a class="link" href="ix14.html#api-index-0.1.15">0.1.15</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgent--stun-max-retransmissions"></a><h3>The <code class="literal">“stun-max-retransmissions”</code> property</h3>
+<pre class="programlisting"> “stun-max-retransmissions” <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a></pre>
+<p>The maximum number of retransmissions of the STUN binding requests
+used in the gathering stage, to find our local candidates, and used
+in the connection check stage, to test the validity of each
+constructed pair. This property is described as 'Rc' in the RFC
+5389, with a default value of 7. The timeout of each STUN request
+is doubled for each retransmission, so the choice of this value has
+a direct impact on the time needed to move from the CONNECTED state
+to the READY state, and on the time needed to complete the GATHERING
+state.</p>
+<p>Flags: Read / Write / Construct</p>
+<p>Allowed values: [1,99]</p>
+<p>Default value: 7</p>
+<p class="since">Since: <a class="link" href="ix14.html#api-index-0.1.15">0.1.15</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgent--stun-pacing-timer"></a><h3>The <code class="literal">“stun-pacing-timer”</code> property</h3>
+<pre class="programlisting"> “stun-pacing-timer” <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a></pre>
+<p>Timer 'Ta' (msecs) used in the IETF ICE specification for pacing candidate gathering and sending of connectivity checks.</p>
+<p>Flags: Read / Write / Construct</p>
+<p>Allowed values: >= 1</p>
+<p>Default value: 20</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgent--stun-reliable-timeout"></a><h3>The <code class="literal">“stun-reliable-timeout”</code> property</h3>
+<pre class="programlisting"> “stun-reliable-timeout” <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a></pre>
+<p>The initial timeout of the STUN binding requests used
+for a reliable timer.</p>
+<p>Flags: Read / Write / Construct</p>
+<p>Allowed values: [20,99999]</p>
+<p>Default value: 7900</p>
+<p class="since">Since: <a class="link" href="ix14.html#api-index-0.1.15">0.1.15</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgent--stun-server"></a><h3>The <code class="literal">“stun-server”</code> property</h3>
+<pre class="programlisting"> “stun-server” <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *</pre>
+<p>The IP address (not the hostname) of the STUN server to use.</p>
+<p>Flags: Read / Write</p>
+<p>Default value: NULL</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgent--stun-server-port"></a><h3>The <code class="literal">“stun-server-port”</code> property</h3>
+<pre class="programlisting"> “stun-server-port” <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a></pre>
+<p>Port of the STUN server used to gather server-reflexive candidates.</p>
+<p>Flags: Read / Write</p>
+<p>Allowed values: [1,65536]</p>
+<p>Default value: 1</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgent--support-renomination"></a><h3>The <code class="literal">“support-renomination”</code> property</h3>
+<pre class="programlisting"> “support-renomination” <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="type">gboolean</span></a></pre>
+<p>Support RENOMINATION STUN attribute proposed here:
+https://tools.ietf.org/html/draft-thatcher-ice-renomination-00 As
+soon as RENOMINATION attribute is received from remote
+candidate's address, corresponding candidates pair gets
+selected. This is specific to Google Chrome/libWebRTC.</p>
+<p>Flags: Read / Write</p>
+<p>Default value: FALSE</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgent--upnp"></a><h3>The <code class="literal">“upnp”</code> property</h3>
+<pre class="programlisting"> “upnp” <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="type">gboolean</span></a></pre>
+<p>Whether the agent should use UPnP to open a port in the router and
+get the external IP</p>
+<p>Flags: Read / Write / Construct</p>
+<p>Default value: TRUE</p>
+<p class="since">Since: <a class="link" href="ix05.html#api-index-0.0.7">0.0.7</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgent--upnp-timeout"></a><h3>The <code class="literal">“upnp-timeout”</code> property</h3>
+<pre class="programlisting"> “upnp-timeout” <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a></pre>
+<p>The maximum amount of time (in milliseconds) to wait for UPnP discovery to
+finish before signaling the <a class="link" href="NiceAgent.html#NiceAgent-candidate-gathering-done" title="The “candidate-gathering-done” signal"><span class="type">“candidate-gathering-done”</span></a> signal</p>
+<p>Flags: Read / Write / Construct</p>
+<p>Allowed values: [100,60000]</p>
+<p>Default value: 200</p>
+<p class="since">Since: <a class="link" href="ix05.html#api-index-0.0.7">0.0.7</a></p>
+</div>
+</div>
+<div class="refsect1">
+<a name="NiceAgent.signal-details"></a><h2>Signal Details</h2>
+<div class="refsect2">
+<a name="NiceAgent-candidate-gathering-done"></a><h3>The <code class="literal">“candidate-gathering-done”</code> signal</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+user_function (<a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent,
+ <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id,
+ <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gpointer"><span class="type">gpointer</span></a> user_data)</pre>
+<p>This signal is fired whenever a stream has finished gathering its
+candidates after a call to <a class="link" href="NiceAgent.html#nice-agent-gather-candidates" title="nice_agent_gather_candidates ()"><code class="function">nice_agent_gather_candidates()</code></a></p>
+<div class="refsect3">
+<a name="NiceAgent-candidate-gathering-done.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The ID of the stream</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>user_data</p></td>
+<td class="parameter_description"><p>user data set when the signal handler was connected.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p>Flags: <a href="/usr/share/gtk-doc/html/gobject/gobject-Signals.html#G-SIGNAL-RUN-LAST:CAPS">Run Last</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgent-component-state-changed"></a><h3>The <code class="literal">“component-state-changed”</code> signal</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+user_function (<a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent,
+ <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id,
+ <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> component_id,
+ <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> state,
+ <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gpointer"><span class="type">gpointer</span></a> user_data)</pre>
+<p>This signal is fired whenever a component’s state changes. There are many
+valid state transitions.</p>
+<p><span class="inlinemediaobject"><img src="states.png" alt="State transition diagram"></span></p>
+<div class="refsect3">
+<a name="NiceAgent-component-state-changed.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The ID of the stream</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>component_id</p></td>
+<td class="parameter_description"><p>The ID of the component</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>state</p></td>
+<td class="parameter_description"><p>The new <a class="link" href="NiceAgent.html#NiceComponentState" title="enum NiceComponentState"><span class="type">NiceComponentState</span></a> of the component</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>user_data</p></td>
+<td class="parameter_description"><p>user data set when the signal handler was connected.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p>Flags: <a href="/usr/share/gtk-doc/html/gobject/gobject-Signals.html#G-SIGNAL-RUN-LAST:CAPS">Run Last</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgent-initial-binding-request-received"></a><h3>The <code class="literal">“initial-binding-request-received”</code> signal</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+user_function (<a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent,
+ <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id,
+ <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gpointer"><span class="type">gpointer</span></a> user_data)</pre>
+<p>This signal is fired when we received our first binding request from
+the peer.</p>
+<div class="refsect3">
+<a name="NiceAgent-initial-binding-request-received.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The ID of the stream</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>user_data</p></td>
+<td class="parameter_description"><p>user data set when the signal handler was connected.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p>Flags: <a href="/usr/share/gtk-doc/html/gobject/gobject-Signals.html#G-SIGNAL-RUN-LAST:CAPS">Run Last</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgent-new-candidate"></a><h3>The <code class="literal">“new-candidate”</code> signal</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+user_function (<a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent,
+ <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id,
+ <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> component_id,
+ <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *foundation,
+ <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gpointer"><span class="type">gpointer</span></a> user_data)</pre>
+<p>This signal is fired when the agent discovers a new local candidate.
+When this signal is emitted, a matching <a class="link" href="NiceAgent.html#NiceAgent-new-candidate-full" title="The “new-candidate-full” signal"><span class="type">“new-candidate-full”</span></a> is
+also emitted with the candidate.</p>
+<p>See also: <a class="link" href="NiceAgent.html#NiceAgent-candidate-gathering-done" title="The “candidate-gathering-done” signal"><span class="type">“candidate-gathering-done”</span></a>,
+<a class="link" href="NiceAgent.html#NiceAgent-new-candidate-full" title="The “new-candidate-full” signal"><span class="type">“new-candidate-full”</span></a></p>
+<div class="warning">
+<p><code class="literal">NiceAgent::new-candidate</code> has been deprecated since version 0.1.8 and should not be used in newly-written code.</p>
+<p>Use <a class="link" href="NiceAgent.html#NiceAgent-new-candidate-full" title="The “new-candidate-full” signal"><span class="type">“new-candidate-full”</span></a></p>
+</div>
+<div class="refsect3">
+<a name="NiceAgent-new-candidate.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The ID of the stream</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>component_id</p></td>
+<td class="parameter_description"><p>The ID of the component</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>foundation</p></td>
+<td class="parameter_description"><p>The foundation of the new candidate</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>user_data</p></td>
+<td class="parameter_description"><p>user data set when the signal handler was connected.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p>Flags: <a href="/usr/share/gtk-doc/html/gobject/gobject-Signals.html#G-SIGNAL-RUN-LAST:CAPS">Run Last</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgent-new-candidate-full"></a><h3>The <code class="literal">“new-candidate-full”</code> signal</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+user_function (<a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent,
+ <a class="link" href="NiceCandidate.html" title="NiceCandidate"><span class="type">NiceCandidate</span></a> *candidate,
+ <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gpointer"><span class="type">gpointer</span></a> user_data)</pre>
+<p>This signal is fired when the agent discovers a new local candidate.
+When this signal is emitted, a matching <a class="link" href="NiceAgent.html#NiceAgent-new-candidate" title="The “new-candidate” signal"><span class="type">“new-candidate”</span></a> is
+also emitted with the candidate's foundation.</p>
+<p>See also: <a class="link" href="NiceAgent.html#NiceAgent-candidate-gathering-done" title="The “candidate-gathering-done” signal"><span class="type">“candidate-gathering-done”</span></a>,
+<a class="link" href="NiceAgent.html#NiceAgent-new-candidate" title="The “new-candidate” signal"><span class="type">“new-candidate”</span></a></p>
+<div class="refsect3">
+<a name="NiceAgent-new-candidate-full.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>candidate</p></td>
+<td class="parameter_description"><p>The new <a class="link" href="NiceCandidate.html" title="NiceCandidate"><span class="type">NiceCandidate</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>user_data</p></td>
+<td class="parameter_description"><p>user data set when the signal handler was connected.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p>Flags: <a href="/usr/share/gtk-doc/html/gobject/gobject-Signals.html#G-SIGNAL-RUN-LAST:CAPS">Run Last</a></p>
+<p class="since">Since: <a class="link" href="ix12.html#api-index-0.1.8">0.1.8</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgent-new-remote-candidate"></a><h3>The <code class="literal">“new-remote-candidate”</code> signal</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+user_function (<a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent,
+ <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id,
+ <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> component_id,
+ <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *foundation,
+ <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gpointer"><span class="type">gpointer</span></a> user_data)</pre>
+<p>This signal is fired when the agent discovers a new remote
+candidate. This can happen with peer reflexive candidates. When
+this signal is emitted, a matching
+<a class="link" href="NiceAgent.html#NiceAgent-new-remote-candidate-full" title="The “new-remote-candidate-full” signal"><span class="type">“new-remote-candidate-full”</span></a> is also emitted with the
+candidate.</p>
+<p>See also: <a class="link" href="NiceAgent.html#NiceAgent-new-remote-candidate-full" title="The “new-remote-candidate-full” signal"><span class="type">“new-remote-candidate-full”</span></a></p>
+<div class="warning">
+<p><code class="literal">NiceAgent::new-remote-candidate</code> has been deprecated since version 0.1.8 and should not be used in newly-written code.</p>
+<p>Use <a class="link" href="NiceAgent.html#NiceAgent-new-remote-candidate-full" title="The “new-remote-candidate-full” signal"><span class="type">“new-remote-candidate-full”</span></a></p>
+</div>
+<div class="refsect3">
+<a name="NiceAgent-new-remote-candidate.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The ID of the stream</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>component_id</p></td>
+<td class="parameter_description"><p>The ID of the component</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>foundation</p></td>
+<td class="parameter_description"><p>The foundation of the new candidate</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>user_data</p></td>
+<td class="parameter_description"><p>user data set when the signal handler was connected.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p>Flags: <a href="/usr/share/gtk-doc/html/gobject/gobject-Signals.html#G-SIGNAL-RUN-LAST:CAPS">Run Last</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgent-new-remote-candidate-full"></a><h3>The <code class="literal">“new-remote-candidate-full”</code> signal</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+user_function (<a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent,
+ <a class="link" href="NiceCandidate.html" title="NiceCandidate"><span class="type">NiceCandidate</span></a> *candidate,
+ <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gpointer"><span class="type">gpointer</span></a> user_data)</pre>
+<p>This signal is fired when the agent discovers a new remote candidate.
+This can happen with peer reflexive candidates.
+When this signal is emitted, a matching <a class="link" href="NiceAgent.html#NiceAgent-new-remote-candidate" title="The “new-remote-candidate” signal"><span class="type">“new-remote-candidate”</span></a> is
+also emitted with the candidate's foundation.</p>
+<p>See also: <a class="link" href="NiceAgent.html#NiceAgent-new-remote-candidate" title="The “new-remote-candidate” signal"><span class="type">“new-remote-candidate”</span></a></p>
+<div class="refsect3">
+<a name="NiceAgent-new-remote-candidate-full.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>candidate</p></td>
+<td class="parameter_description"><p>The new <a class="link" href="NiceCandidate.html" title="NiceCandidate"><span class="type">NiceCandidate</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>user_data</p></td>
+<td class="parameter_description"><p>user data set when the signal handler was connected.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p>Flags: <a href="/usr/share/gtk-doc/html/gobject/gobject-Signals.html#G-SIGNAL-RUN-LAST:CAPS">Run Last</a></p>
+<p class="since">Since: <a class="link" href="ix12.html#api-index-0.1.8">0.1.8</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgent-new-selected-pair"></a><h3>The <code class="literal">“new-selected-pair”</code> signal</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+user_function (<a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent,
+ <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id,
+ <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> component_id,
+ <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *lfoundation,
+ <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *rfoundation,
+ <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gpointer"><span class="type">gpointer</span></a> user_data)</pre>
+<p>This signal is fired once a candidate pair is selected for data
+transfer for a stream's component This is emitted along with
+<a class="link" href="NiceAgent.html#NiceAgent-new-selected-pair-full" title="The “new-selected-pair-full” signal"><span class="type">“new-selected-pair-full”</span></a> which has the whole candidate,
+the Foundation of a Candidate is not a unique identifier.</p>
+<p>See also: <a class="link" href="NiceAgent.html#NiceAgent-new-selected-pair-full" title="The “new-selected-pair-full” signal"><span class="type">“new-selected-pair-full”</span></a></p>
+<div class="warning">
+<p><code class="literal">NiceAgent::new-selected-pair</code> has been deprecated since version 0.1.8 and should not be used in newly-written code.</p>
+<p>Use <a class="link" href="NiceAgent.html#NiceAgent-new-selected-pair-full" title="The “new-selected-pair-full” signal"><span class="type">“new-selected-pair-full”</span></a></p>
+</div>
+<div class="refsect3">
+<a name="NiceAgent-new-selected-pair.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The ID of the stream</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>component_id</p></td>
+<td class="parameter_description"><p>The ID of the component</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>lfoundation</p></td>
+<td class="parameter_description"><p>The local foundation of the selected candidate pair</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>rfoundation</p></td>
+<td class="parameter_description"><p>The remote foundation of the selected candidate pair</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>user_data</p></td>
+<td class="parameter_description"><p>user data set when the signal handler was connected.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p>Flags: <a href="/usr/share/gtk-doc/html/gobject/gobject-Signals.html#G-SIGNAL-RUN-LAST:CAPS">Run Last</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgent-new-selected-pair-full"></a><h3>The <code class="literal">“new-selected-pair-full”</code> signal</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+user_function (<a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent,
+ <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id,
+ <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> component_id,
+ <a class="link" href="NiceCandidate.html" title="NiceCandidate"><span class="type">NiceCandidate</span></a> *lcandidate,
+ <a class="link" href="NiceCandidate.html" title="NiceCandidate"><span class="type">NiceCandidate</span></a> *rcandidate,
+ <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gpointer"><span class="type">gpointer</span></a> user_data)</pre>
+<p>This signal is fired once a candidate pair is selected for data
+transfer for a stream's component. This is emitted along with
+<a class="link" href="NiceAgent.html#NiceAgent-new-selected-pair" title="The “new-selected-pair” signal"><span class="type">“new-selected-pair”</span></a>.</p>
+<p>See also: <a class="link" href="NiceAgent.html#NiceAgent-new-selected-pair" title="The “new-selected-pair” signal"><span class="type">“new-selected-pair”</span></a></p>
+<div class="refsect3">
+<a name="NiceAgent-new-selected-pair-full.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The ID of the stream</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>component_id</p></td>
+<td class="parameter_description"><p>The ID of the component</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>lcandidate</p></td>
+<td class="parameter_description"><p>The local <a class="link" href="NiceCandidate.html" title="NiceCandidate"><span class="type">NiceCandidate</span></a> of the selected candidate pair</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>rcandidate</p></td>
+<td class="parameter_description"><p>The remote <a class="link" href="NiceCandidate.html" title="NiceCandidate"><span class="type">NiceCandidate</span></a> of the selected candidate pair</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>user_data</p></td>
+<td class="parameter_description"><p>user data set when the signal handler was connected.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p>Flags: <a href="/usr/share/gtk-doc/html/gobject/gobject-Signals.html#G-SIGNAL-RUN-LAST:CAPS">Run Last</a></p>
+<p class="since">Since: <a class="link" href="ix12.html#api-index-0.1.8">0.1.8</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgent-reliable-transport-writable"></a><h3>The <code class="literal">“reliable-transport-writable”</code> signal</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+user_function (<a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent,
+ <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> stream_id,
+ <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> component_id,
+ <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gpointer"><span class="type">gpointer</span></a> user_data)</pre>
+<p>This signal is fired on the reliable <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> when the underlying reliable
+transport becomes writable.
+This signal is only emitted when the <a class="link" href="NiceAgent.html#nice-agent-send" title="nice_agent_send ()"><code class="function">nice_agent_send()</code></a> function returns less
+bytes than requested to send (or -1) and once when the connection
+is established.</p>
+<div class="refsect3">
+<a name="NiceAgent-reliable-transport-writable.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_id</p></td>
+<td class="parameter_description"><p>The ID of the stream</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>component_id</p></td>
+<td class="parameter_description"><p>The ID of the component</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>user_data</p></td>
+<td class="parameter_description"><p>user data set when the signal handler was connected.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p>Flags: <a href="/usr/share/gtk-doc/html/gobject/gobject-Signals.html#G-SIGNAL-RUN-LAST:CAPS">Run Last</a></p>
+<p class="since">Since: <a class="link" href="ix08.html#api-index-0.0.11">0.0.11</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceAgent-streams-removed"></a><h3>The <code class="literal">“streams-removed”</code> signal</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+user_function (<a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> *agent,
+ <span class="type">_NiceAgentStreamIds</span> *stream_ids,
+ <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gpointer"><span class="type">gpointer</span></a> user_data)</pre>
+<p>This signal is fired whenever one or more streams are removed from the
+<em class="parameter"><code>agent</code></em>
+.</p>
+<div class="refsect3">
+<a name="NiceAgent-streams-removed.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a> object</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>stream_ids</p></td>
+<td class="parameter_description"><p>An array of
+unsigned integer stream IDs, ending with a 0 ID. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> zero-terminated=1][<acronym title="Generics and defining elements of containers and arrays."><span class="acronym">element-type</span></acronym> uint]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>user_data</p></td>
+<td class="parameter_description"><p>user data set when the signal handler was connected.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p>Flags: <a href="/usr/share/gtk-doc/html/gobject/gobject-Signals.html#G-SIGNAL-RUN-LAST:CAPS">Run Last</a></p>
+<p class="since">Since: <a class="link" href="ix10.html#api-index-0.1.5">0.1.5</a></p>
+</div>
+</div>
+<div class="refsect1">
+<a name="NiceAgent.see-also"></a><h2>See Also</h2>
+<p><a class="link" href="NiceCandidate.html" title="NiceCandidate"><span class="type">NiceCandidate</span></a>, <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a></p>
+</div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.29</div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>NiceCandidate: libnice Reference Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets Vsnapshot">
+<link rel="home" href="index.html" title="libnice Reference Manual">
+<link rel="up" href="ch01.html" title="">
+<link rel="prev" href="libnice-NiceAddress.html" title="NiceAddress">
+<link rel="next" href="ch02.html" title="Libnice helper functions">
+<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts">
+<a href="#" class="shortcut">Top</a><span id="nav_description"> <span class="dim">|</span>
+ <a href="#NiceCandidate.description" class="shortcut">Description</a></span><span id="nav_hierarchy"> <span class="dim">|</span>
+ <a href="#NiceCandidate.object-hierarchy" class="shortcut">Object Hierarchy</a></span>
+</td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="ch01.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="libnice-NiceAddress.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="ch02.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="refentry">
+<a name="NiceCandidate"></a><div class="titlepage"></div>
+<div class="refnamediv"><table width="100%"><tr>
+<td valign="top">
+<h2><span class="refentrytitle"><a name="NiceCandidate.top_of_page"></a>NiceCandidate</span></h2>
+<p>NiceCandidate — ICE candidate representation</p>
+</td>
+<td class="gallery_image" valign="top" align="right"></td>
+</tr></table></div>
+<div class="refsect1">
+<a name="NiceCandidate.stability-level"></a><h2>Stability Level</h2>
+<acronym title="The intention of a Stable interface is to enable arbitrary third parties to
+develop applications to these interfaces, release them, and have confidence that
+they will run on all minor releases of the product (after the one in which the
+interface was introduced, and within the same major release). Even at a major
+release, incompatible changes are expected to be rare, and to have strong
+justifications.
+"><span class="acronym">Stable</span></acronym>, unless otherwise indicated
+</div>
+<div class="refsect1">
+<a name="NiceCandidate.functions"></a><h2>Functions</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="functions_return">
+<col class="functions_name">
+</colgroup>
+<tbody>
+<tr>
+<td class="function_type">
+<a class="link" href="NiceCandidate.html" title="NiceCandidate"><span class="returnvalue">NiceCandidate</span></a> *
+</td>
+<td class="function_name">
+<a class="link" href="NiceCandidate.html#nice-candidate-new" title="nice_candidate_new ()">nice_candidate_new</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="NiceCandidate.html#nice-candidate-free" title="nice_candidate_free ()">nice_candidate_free</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="NiceCandidate.html" title="NiceCandidate"><span class="returnvalue">NiceCandidate</span></a> *
+</td>
+<td class="function_name">
+<a class="link" href="NiceCandidate.html#nice-candidate-copy" title="nice_candidate_copy ()">nice_candidate_copy</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="NiceCandidate.html#nice-candidate-equal-target" title="nice_candidate_equal_target ()">nice_candidate_equal_target</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect1">
+<a name="NiceCandidate.other"></a><h2>Types and Values</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="name">
+<col class="description">
+</colgroup>
+<tbody>
+<tr>
+<td class="datatype_keyword">struct</td>
+<td class="function_name"><a class="link" href="NiceCandidate.html#NiceCandidate-struct" title="struct NiceCandidate">NiceCandidate</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="NiceCandidate.html#NiceCandidateType" title="enum NiceCandidateType">NiceCandidateType</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="NiceCandidate.html#NiceCandidateTransport" title="enum NiceCandidateTransport">NiceCandidateTransport</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">struct</td>
+<td class="function_name"><a class="link" href="NiceCandidate.html#TurnServer" title="struct TurnServer">TurnServer</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="NiceCandidate.html#NiceRelayType" title="enum NiceRelayType">NiceRelayType</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="NiceCandidate.html#NICE-CANDIDATE-MAX-FOUNDATION:CAPS" title="NICE_CANDIDATE_MAX_FOUNDATION">NICE_CANDIDATE_MAX_FOUNDATION</a></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect1">
+<a name="NiceCandidate.object-hierarchy"></a><h2>Object Hierarchy</h2>
+<pre class="screen"> <a href="/usr/share/gtk-doc/html/gobject/gobject-Boxed-Types.html">GBoxed</a>
+ <span class="lineart">╰──</span> NiceCandidate
+ <a href="/usr/share/gtk-doc/html/gobject/gobject-Enumeration-and-Flag-Types.html">GEnum</a>
+ <span class="lineart">├──</span> NiceCandidateTransport
+ <span class="lineart">├──</span> NiceCandidateType
+ <span class="lineart">╰──</span> NiceRelayType
+</pre>
+</div>
+<div class="refsect1">
+<a name="NiceCandidate.description"></a><h2>Description</h2>
+<p>A representation of an ICE candidate. Make sure you read the ICE drafts[1] to
+understand correctly the concept of ICE candidates.</p>
+<p>[1] http://tools.ietf.org/wg/mmusic/draft-ietf-mmusic-ice/</p>
+</div>
+<div class="refsect1">
+<a name="NiceCandidate.functions_details"></a><h2>Functions</h2>
+<div class="refsect2">
+<a name="nice-candidate-new"></a><h3>nice_candidate_new ()</h3>
+<pre class="programlisting"><a class="link" href="NiceCandidate.html" title="NiceCandidate"><span class="returnvalue">NiceCandidate</span></a> *
+nice_candidate_new (<em class="parameter"><code><a class="link" href="NiceCandidate.html#NiceCandidateType" title="enum NiceCandidateType"><span class="type">NiceCandidateType</span></a> type</code></em>);</pre>
+<p>Creates a new candidate. Must be freed with <a class="link" href="NiceCandidate.html#nice-candidate-free" title="nice_candidate_free ()"><code class="function">nice_candidate_free()</code></a></p>
+<div class="refsect3">
+<a name="nice-candidate-new.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>type</p></td>
+<td class="parameter_description"><p>The <a class="link" href="NiceCandidate.html#NiceCandidateType" title="enum NiceCandidateType"><span class="type">NiceCandidateType</span></a> of the candidate to create</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-candidate-new.returns"></a><h4>Returns</h4>
+<p> A new <a class="link" href="NiceCandidate.html" title="NiceCandidate"><span class="type">NiceCandidate</span></a></p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-candidate-free"></a><h3>nice_candidate_free ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+nice_candidate_free (<em class="parameter"><code><a class="link" href="NiceCandidate.html" title="NiceCandidate"><span class="type">NiceCandidate</span></a> *candidate</code></em>);</pre>
+<p>Frees a <a class="link" href="NiceCandidate.html" title="NiceCandidate"><span class="type">NiceCandidate</span></a></p>
+<div class="refsect3">
+<a name="nice-candidate-free.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>candidate</p></td>
+<td class="parameter_description"><p>The candidate to free</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-candidate-copy"></a><h3>nice_candidate_copy ()</h3>
+<pre class="programlisting"><a class="link" href="NiceCandidate.html" title="NiceCandidate"><span class="returnvalue">NiceCandidate</span></a> *
+nice_candidate_copy (<em class="parameter"><code>const <a class="link" href="NiceCandidate.html" title="NiceCandidate"><span class="type">NiceCandidate</span></a> *candidate</code></em>);</pre>
+<p>Makes a copy of a <a class="link" href="NiceCandidate.html" title="NiceCandidate"><span class="type">NiceCandidate</span></a></p>
+<div class="refsect3">
+<a name="nice-candidate-copy.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>candidate</p></td>
+<td class="parameter_description"><p>The candidate to copy</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-candidate-copy.returns"></a><h4>Returns</h4>
+<p> A new <a class="link" href="NiceCandidate.html" title="NiceCandidate"><span class="type">NiceCandidate</span></a>, a copy of <em class="parameter"><code>candidate</code></em>
+</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-candidate-equal-target"></a><h3>nice_candidate_equal_target ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+nice_candidate_equal_target (<em class="parameter"><code>const <a class="link" href="NiceCandidate.html" title="NiceCandidate"><span class="type">NiceCandidate</span></a> *candidate1</code></em>,
+ <em class="parameter"><code>const <a class="link" href="NiceCandidate.html" title="NiceCandidate"><span class="type">NiceCandidate</span></a> *candidate2</code></em>);</pre>
+<p>Verifies that the candidates point to the same place, meaning they have
+the same transport and the same address. It ignores all other aspects.</p>
+<div class="refsect3">
+<a name="nice-candidate-equal-target.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>candidate1</p></td>
+<td class="parameter_description"><p>A candidate</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>candidate2</p></td>
+<td class="parameter_description"><p>A candidate</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-candidate-equal-target.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> if the candidates point to the same place</p>
+</div>
+<p class="since">Since: <a class="link" href="ix14.html#api-index-0.1.15">0.1.15</a></p>
+</div>
+</div>
+<div class="refsect1">
+<a name="NiceCandidate.other_details"></a><h2>Types and Values</h2>
+<div class="refsect2">
+<a name="NiceCandidate-struct"></a><h3>struct NiceCandidate</h3>
+<pre class="programlisting">struct NiceCandidate {
+ NiceCandidateType type;
+ NiceCandidateTransport transport;
+ NiceAddress addr;
+ NiceAddress base_addr;
+ guint32 priority;
+ guint stream_id;
+ guint component_id;
+ gchar foundation[NICE_CANDIDATE_MAX_FOUNDATION];
+ gchar *username; /* pointer to a nul-terminated username string */
+ gchar *password; /* pointer to a nul-terminated password string */
+ TurnServer *turn;
+ gpointer sockptr;
+};
+</pre>
+<p>A structure to represent an ICE candidate</p>
+<div class="note"><p>
+ The <em class="parameter"><code>priority</code></em> is an integer as specified in the ICE draft 19. If you are
+ using the MSN or the GOOGLE compatibility mode (which are based on ICE
+ draft 6, which uses a floating point qvalue as priority), then the <em class="parameter"><code>priority</code></em>
+ value will represent the qvalue multiplied by 1000.
+ </p></div>
+<div class="refsect3">
+<a name="NiceCandidate.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="struct_members_name">
+<col class="struct_members_description">
+<col width="200px" class="struct_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="struct_member_name"><p><a class="link" href="NiceCandidate.html#NiceCandidateType" title="enum NiceCandidateType"><span class="type">NiceCandidateType</span></a> <em class="structfield"><code><a name="NiceCandidate-struct.type"></a>type</code></em>;</p></td>
+<td class="struct_member_description"><p>The type of candidate</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><a class="link" href="NiceCandidate.html#NiceCandidateTransport" title="enum NiceCandidateTransport"><span class="type">NiceCandidateTransport</span></a> <em class="structfield"><code><a name="NiceCandidate-struct.transport"></a>transport</code></em>;</p></td>
+<td class="struct_member_description"><p>The transport being used for the candidate</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> <em class="structfield"><code><a name="NiceCandidate-struct.addr"></a>addr</code></em>;</p></td>
+<td class="struct_member_description"><p>The <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> of the candidate</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> <em class="structfield"><code><a name="NiceCandidate-struct.base-addr"></a>base_addr</code></em>;</p></td>
+<td class="struct_member_description"><p>The <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> of the base address used by the candidate</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint32"><span class="type">guint32</span></a> <em class="structfield"><code><a name="NiceCandidate-struct.priority"></a>priority</code></em>;</p></td>
+<td class="struct_member_description"><p>The priority of the candidate <span class="emphasis"><em> see note </em></span></p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> <em class="structfield"><code><a name="NiceCandidate-struct.stream-id"></a>stream_id</code></em>;</p></td>
+<td class="struct_member_description"><p>The ID of the stream to which belongs the candidate</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> <em class="structfield"><code><a name="NiceCandidate-struct.component-id"></a>component_id</code></em>;</p></td>
+<td class="struct_member_description"><p>The ID of the component to which belongs the candidate</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> <em class="structfield"><code><a name="NiceCandidate-struct.foundation"></a>foundation</code></em>[NICE_CANDIDATE_MAX_FOUNDATION];</p></td>
+<td class="struct_member_description"><p>The foundation of the candidate</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *<em class="structfield"><code><a name="NiceCandidate-struct.username"></a>username</code></em>;</p></td>
+<td class="struct_member_description"><p>The candidate-specific username to use (overrides the one set
+by <a class="link" href="NiceAgent.html#nice-agent-set-local-credentials" title="nice_agent_set_local_credentials ()"><code class="function">nice_agent_set_local_credentials()</code></a> or <a class="link" href="NiceAgent.html#nice-agent-set-remote-credentials" title="nice_agent_set_remote_credentials ()"><code class="function">nice_agent_set_remote_credentials()</code></a>)</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *<em class="structfield"><code><a name="NiceCandidate-struct.password"></a>password</code></em>;</p></td>
+<td class="struct_member_description"><p>The candidate-specific password to use (overrides the one set
+by <a class="link" href="NiceAgent.html#nice-agent-set-local-credentials" title="nice_agent_set_local_credentials ()"><code class="function">nice_agent_set_local_credentials()</code></a> or <a class="link" href="NiceAgent.html#nice-agent-set-remote-credentials" title="nice_agent_set_remote_credentials ()"><code class="function">nice_agent_set_remote_credentials()</code></a>)</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><a class="link" href="NiceCandidate.html#TurnServer" title="struct TurnServer"><span class="type">TurnServer</span></a> *<em class="structfield"><code><a name="NiceCandidate-struct.turn"></a>turn</code></em>;</p></td>
+<td class="struct_member_description"><p>The <a class="link" href="NiceCandidate.html#TurnServer" title="struct TurnServer"><span class="type">TurnServer</span></a> settings if the candidate is
+of type <a class="link" href="NiceCandidate.html#NICE-CANDIDATE-TYPE-RELAYED:CAPS"><code class="literal">NICE_CANDIDATE_TYPE_RELAYED</code></a></p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gpointer"><span class="type">gpointer</span></a> <em class="structfield"><code><a name="NiceCandidate-struct.sockptr"></a>sockptr</code></em>;</p></td>
+<td class="struct_member_description"><p>The underlying socket</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceCandidateType"></a><h3>enum NiceCandidateType</h3>
+<p>An enum represneting the type of a candidate</p>
+<div class="refsect3">
+<a name="NiceCandidateType.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-CANDIDATE-TYPE-HOST:CAPS"></a>NICE_CANDIDATE_TYPE_HOST</p></td>
+<td class="enum_member_description">
+<p>A host candidate</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-CANDIDATE-TYPE-SERVER-REFLEXIVE:CAPS"></a>NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE</p></td>
+<td class="enum_member_description">
+<p>A server reflexive candidate</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-CANDIDATE-TYPE-PEER-REFLEXIVE:CAPS"></a>NICE_CANDIDATE_TYPE_PEER_REFLEXIVE</p></td>
+<td class="enum_member_description">
+<p>A peer reflexive candidate</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-CANDIDATE-TYPE-RELAYED:CAPS"></a>NICE_CANDIDATE_TYPE_RELAYED</p></td>
+<td class="enum_member_description">
+<p>A relay candidate</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceCandidateTransport"></a><h3>enum NiceCandidateTransport</h3>
+<p>An enum representing the type of transport to use</p>
+<div class="refsect3">
+<a name="NiceCandidateTransport.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-CANDIDATE-TRANSPORT-UDP:CAPS"></a>NICE_CANDIDATE_TRANSPORT_UDP</p></td>
+<td class="enum_member_description">
+<p>UDP transport</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-CANDIDATE-TRANSPORT-TCP-ACTIVE:CAPS"></a>NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE</p></td>
+<td class="enum_member_description">
+<p>TCP Active transport</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-CANDIDATE-TRANSPORT-TCP-PASSIVE:CAPS"></a>NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE</p></td>
+<td class="enum_member_description">
+<p>TCP Passive transport</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-CANDIDATE-TRANSPORT-TCP-SO:CAPS"></a>NICE_CANDIDATE_TRANSPORT_TCP_SO</p></td>
+<td class="enum_member_description">
+<p>TCP Simultaneous-Open transport</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="TurnServer"></a><h3>struct TurnServer</h3>
+<pre class="programlisting">struct TurnServer {
+ gint ref_count;
+
+ NiceAddress server;
+ gchar *username;
+ gchar *password;
+ NiceRelayType type;
+};
+</pre>
+<p>A structure to store the TURN relay settings</p>
+<div class="refsect3">
+<a name="TurnServer.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="struct_members_name">
+<col class="struct_members_description">
+<col width="200px" class="struct_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="struct_member_name"><p><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gint"><span class="type">gint</span></a> <em class="structfield"><code><a name="TurnServer.ref-count"></a>ref_count</code></em>;</p></td>
+<td class="struct_member_description"><p>Reference count for the structure.</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> <em class="structfield"><code><a name="TurnServer.server"></a>server</code></em>;</p></td>
+<td class="struct_member_description"><p>The <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> of the TURN server</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *<em class="structfield"><code><a name="TurnServer.username"></a>username</code></em>;</p></td>
+<td class="struct_member_description"><p>The TURN username</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *<em class="structfield"><code><a name="TurnServer.password"></a>password</code></em>;</p></td>
+<td class="struct_member_description"><p>The TURN password</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><a class="link" href="NiceCandidate.html#NiceRelayType" title="enum NiceRelayType"><span class="type">NiceRelayType</span></a> <em class="structfield"><code><a name="TurnServer.type"></a>type</code></em>;</p></td>
+<td class="struct_member_description"><p>The <a class="link" href="NiceCandidate.html#NiceRelayType" title="enum NiceRelayType"><span class="type">NiceRelayType</span></a> of the server</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NiceRelayType"></a><h3>enum NiceRelayType</h3>
+<p>An enum representing the type of relay to use</p>
+<div class="refsect3">
+<a name="NiceRelayType.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-RELAY-TYPE-TURN-UDP:CAPS"></a>NICE_RELAY_TYPE_TURN_UDP</p></td>
+<td class="enum_member_description">
+<p>A TURN relay using UDP</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-RELAY-TYPE-TURN-TCP:CAPS"></a>NICE_RELAY_TYPE_TURN_TCP</p></td>
+<td class="enum_member_description">
+<p>A TURN relay using TCP</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="NICE-RELAY-TYPE-TURN-TLS:CAPS"></a>NICE_RELAY_TYPE_TURN_TLS</p></td>
+<td class="enum_member_description">
+<p>A TURN relay using TLS over TCP</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NICE-CANDIDATE-MAX-FOUNDATION:CAPS"></a><h3>NICE_CANDIDATE_MAX_FOUNDATION</h3>
+<pre class="programlisting">#define NICE_CANDIDATE_MAX_FOUNDATION (32+1)
+</pre>
+<p>The maximum size a candidate foundation can have.</p>
+</div>
+</div>
+<div class="refsect1">
+<a name="NiceCandidate.see-also"></a><h2>See Also</h2>
+<p><a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a></p>
+</div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.29</div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Annotation Glossary: libnice Reference Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets Vsnapshot">
+<link rel="home" href="index.html" title="libnice Reference Manual">
+<link rel="up" href="pt04.html" title="Part IV. Appendices">
+<link rel="prev" href="ix15.html" title="Index of new symbols in 0.1.16">
+<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"><span id="nav_glossary"><a class="shortcut" href="#glsA">A</a>
+ <span class="dim">|</span>
+ <a class="shortcut" href="#glsE">E</a>
+ <span class="dim">|</span>
+ <a class="shortcut" href="#glsI">I</a>
+ <span class="dim">|</span>
+ <a class="shortcut" href="#glsN">N</a>
+ <span class="dim">|</span>
+ <a class="shortcut" href="#glsO">O</a>
+ <span class="dim">|</span>
+ <a class="shortcut" href="#glsS">S</a>
+ <span class="dim">|</span>
+ <a class="shortcut" href="#glsT">T</a>
+ <span class="dim">|</span>
+ <a class="shortcut" href="#glsU">U</a></span></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="pt04.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="ix15.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><img src="right-insensitive.png" width="16" height="16" border="0"></td>
+</tr></table>
+<div class="glossary">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="annotation-glossary"></a>Annotation Glossary</h2></div></div></div>
+<a name="glsA"></a><h3 class="title">A</h3>
+<dt><span class="glossterm"><a name="annotation-glossterm-allow-none"></a>allow-none</span></dt>
+<dd class="glossdef"><p>NULL is OK, both for passing and for returning.</p></dd>
+<dt><span class="glossterm"><a name="annotation-glossterm-array"></a>array</span></dt>
+<dd class="glossdef"><p>Parameter points to an array of items.</p></dd>
+<a name="glsE"></a><h3 class="title">E</h3>
+<dt><span class="glossterm"><a name="annotation-glossterm-element-type"></a>element-type</span></dt>
+<dd class="glossdef"><p>Generics and defining elements of containers and arrays.</p></dd>
+<a name="glsI"></a><h3 class="title">I</h3>
+<dt><span class="glossterm"><a name="annotation-glossterm-in"></a>in</span></dt>
+<dd class="glossdef"><p>Parameter for input. Default is <acronym title="Don't free data after the code is done."><span class="acronym">transfer none</span></acronym>.</p></dd>
+<a name="glsN"></a><h3 class="title">N</h3>
+<dt><span class="glossterm"><a name="annotation-glossterm-nullable"></a>nullable</span></dt>
+<dd class="glossdef"><p>NULL may be passed as the value in, out, in-out; or as a return value.</p></dd>
+<a name="glsO"></a><h3 class="title">O</h3>
+<dt><span class="glossterm"><a name="annotation-glossterm-out%20callee-allocates"></a>out callee-allocates</span></dt>
+<dd class="glossdef"><p>Out parameter, where caller must allocate storage.</p></dd>
+<dt><span class="glossterm"><a name="annotation-glossterm-out%20caller-allocates"></a>out caller-allocates</span></dt>
+<dd class="glossdef"><p>Out parameter, where caller must allocate storage.</p></dd>
+<a name="glsS"></a><h3 class="title">S</h3>
+<dt><span class="glossterm"><a name="annotation-glossterm-skip"></a>skip</span></dt>
+<dd class="glossdef"><p>Exposed in C code, not necessarily available in other languages.</p></dd>
+<dt><span class="glossterm"><a name="annotation-glossterm-Stable"></a>Stable</span></dt>
+<dd class="glossdef"><p>The intention of a Stable interface is to enable arbitrary third parties to
+develop applications to these interfaces, release them, and have confidence that
+they will run on all minor releases of the product (after the one in which the
+interface was introduced, and within the same major release). Even at a major
+release, incompatible changes are expected to be rare, and to have strong
+justifications.
+</p></dd>
+<a name="glsT"></a><h3 class="title">T</h3>
+<dt><span class="glossterm"><a name="annotation-glossterm-transfer%20full"></a>transfer full</span></dt>
+<dd class="glossdef"><p>Free data after the code is done.</p></dd>
+<dt><span class="glossterm"><a name="annotation-glossterm-transfer%20none"></a>transfer none</span></dt>
+<dd class="glossdef"><p>Don't free data after the code is done.</p></dd>
+<a name="glsU"></a><h3 class="title">U</h3>
+<dt><span class="glossterm"><a name="annotation-glossterm-Unstable"></a>Unstable</span></dt>
+<dd class="glossdef"><p>Unstable interfaces are experimental or transitional. They are typically used to
+give outside developers early access to new or rapidly changing technology, or
+to provide an interim solution to a problem where a more general solution is
+anticipated. No claims are made about either source or binary compatibility from
+one minor release to the next.
+
+The Unstable interface level is a warning that these interfaces are subject to
+change without warning and should not be used in unbundled products.
+
+Given such caveats, customer impact need not be a factor when considering
+incompatible changes to an Unstable interface in a major or minor release.
+Nonetheless, when such changes are introduced, the changes should still be
+mentioned in the release notes for the affected release.
+</p></dd>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.29</div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Index of deprecated symbols: libnice Reference Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets Vsnapshot">
+<link rel="home" href="index.html" title="libnice Reference Manual">
+<link rel="up" href="pt04.html" title="Part IV. Appendices">
+<link rel="prev" href="api-index-full.html" title="API Index">
+<link rel="next" href="ix03.html" title="Index of new symbols in 0.0.4">
+<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"><span id="nav_index"><a class="shortcut" href="#idxA">A</a></span></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="pt04.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="api-index-full.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="ix03.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="index">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="api-index-deprecated"></a>Index of deprecated symbols</h2></div></div></div>
+<a name="idx"></a><a name="idxA"></a><h3 class="title">A</h3>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent-new-candidate" title="The “new-candidate” signal">NiceAgent::new-candidate</a>, object signal in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent-new-remote-candidate" title="The “new-remote-candidate” signal">NiceAgent::new-remote-candidate</a>, object signal in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent-new-selected-pair" title="The “new-selected-pair” signal">NiceAgent::new-selected-pair</a>, object signal in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.29</div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>API Index: libnice Reference Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets Vsnapshot">
+<link rel="home" href="index.html" title="libnice Reference Manual">
+<link rel="up" href="pt04.html" title="Part IV. Appendices">
+<link rel="prev" href="pt04.html" title="Part IV. Appendices">
+<link rel="next" href="api-index-deprecated.html" title="Index of deprecated symbols">
+<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"><span id="nav_index"><a class="shortcut" href="#idxA">A</a>
+ <span class="dim">|</span>
+ <a class="shortcut" href="#idxC">C</a>
+ <span class="dim">|</span>
+ <a class="shortcut" href="#idxD">D</a>
+ <span class="dim">|</span>
+ <a class="shortcut" href="#idxI">I</a>
+ <span class="dim">|</span>
+ <a class="shortcut" href="#idxN">N</a>
+ <span class="dim">|</span>
+ <a class="shortcut" href="#idxO">O</a>
+ <span class="dim">|</span>
+ <a class="shortcut" href="#idxP">P</a>
+ <span class="dim">|</span>
+ <a class="shortcut" href="#idxR">R</a>
+ <span class="dim">|</span>
+ <a class="shortcut" href="#idxS">S</a>
+ <span class="dim">|</span>
+ <a class="shortcut" href="#idxT">T</a></span></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="pt04.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="pt04.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-deprecated.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="index">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="api-index-full"></a>API Index</h2></div></div></div>
+<a name="idx"></a><a name="idxA"></a><h3 class="title">A</h3>
+<dt>
+<a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress">NiceAddress</a>, struct in <a class="link" href="libnice-NiceAddress.html" title="NiceAddress">NiceAddress</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-NiceAddress.html#nice-address-copy-to-sockaddr" title="nice_address_copy_to_sockaddr ()">nice_address_copy_to_sockaddr</a>, function in <a class="link" href="libnice-NiceAddress.html" title="NiceAddress">NiceAddress</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-NiceAddress.html#nice-address-dup" title="nice_address_dup ()">nice_address_dup</a>, function in <a class="link" href="libnice-NiceAddress.html" title="NiceAddress">NiceAddress</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-NiceAddress.html#nice-address-equal" title="nice_address_equal ()">nice_address_equal</a>, function in <a class="link" href="libnice-NiceAddress.html" title="NiceAddress">NiceAddress</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-NiceAddress.html#nice-address-equal-no-port" title="nice_address_equal_no_port ()">nice_address_equal_no_port</a>, function in <a class="link" href="libnice-NiceAddress.html" title="NiceAddress">NiceAddress</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-NiceAddress.html#nice-address-free" title="nice_address_free ()">nice_address_free</a>, function in <a class="link" href="libnice-NiceAddress.html" title="NiceAddress">NiceAddress</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-NiceAddress.html#nice-address-get-port" title="nice_address_get_port ()">nice_address_get_port</a>, function in <a class="link" href="libnice-NiceAddress.html" title="NiceAddress">NiceAddress</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-NiceAddress.html#nice-address-init" title="nice_address_init ()">nice_address_init</a>, function in <a class="link" href="libnice-NiceAddress.html" title="NiceAddress">NiceAddress</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-NiceAddress.html#nice-address-ip-version" title="nice_address_ip_version ()">nice_address_ip_version</a>, function in <a class="link" href="libnice-NiceAddress.html" title="NiceAddress">NiceAddress</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-NiceAddress.html#nice-address-is-private" title="nice_address_is_private ()">nice_address_is_private</a>, function in <a class="link" href="libnice-NiceAddress.html" title="NiceAddress">NiceAddress</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-NiceAddress.html#nice-address-is-valid" title="nice_address_is_valid ()">nice_address_is_valid</a>, function in <a class="link" href="libnice-NiceAddress.html" title="NiceAddress">NiceAddress</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-NiceAddress.html#nice-address-new" title="nice_address_new ()">nice_address_new</a>, function in <a class="link" href="libnice-NiceAddress.html" title="NiceAddress">NiceAddress</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-NiceAddress.html#nice-address-set-from-sockaddr" title="nice_address_set_from_sockaddr ()">nice_address_set_from_sockaddr</a>, function in <a class="link" href="libnice-NiceAddress.html" title="NiceAddress">NiceAddress</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-NiceAddress.html#nice-address-set-from-string" title="nice_address_set_from_string ()">nice_address_set_from_string</a>, function in <a class="link" href="libnice-NiceAddress.html" title="NiceAddress">NiceAddress</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-NiceAddress.html#nice-address-set-ipv4" title="nice_address_set_ipv4 ()">nice_address_set_ipv4</a>, function in <a class="link" href="libnice-NiceAddress.html" title="NiceAddress">NiceAddress</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-NiceAddress.html#nice-address-set-ipv6" title="nice_address_set_ipv6 ()">nice_address_set_ipv6</a>, function in <a class="link" href="libnice-NiceAddress.html" title="NiceAddress">NiceAddress</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-NiceAddress.html#nice-address-set-port" title="nice_address_set_port ()">nice_address_set_port</a>, function in <a class="link" href="libnice-NiceAddress.html" title="NiceAddress">NiceAddress</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-NiceAddress.html#NICE-ADDRESS-STRING-LEN:CAPS" title="NICE_ADDRESS_STRING_LEN">NICE_ADDRESS_STRING_LEN</a>, macro in <a class="link" href="libnice-NiceAddress.html" title="NiceAddress">NiceAddress</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-NiceAddress.html#nice-address-to-string" title="nice_address_to_string ()">nice_address_to_string</a>, function in <a class="link" href="libnice-NiceAddress.html" title="NiceAddress">NiceAddress</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent-struct" title="NiceAgent">NiceAgent</a>, struct in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent-candidate-gathering-done" title="The “candidate-gathering-done” signal">NiceAgent::candidate-gathering-done</a>, object signal in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent-component-state-changed" title="The “component-state-changed” signal">NiceAgent::component-state-changed</a>, object signal in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent-initial-binding-request-received" title="The “initial-binding-request-received” signal">NiceAgent::initial-binding-request-received</a>, object signal in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent-new-candidate" title="The “new-candidate” signal">NiceAgent::new-candidate</a>, object signal in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent-new-candidate-full" title="The “new-candidate-full” signal">NiceAgent::new-candidate-full</a>, object signal in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent-new-remote-candidate" title="The “new-remote-candidate” signal">NiceAgent::new-remote-candidate</a>, object signal in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent-new-remote-candidate-full" title="The “new-remote-candidate-full” signal">NiceAgent::new-remote-candidate-full</a>, object signal in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent-new-selected-pair" title="The “new-selected-pair” signal">NiceAgent::new-selected-pair</a>, object signal in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent-new-selected-pair-full" title="The “new-selected-pair-full” signal">NiceAgent::new-selected-pair-full</a>, object signal in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent-reliable-transport-writable" title="The “reliable-transport-writable” signal">NiceAgent::reliable-transport-writable</a>, object signal in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent-streams-removed" title="The “streams-removed” signal">NiceAgent::streams-removed</a>, object signal in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent--bytestream-tcp" title="The “bytestream-tcp” property">NiceAgent:bytestream-tcp</a>, object property in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent--compatibility" title="The “compatibility” property">NiceAgent:compatibility</a>, object property in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent--controlling-mode" title="The “controlling-mode” property">NiceAgent:controlling-mode</a>, object property in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent--force-relay" title="The “force-relay” property">NiceAgent:force-relay</a>, object property in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent--full-mode" title="The “full-mode” property">NiceAgent:full-mode</a>, object property in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent--ice-tcp" title="The “ice-tcp” property">NiceAgent:ice-tcp</a>, object property in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent--ice-trickle" title="The “ice-trickle” property">NiceAgent:ice-trickle</a>, object property in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent--ice-udp" title="The “ice-udp” property">NiceAgent:ice-udp</a>, object property in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent--keepalive-conncheck" title="The “keepalive-conncheck” property">NiceAgent:keepalive-conncheck</a>, object property in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent--main-context" title="The “main-context” property">NiceAgent:main-context</a>, object property in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent--max-connectivity-checks" title="The “max-connectivity-checks” property">NiceAgent:max-connectivity-checks</a>, object property in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent--nomination-mode" title="The “nomination-mode” property">NiceAgent:nomination-mode</a>, object property in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent--proxy-ip" title="The “proxy-ip” property">NiceAgent:proxy-ip</a>, object property in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent--proxy-password" title="The “proxy-password” property">NiceAgent:proxy-password</a>, object property in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent--proxy-port" title="The “proxy-port” property">NiceAgent:proxy-port</a>, object property in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent--proxy-type" title="The “proxy-type” property">NiceAgent:proxy-type</a>, object property in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent--proxy-username" title="The “proxy-username” property">NiceAgent:proxy-username</a>, object property in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent--reliable" title="The “reliable” property">NiceAgent:reliable</a>, object property in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent--stun-initial-timeout" title="The “stun-initial-timeout” property">NiceAgent:stun-initial-timeout</a>, object property in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent--stun-max-retransmissions" title="The “stun-max-retransmissions” property">NiceAgent:stun-max-retransmissions</a>, object property in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent--stun-pacing-timer" title="The “stun-pacing-timer” property">NiceAgent:stun-pacing-timer</a>, object property in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent--stun-reliable-timeout" title="The “stun-reliable-timeout” property">NiceAgent:stun-reliable-timeout</a>, object property in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent--stun-server" title="The “stun-server” property">NiceAgent:stun-server</a>, object property in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent--stun-server-port" title="The “stun-server-port” property">NiceAgent:stun-server-port</a>, object property in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent--support-renomination" title="The “support-renomination” property">NiceAgent:support-renomination</a>, object property in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent--upnp" title="The “upnp” property">NiceAgent:upnp</a>, object property in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgent--upnp-timeout" title="The “upnp-timeout” property">NiceAgent:upnp-timeout</a>, object property in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgentOption" title="enum NiceAgentOption">NiceAgentOption</a>, enum in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceAgentRecvFunc" title="NiceAgentRecvFunc ()">NiceAgentRecvFunc</a>, user_function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-add-local-address" title="nice_agent_add_local_address ()">nice_agent_add_local_address</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-add-stream" title="nice_agent_add_stream ()">nice_agent_add_stream</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-attach-recv" title="nice_agent_attach_recv ()">nice_agent_attach_recv</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-close-async" title="nice_agent_close_async ()">nice_agent_close_async</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-forget-relays" title="nice_agent_forget_relays ()">nice_agent_forget_relays</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-gather-candidates" title="nice_agent_gather_candidates ()">nice_agent_gather_candidates</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-generate-local-candidate-sdp" title="nice_agent_generate_local_candidate_sdp ()">nice_agent_generate_local_candidate_sdp</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-generate-local-sdp" title="nice_agent_generate_local_sdp ()">nice_agent_generate_local_sdp</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-generate-local-stream-sdp" title="nice_agent_generate_local_stream_sdp ()">nice_agent_generate_local_stream_sdp</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-get-component-state" title="nice_agent_get_component_state ()">nice_agent_get_component_state</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-get-default-local-candidate" title="nice_agent_get_default_local_candidate ()">nice_agent_get_default_local_candidate</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-get-io-stream" title="nice_agent_get_io_stream ()">nice_agent_get_io_stream</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-get-local-candidates" title="nice_agent_get_local_candidates ()">nice_agent_get_local_candidates</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-get-local-credentials" title="nice_agent_get_local_credentials ()">nice_agent_get_local_credentials</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-get-remote-candidates" title="nice_agent_get_remote_candidates ()">nice_agent_get_remote_candidates</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-get-selected-pair" title="nice_agent_get_selected_pair ()">nice_agent_get_selected_pair</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-get-selected-socket" title="nice_agent_get_selected_socket ()">nice_agent_get_selected_socket</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-get-stream-name" title="nice_agent_get_stream_name ()">nice_agent_get_stream_name</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NICE-AGENT-MAX-REMOTE-CANDIDATES:CAPS" title="NICE_AGENT_MAX_REMOTE_CANDIDATES">NICE_AGENT_MAX_REMOTE_CANDIDATES</a>, macro in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-new" title="nice_agent_new ()">nice_agent_new</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-new-full" title="nice_agent_new_full ()">nice_agent_new_full</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-new-reliable" title="nice_agent_new_reliable ()">nice_agent_new_reliable</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-parse-remote-candidate-sdp" title="nice_agent_parse_remote_candidate_sdp ()">nice_agent_parse_remote_candidate_sdp</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-parse-remote-sdp" title="nice_agent_parse_remote_sdp ()">nice_agent_parse_remote_sdp</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-parse-remote-stream-sdp" title="nice_agent_parse_remote_stream_sdp ()">nice_agent_parse_remote_stream_sdp</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-peer-candidate-gathering-done" title="nice_agent_peer_candidate_gathering_done ()">nice_agent_peer_candidate_gathering_done</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-recv" title="nice_agent_recv ()">nice_agent_recv</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-recv-messages" title="nice_agent_recv_messages ()">nice_agent_recv_messages</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-recv-messages-nonblocking" title="nice_agent_recv_messages_nonblocking ()">nice_agent_recv_messages_nonblocking</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-recv-nonblocking" title="nice_agent_recv_nonblocking ()">nice_agent_recv_nonblocking</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-remove-stream" title="nice_agent_remove_stream ()">nice_agent_remove_stream</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-restart" title="nice_agent_restart ()">nice_agent_restart</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-restart-stream" title="nice_agent_restart_stream ()">nice_agent_restart_stream</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-send" title="nice_agent_send ()">nice_agent_send</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-send-messages-nonblocking" title="nice_agent_send_messages_nonblocking ()">nice_agent_send_messages_nonblocking</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-set-local-credentials" title="nice_agent_set_local_credentials ()">nice_agent_set_local_credentials</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-set-port-range" title="nice_agent_set_port_range ()">nice_agent_set_port_range</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-set-relay-info" title="nice_agent_set_relay_info ()">nice_agent_set_relay_info</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-set-remote-candidates" title="nice_agent_set_remote_candidates ()">nice_agent_set_remote_candidates</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-set-remote-credentials" title="nice_agent_set_remote_credentials ()">nice_agent_set_remote_credentials</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-set-selected-pair" title="nice_agent_set_selected_pair ()">nice_agent_set_selected_pair</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-set-selected-remote-candidate" title="nice_agent_set_selected_remote_candidate ()">nice_agent_set_selected_remote_candidate</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-set-software" title="nice_agent_set_software ()">nice_agent_set_software</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-set-stream-name" title="nice_agent_set_stream_name ()">nice_agent_set_stream_name</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-agent-set-stream-tos" title="nice_agent_set_stream_tos ()">nice_agent_set_stream_tos</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<a name="idxC"></a><h3 class="title">C</h3>
+<dt>
+<a class="link" href="NiceCandidate.html#NiceCandidate-struct" title="struct NiceCandidate">NiceCandidate</a>, struct in <a class="link" href="NiceCandidate.html" title="NiceCandidate">NiceCandidate</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceCandidate.html#NiceCandidateTransport" title="enum NiceCandidateTransport">NiceCandidateTransport</a>, enum in <a class="link" href="NiceCandidate.html" title="NiceCandidate">NiceCandidate</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceCandidate.html#NiceCandidateType" title="enum NiceCandidateType">NiceCandidateType</a>, enum in <a class="link" href="NiceCandidate.html" title="NiceCandidate">NiceCandidate</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceCandidate.html#nice-candidate-copy" title="nice_candidate_copy ()">nice_candidate_copy</a>, function in <a class="link" href="NiceCandidate.html" title="NiceCandidate">NiceCandidate</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceCandidate.html#nice-candidate-equal-target" title="nice_candidate_equal_target ()">nice_candidate_equal_target</a>, function in <a class="link" href="NiceCandidate.html" title="NiceCandidate">NiceCandidate</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceCandidate.html#nice-candidate-free" title="nice_candidate_free ()">nice_candidate_free</a>, function in <a class="link" href="NiceCandidate.html" title="NiceCandidate">NiceCandidate</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceCandidate.html#NICE-CANDIDATE-MAX-FOUNDATION:CAPS" title="NICE_CANDIDATE_MAX_FOUNDATION">NICE_CANDIDATE_MAX_FOUNDATION</a>, macro in <a class="link" href="NiceCandidate.html" title="NiceCandidate">NiceCandidate</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceCandidate.html#nice-candidate-new" title="nice_candidate_new ()">nice_candidate_new</a>, function in <a class="link" href="NiceCandidate.html" title="NiceCandidate">NiceCandidate</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceCompatibility" title="enum NiceCompatibility">NiceCompatibility</a>, enum in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceComponentState" title="enum NiceComponentState">NiceComponentState</a>, enum in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#NiceComponentType" title="enum NiceComponentType">NiceComponentType</a>, enum in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="NiceAgent.html#nice-component-state-to-string" title="nice_component_state_to_string ()">nice_component_state_to_string</a>, function in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<a name="idxD"></a><h3 class="title">D</h3>
+<dt>
+<a class="link" href="libnice-Debug-messages.html#nice-debug-disable" title="nice_debug_disable ()">nice_debug_disable</a>, function in <a class="link" href="libnice-Debug-messages.html" title="Debug messages">Debug messages</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Debug-messages.html#nice-debug-enable" title="nice_debug_enable ()">nice_debug_enable</a>, function in <a class="link" href="libnice-Debug-messages.html" title="Debug messages">Debug messages</a>
+</dt>
+<dd></dd>
+<a name="idxI"></a><h3 class="title">I</h3>
+<dt>
+<a class="link" href="NiceAgent.html#NiceInputMessage" title="NiceInputMessage">NiceInputMessage</a>, struct in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Network-interfaces-discovery.html#nice-interfaces-get-ip-for-interface" title="nice_interfaces_get_ip_for_interface ()">nice_interfaces_get_ip_for_interface</a>, function in <a class="link" href="libnice-Network-interfaces-discovery.html" title="Network interfaces discovery">Network interfaces discovery</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Network-interfaces-discovery.html#nice-interfaces-get-local-interfaces" title="nice_interfaces_get_local_interfaces ()">nice_interfaces_get_local_interfaces</a>, function in <a class="link" href="libnice-Network-interfaces-discovery.html" title="Network interfaces discovery">Network interfaces discovery</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Network-interfaces-discovery.html#nice-interfaces-get-local-ips" title="nice_interfaces_get_local_ips ()">nice_interfaces_get_local_ips</a>, function in <a class="link" href="libnice-Network-interfaces-discovery.html" title="Network interfaces discovery">Network interfaces discovery</a>
+</dt>
+<dd></dd>
+<a name="idxN"></a><h3 class="title">N</h3>
+<dt>
+<a class="link" href="NiceAgent.html#NiceNominationMode" title="enum NiceNominationMode">NiceNominationMode</a>, enum in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<a name="idxO"></a><h3 class="title">O</h3>
+<dt>
+<a class="link" href="NiceAgent.html#NiceOutputMessage" title="NiceOutputMessage">NiceOutputMessage</a>, struct in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<a name="idxP"></a><h3 class="title">P</h3>
+<dt>
+<a class="link" href="NiceAgent.html#NiceProxyType" title="enum NiceProxyType">NiceProxyType</a>, enum in <a class="link" href="NiceAgent.html" title="NiceAgent">NiceAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpCallbacks" title="PseudoTcpCallbacks">PseudoTcpCallbacks</a>, struct in <a class="link" href="libnice-Pseudo-TCP-Socket.html" title="Pseudo TCP Socket">Pseudo TCP Socket</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpDebugLevel" title="enum PseudoTcpDebugLevel">PseudoTcpDebugLevel</a>, enum in <a class="link" href="libnice-Pseudo-TCP-Socket.html" title="Pseudo TCP Socket">Pseudo TCP Socket</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpShutdown" title="enum PseudoTcpShutdown">PseudoTcpShutdown</a>, enum in <a class="link" href="libnice-Pseudo-TCP-Socket.html" title="Pseudo TCP Socket">Pseudo TCP Socket</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket-struct" title="PseudoTcpSocket">PseudoTcpSocket</a>, struct in <a class="link" href="libnice-Pseudo-TCP-Socket.html" title="Pseudo TCP Socket">Pseudo TCP Socket</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket--ack-delay" title="The “ack-delay” property">PseudoTcpSocket:ack-delay</a>, object property in <a class="link" href="libnice-Pseudo-TCP-Socket.html" title="Pseudo TCP Socket">Pseudo TCP Socket</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket--callbacks" title="The “callbacks” property">PseudoTcpSocket:callbacks</a>, object property in <a class="link" href="libnice-Pseudo-TCP-Socket.html" title="Pseudo TCP Socket">Pseudo TCP Socket</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket--conversation" title="The “conversation” property">PseudoTcpSocket:conversation</a>, object property in <a class="link" href="libnice-Pseudo-TCP-Socket.html" title="Pseudo TCP Socket">Pseudo TCP Socket</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket--no-delay" title="The “no-delay” property">PseudoTcpSocket:no-delay</a>, object property in <a class="link" href="libnice-Pseudo-TCP-Socket.html" title="Pseudo TCP Socket">Pseudo TCP Socket</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket--rcv-buf" title="The “rcv-buf” property">PseudoTcpSocket:rcv-buf</a>, object property in <a class="link" href="libnice-Pseudo-TCP-Socket.html" title="Pseudo TCP Socket">Pseudo TCP Socket</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket--snd-buf" title="The “snd-buf” property">PseudoTcpSocket:snd-buf</a>, object property in <a class="link" href="libnice-Pseudo-TCP-Socket.html" title="Pseudo TCP Socket">Pseudo TCP Socket</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket--state" title="The “state” property">PseudoTcpSocket:state</a>, object property in <a class="link" href="libnice-Pseudo-TCP-Socket.html" title="Pseudo TCP Socket">Pseudo TCP Socket</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket--support-fin-ack" title="The “support-fin-ack” property">PseudoTcpSocket:support-fin-ack</a>, object property in <a class="link" href="libnice-Pseudo-TCP-Socket.html" title="Pseudo TCP Socket">Pseudo TCP Socket</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpState" title="enum PseudoTcpState">PseudoTcpState</a>, enum in <a class="link" href="libnice-Pseudo-TCP-Socket.html" title="Pseudo TCP Socket">Pseudo TCP Socket</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpWriteResult" title="enum PseudoTcpWriteResult">PseudoTcpWriteResult</a>, enum in <a class="link" href="libnice-Pseudo-TCP-Socket.html" title="Pseudo TCP Socket">Pseudo TCP Socket</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-set-debug-level" title="pseudo_tcp_set_debug_level ()">pseudo_tcp_set_debug_level</a>, function in <a class="link" href="libnice-Pseudo-TCP-Socket.html" title="Pseudo TCP Socket">Pseudo TCP Socket</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-can-send" title="pseudo_tcp_socket_can_send ()">pseudo_tcp_socket_can_send</a>, function in <a class="link" href="libnice-Pseudo-TCP-Socket.html" title="Pseudo TCP Socket">Pseudo TCP Socket</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-close" title="pseudo_tcp_socket_close ()">pseudo_tcp_socket_close</a>, function in <a class="link" href="libnice-Pseudo-TCP-Socket.html" title="Pseudo TCP Socket">Pseudo TCP Socket</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-connect" title="pseudo_tcp_socket_connect ()">pseudo_tcp_socket_connect</a>, function in <a class="link" href="libnice-Pseudo-TCP-Socket.html" title="Pseudo TCP Socket">Pseudo TCP Socket</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-get-available-bytes" title="pseudo_tcp_socket_get_available_bytes ()">pseudo_tcp_socket_get_available_bytes</a>, function in <a class="link" href="libnice-Pseudo-TCP-Socket.html" title="Pseudo TCP Socket">Pseudo TCP Socket</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-get-available-send-space" title="pseudo_tcp_socket_get_available_send_space ()">pseudo_tcp_socket_get_available_send_space</a>, function in <a class="link" href="libnice-Pseudo-TCP-Socket.html" title="Pseudo TCP Socket">Pseudo TCP Socket</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-get-error" title="pseudo_tcp_socket_get_error ()">pseudo_tcp_socket_get_error</a>, function in <a class="link" href="libnice-Pseudo-TCP-Socket.html" title="Pseudo TCP Socket">Pseudo TCP Socket</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-get-next-clock" title="pseudo_tcp_socket_get_next_clock ()">pseudo_tcp_socket_get_next_clock</a>, function in <a class="link" href="libnice-Pseudo-TCP-Socket.html" title="Pseudo TCP Socket">Pseudo TCP Socket</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-is-closed" title="pseudo_tcp_socket_is_closed ()">pseudo_tcp_socket_is_closed</a>, function in <a class="link" href="libnice-Pseudo-TCP-Socket.html" title="Pseudo TCP Socket">Pseudo TCP Socket</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-is-closed-remotely" title="pseudo_tcp_socket_is_closed_remotely ()">pseudo_tcp_socket_is_closed_remotely</a>, function in <a class="link" href="libnice-Pseudo-TCP-Socket.html" title="Pseudo TCP Socket">Pseudo TCP Socket</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-new" title="pseudo_tcp_socket_new ()">pseudo_tcp_socket_new</a>, function in <a class="link" href="libnice-Pseudo-TCP-Socket.html" title="Pseudo TCP Socket">Pseudo TCP Socket</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-notify-clock" title="pseudo_tcp_socket_notify_clock ()">pseudo_tcp_socket_notify_clock</a>, function in <a class="link" href="libnice-Pseudo-TCP-Socket.html" title="Pseudo TCP Socket">Pseudo TCP Socket</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-notify-message" title="pseudo_tcp_socket_notify_message ()">pseudo_tcp_socket_notify_message</a>, function in <a class="link" href="libnice-Pseudo-TCP-Socket.html" title="Pseudo TCP Socket">Pseudo TCP Socket</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-notify-mtu" title="pseudo_tcp_socket_notify_mtu ()">pseudo_tcp_socket_notify_mtu</a>, function in <a class="link" href="libnice-Pseudo-TCP-Socket.html" title="Pseudo TCP Socket">Pseudo TCP Socket</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-notify-packet" title="pseudo_tcp_socket_notify_packet ()">pseudo_tcp_socket_notify_packet</a>, function in <a class="link" href="libnice-Pseudo-TCP-Socket.html" title="Pseudo TCP Socket">Pseudo TCP Socket</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-recv" title="pseudo_tcp_socket_recv ()">pseudo_tcp_socket_recv</a>, function in <a class="link" href="libnice-Pseudo-TCP-Socket.html" title="Pseudo TCP Socket">Pseudo TCP Socket</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-send" title="pseudo_tcp_socket_send ()">pseudo_tcp_socket_send</a>, function in <a class="link" href="libnice-Pseudo-TCP-Socket.html" title="Pseudo TCP Socket">Pseudo TCP Socket</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-set-time" title="pseudo_tcp_socket_set_time ()">pseudo_tcp_socket_set_time</a>, function in <a class="link" href="libnice-Pseudo-TCP-Socket.html" title="Pseudo TCP Socket">Pseudo TCP Socket</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-shutdown" title="pseudo_tcp_socket_shutdown ()">pseudo_tcp_socket_shutdown</a>, function in <a class="link" href="libnice-Pseudo-TCP-Socket.html" title="Pseudo TCP Socket">Pseudo TCP Socket</a>
+</dt>
+<dd></dd>
+<a name="idxR"></a><h3 class="title">R</h3>
+<dt>
+<a class="link" href="NiceCandidate.html#NiceRelayType" title="enum NiceRelayType">NiceRelayType</a>, enum in <a class="link" href="NiceCandidate.html" title="NiceCandidate">NiceCandidate</a>
+</dt>
+<dd></dd>
+<a name="idxS"></a><h3 class="title">S</h3>
+<dt>
+<a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent">StunAgent</a>, typedef in <a class="link" href="libnice-StunAgent.html" title="StunAgent">StunAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunAgent.html#StunAgentUsageFlags" title="enum StunAgentUsageFlags">StunAgentUsageFlags</a>, enum in <a class="link" href="libnice-StunAgent.html" title="StunAgent">StunAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute">StunAttribute</a>, enum in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#StunClass" title="enum StunClass">StunClass</a>, enum in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunAgent.html#StunCompatibility" title="enum StunCompatibility">StunCompatibility</a>, enum in <a class="link" href="libnice-StunAgent.html" title="StunAgent">StunAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunAgent.html#StunDebugHandler" title="StunDebugHandler ()">StunDebugHandler</a>, user_function in <a class="link" href="libnice-StunAgent.html" title="StunAgent">StunAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunAgent.html#StunDefaultValidaterData" title="StunDefaultValidaterData">StunDefaultValidaterData</a>, struct in <a class="link" href="libnice-StunAgent.html" title="StunAgent">StunAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#StunError" title="enum StunError">StunError</a>, enum in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#StunInputVector" title="StunInputVector">StunInputVector</a>, struct in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage">StunMessage</a>, struct in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunAgent.html#StunMessageIntegrityValidate" title="StunMessageIntegrityValidate ()">StunMessageIntegrityValidate</a>, user_function in <a class="link" href="libnice-StunAgent.html" title="StunAgent">StunAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn">StunMessageReturn</a>, enum in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#StunMethod" title="enum StunMethod">StunMethod</a>, enum in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Timer.html#StunTimer" title="StunTimer">StunTimer</a>, typedef in <a class="link" href="libnice-Timer.html" title="Timer">Timer</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#StunTransactionId" title="StunTransactionId">StunTransactionId</a>, typedef in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Bind.html#StunUsageBindReturn" title="enum StunUsageBindReturn">StunUsageBindReturn</a>, enum in <a class="link" href="libnice-Bind.html" title="Bind">Bind</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-ICE.html#StunUsageIceCompatibility" title="enum StunUsageIceCompatibility">StunUsageIceCompatibility</a>, enum in <a class="link" href="libnice-ICE.html" title="ICE">ICE</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-ICE.html#StunUsageIceReturn" title="enum StunUsageIceReturn">StunUsageIceReturn</a>, enum in <a class="link" href="libnice-ICE.html" title="ICE">ICE</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Timer.html#StunUsageTimerReturn" title="enum StunUsageTimerReturn">StunUsageTimerReturn</a>, enum in <a class="link" href="libnice-Timer.html" title="Timer">Timer</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-TURN.html#StunUsageTurnCompatibility" title="enum StunUsageTurnCompatibility">StunUsageTurnCompatibility</a>, enum in <a class="link" href="libnice-TURN.html" title="TURN">TURN</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-TURN.html#StunUsageTurnRequestPorts" title="enum StunUsageTurnRequestPorts">StunUsageTurnRequestPorts</a>, enum in <a class="link" href="libnice-TURN.html" title="TURN">TURN</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-TURN.html#StunUsageTurnReturn" title="enum StunUsageTurnReturn">StunUsageTurnReturn</a>, enum in <a class="link" href="libnice-TURN.html" title="TURN">TURN</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunAgent.html#StunValidationStatus" title="enum StunValidationStatus">StunValidationStatus</a>, enum in <a class="link" href="libnice-StunAgent.html" title="StunAgent">StunAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunAgent.html#stun-agent-build-unknown-attributes-error" title="stun_agent_build_unknown_attributes_error ()">stun_agent_build_unknown_attributes_error</a>, function in <a class="link" href="libnice-StunAgent.html" title="StunAgent">StunAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunAgent.html#stun-agent-default-validater" title="stun_agent_default_validater ()">stun_agent_default_validater</a>, function in <a class="link" href="libnice-StunAgent.html" title="StunAgent">StunAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunAgent.html#stun-agent-finish-message" title="stun_agent_finish_message ()">stun_agent_finish_message</a>, function in <a class="link" href="libnice-StunAgent.html" title="StunAgent">StunAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunAgent.html#stun-agent-forget-transaction" title="stun_agent_forget_transaction ()">stun_agent_forget_transaction</a>, function in <a class="link" href="libnice-StunAgent.html" title="StunAgent">StunAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunAgent.html#stun-agent-init" title="stun_agent_init ()">stun_agent_init</a>, function in <a class="link" href="libnice-StunAgent.html" title="StunAgent">StunAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunAgent.html#stun-agent-init-error" title="stun_agent_init_error ()">stun_agent_init_error</a>, function in <a class="link" href="libnice-StunAgent.html" title="StunAgent">StunAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunAgent.html#stun-agent-init-indication" title="stun_agent_init_indication ()">stun_agent_init_indication</a>, function in <a class="link" href="libnice-StunAgent.html" title="StunAgent">StunAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunAgent.html#stun-agent-init-request" title="stun_agent_init_request ()">stun_agent_init_request</a>, function in <a class="link" href="libnice-StunAgent.html" title="StunAgent">StunAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunAgent.html#stun-agent-init-response" title="stun_agent_init_response ()">stun_agent_init_response</a>, function in <a class="link" href="libnice-StunAgent.html" title="StunAgent">StunAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-STUN-Constants.html#STUN-AGENT-MAX-SAVED-IDS:CAPS" title="STUN_AGENT_MAX_SAVED_IDS">STUN_AGENT_MAX_SAVED_IDS</a>, macro in <a class="link" href="libnice-STUN-Constants.html" title="STUN Constants">STUN Constants</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-STUN-Constants.html#STUN-AGENT-MAX-UNKNOWN-ATTRIBUTES:CAPS" title="STUN_AGENT_MAX_UNKNOWN_ATTRIBUTES">STUN_AGENT_MAX_UNKNOWN_ATTRIBUTES</a>, macro in <a class="link" href="libnice-STUN-Constants.html" title="STUN Constants">STUN Constants</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunAgent.html#stun-agent-set-software" title="stun_agent_set_software ()">stun_agent_set_software</a>, function in <a class="link" href="libnice-StunAgent.html" title="StunAgent">StunAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunAgent.html#stun-agent-validate" title="stun_agent_validate ()">stun_agent_validate</a>, function in <a class="link" href="libnice-StunAgent.html" title="StunAgent">StunAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-STUN-Constants.html#STUN-ATTRIBUTE-HEADER-LENGTH:CAPS" title="STUN_ATTRIBUTE_HEADER_LENGTH">STUN_ATTRIBUTE_HEADER_LENGTH</a>, macro in <a class="link" href="libnice-STUN-Constants.html" title="STUN Constants">STUN Constants</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-STUN-Constants.html#STUN-ATTRIBUTE-LENGTH-LEN:CAPS" title="STUN_ATTRIBUTE_LENGTH_LEN">STUN_ATTRIBUTE_LENGTH_LEN</a>, macro in <a class="link" href="libnice-STUN-Constants.html" title="STUN Constants">STUN Constants</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-STUN-Constants.html#STUN-ATTRIBUTE-LENGTH-POS:CAPS" title="STUN_ATTRIBUTE_LENGTH_POS">STUN_ATTRIBUTE_LENGTH_POS</a>, macro in <a class="link" href="libnice-STUN-Constants.html" title="STUN Constants">STUN Constants</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-STUN-Constants.html#STUN-ATTRIBUTE-TYPE-LEN:CAPS" title="STUN_ATTRIBUTE_TYPE_LEN">STUN_ATTRIBUTE_TYPE_LEN</a>, macro in <a class="link" href="libnice-STUN-Constants.html" title="STUN Constants">STUN Constants</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-STUN-Constants.html#STUN-ATTRIBUTE-TYPE-POS:CAPS" title="STUN_ATTRIBUTE_TYPE_POS">STUN_ATTRIBUTE_TYPE_POS</a>, macro in <a class="link" href="libnice-STUN-Constants.html" title="STUN Constants">STUN Constants</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-STUN-Constants.html#STUN-ATTRIBUTE-VALUE-POS:CAPS" title="STUN_ATTRIBUTE_VALUE_POS">STUN_ATTRIBUTE_VALUE_POS</a>, macro in <a class="link" href="libnice-STUN-Constants.html" title="STUN Constants">STUN Constants</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunAgent.html#stun-debug-disable" title="stun_debug_disable ()">stun_debug_disable</a>, function in <a class="link" href="libnice-StunAgent.html" title="StunAgent">StunAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunAgent.html#stun-debug-enable" title="stun_debug_enable ()">stun_debug_enable</a>, function in <a class="link" href="libnice-StunAgent.html" title="StunAgent">StunAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-STUN-Constants.html#STUN-ID-LEN:CAPS" title="STUN_ID_LEN">STUN_ID_LEN</a>, macro in <a class="link" href="libnice-STUN-Constants.html" title="STUN Constants">STUN Constants</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-STUN-Constants.html#STUN-MAGIC-COOKIE:CAPS" title="STUN_MAGIC_COOKIE">STUN_MAGIC_COOKIE</a>, macro in <a class="link" href="libnice-STUN-Constants.html" title="STUN Constants">STUN Constants</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-STUN-Constants.html#STUN-MAX-MESSAGE-SIZE:CAPS" title="STUN_MAX_MESSAGE_SIZE">STUN_MAX_MESSAGE_SIZE</a>, macro in <a class="link" href="libnice-STUN-Constants.html" title="STUN Constants">STUN Constants</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-STUN-Constants.html#STUN-MAX-MESSAGE-SIZE-IPV4:CAPS" title="STUN_MAX_MESSAGE_SIZE_IPV4">STUN_MAX_MESSAGE_SIZE_IPV4</a>, macro in <a class="link" href="libnice-STUN-Constants.html" title="STUN Constants">STUN Constants</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-STUN-Constants.html#STUN-MAX-MESSAGE-SIZE-IPV6:CAPS" title="STUN_MAX_MESSAGE_SIZE_IPV6">STUN_MAX_MESSAGE_SIZE_IPV6</a>, macro in <a class="link" href="libnice-STUN-Constants.html" title="STUN Constants">STUN Constants</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#stun-message-append" title="stun_message_append ()">stun_message_append</a>, function in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#stun-message-append32" title="stun_message_append32 ()">stun_message_append32</a>, function in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#stun-message-append64" title="stun_message_append64 ()">stun_message_append64</a>, function in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#stun-message-append-addr" title="stun_message_append_addr ()">stun_message_append_addr</a>, function in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#stun-message-append-bytes" title="stun_message_append_bytes ()">stun_message_append_bytes</a>, function in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#stun-message-append-error" title="stun_message_append_error ()">stun_message_append_error</a>, function in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#stun-message-append-flag" title="stun_message_append_flag ()">stun_message_append_flag</a>, function in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#stun-message-append-string" title="stun_message_append_string ()">stun_message_append_string</a>, function in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#stun-message-append-xor-addr" title="stun_message_append_xor_addr ()">stun_message_append_xor_addr</a>, function in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#stun-message-append-xor-addr-full" title="stun_message_append_xor_addr_full ()">stun_message_append_xor_addr_full</a>, function in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-STUN-Constants.html#STUN-MESSAGE-ATTRIBUTES-POS:CAPS" title="STUN_MESSAGE_ATTRIBUTES_POS">STUN_MESSAGE_ATTRIBUTES_POS</a>, macro in <a class="link" href="libnice-STUN-Constants.html" title="STUN Constants">STUN Constants</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#STUN-MESSAGE-BUFFER-INCOMPLETE:CAPS" title="STUN_MESSAGE_BUFFER_INCOMPLETE">STUN_MESSAGE_BUFFER_INCOMPLETE</a>, macro in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#STUN-MESSAGE-BUFFER-INVALID:CAPS" title="STUN_MESSAGE_BUFFER_INVALID">STUN_MESSAGE_BUFFER_INVALID</a>, macro in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#stun-message-find" title="stun_message_find ()">stun_message_find</a>, function in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#stun-message-find32" title="stun_message_find32 ()">stun_message_find32</a>, function in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#stun-message-find64" title="stun_message_find64 ()">stun_message_find64</a>, function in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#stun-message-find-addr" title="stun_message_find_addr ()">stun_message_find_addr</a>, function in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#stun-message-find-error" title="stun_message_find_error ()">stun_message_find_error</a>, function in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#stun-message-find-flag" title="stun_message_find_flag ()">stun_message_find_flag</a>, function in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#stun-message-find-string" title="stun_message_find_string ()">stun_message_find_string</a>, function in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#stun-message-find-xor-addr" title="stun_message_find_xor_addr ()">stun_message_find_xor_addr</a>, function in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#stun-message-find-xor-addr-full" title="stun_message_find_xor_addr_full ()">stun_message_find_xor_addr_full</a>, function in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#stun-message-get-class" title="stun_message_get_class ()">stun_message_get_class</a>, function in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#stun-message-get-method" title="stun_message_get_method ()">stun_message_get_method</a>, function in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#stun-message-has-attribute" title="stun_message_has_attribute ()">stun_message_has_attribute</a>, function in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#stun-message-has-cookie" title="stun_message_has_cookie ()">stun_message_has_cookie</a>, function in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-STUN-Constants.html#STUN-MESSAGE-HEADER-LENGTH:CAPS" title="STUN_MESSAGE_HEADER_LENGTH">STUN_MESSAGE_HEADER_LENGTH</a>, macro in <a class="link" href="libnice-STUN-Constants.html" title="STUN Constants">STUN Constants</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#stun-message-id" title="stun_message_id ()">stun_message_id</a>, function in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#stun-message-init" title="stun_message_init ()">stun_message_init</a>, function in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#stun-message-length" title="stun_message_length ()">stun_message_length</a>, function in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-STUN-Constants.html#STUN-MESSAGE-LENGTH-LEN:CAPS" title="STUN_MESSAGE_LENGTH_LEN">STUN_MESSAGE_LENGTH_LEN</a>, macro in <a class="link" href="libnice-STUN-Constants.html" title="STUN Constants">STUN Constants</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-STUN-Constants.html#STUN-MESSAGE-LENGTH-POS:CAPS" title="STUN_MESSAGE_LENGTH_POS">STUN_MESSAGE_LENGTH_POS</a>, macro in <a class="link" href="libnice-STUN-Constants.html" title="STUN Constants">STUN Constants</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-STUN-Constants.html#STUN-MESSAGE-TRANS-ID-LEN:CAPS" title="STUN_MESSAGE_TRANS_ID_LEN">STUN_MESSAGE_TRANS_ID_LEN</a>, macro in <a class="link" href="libnice-STUN-Constants.html" title="STUN Constants">STUN Constants</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-STUN-Constants.html#STUN-MESSAGE-TRANS-ID-POS:CAPS" title="STUN_MESSAGE_TRANS_ID_POS">STUN_MESSAGE_TRANS_ID_POS</a>, macro in <a class="link" href="libnice-STUN-Constants.html" title="STUN Constants">STUN Constants</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-STUN-Constants.html#STUN-MESSAGE-TYPE-LEN:CAPS" title="STUN_MESSAGE_TYPE_LEN">STUN_MESSAGE_TYPE_LEN</a>, macro in <a class="link" href="libnice-STUN-Constants.html" title="STUN Constants">STUN Constants</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-STUN-Constants.html#STUN-MESSAGE-TYPE-POS:CAPS" title="STUN_MESSAGE_TYPE_POS">STUN_MESSAGE_TYPE_POS</a>, macro in <a class="link" href="libnice-STUN-Constants.html" title="STUN Constants">STUN Constants</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#stun-message-validate-buffer-length" title="stun_message_validate_buffer_length ()">stun_message_validate_buffer_length</a>, function in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#stun-message-validate-buffer-length-fast" title="stun_message_validate_buffer_length_fast ()">stun_message_validate_buffer_length_fast</a>, function in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#stun-optional" title="stun_optional ()">stun_optional</a>, function in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunAgent.html#stun-set-debug-handler" title="stun_set_debug_handler ()">stun_set_debug_handler</a>, function in <a class="link" href="libnice-StunAgent.html" title="StunAgent">StunAgent</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-StunMessage.html#stun-strerror" title="stun_strerror ()">stun_strerror</a>, function in <a class="link" href="libnice-StunMessage.html" title="StunMessage">StunMessage</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Timer.html#STUN-TIMER-DEFAULT-MAX-RETRANSMISSIONS:CAPS" title="STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS">STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS</a>, macro in <a class="link" href="libnice-Timer.html" title="Timer">Timer</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Timer.html#STUN-TIMER-DEFAULT-RELIABLE-TIMEOUT:CAPS" title="STUN_TIMER_DEFAULT_RELIABLE_TIMEOUT">STUN_TIMER_DEFAULT_RELIABLE_TIMEOUT</a>, macro in <a class="link" href="libnice-Timer.html" title="Timer">Timer</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Timer.html#STUN-TIMER-DEFAULT-TIMEOUT:CAPS" title="STUN_TIMER_DEFAULT_TIMEOUT">STUN_TIMER_DEFAULT_TIMEOUT</a>, macro in <a class="link" href="libnice-Timer.html" title="Timer">Timer</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Timer.html#stun-timer-refresh" title="stun_timer_refresh ()">stun_timer_refresh</a>, function in <a class="link" href="libnice-Timer.html" title="Timer">Timer</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Timer.html#stun-timer-remainder" title="stun_timer_remainder ()">stun_timer_remainder</a>, function in <a class="link" href="libnice-Timer.html" title="Timer">Timer</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Timer.html#stun-timer-start" title="stun_timer_start ()">stun_timer_start</a>, function in <a class="link" href="libnice-Timer.html" title="Timer">Timer</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Timer.html#stun-timer-start-reliable" title="stun_timer_start_reliable ()">stun_timer_start_reliable</a>, function in <a class="link" href="libnice-Timer.html" title="Timer">Timer</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Bind.html#stun-usage-bind-create" title="stun_usage_bind_create ()">stun_usage_bind_create</a>, function in <a class="link" href="libnice-Bind.html" title="Bind">Bind</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Bind.html#stun-usage-bind-keepalive" title="stun_usage_bind_keepalive ()">stun_usage_bind_keepalive</a>, function in <a class="link" href="libnice-Bind.html" title="Bind">Bind</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Bind.html#stun-usage-bind-process" title="stun_usage_bind_process ()">stun_usage_bind_process</a>, function in <a class="link" href="libnice-Bind.html" title="Bind">Bind</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-Bind.html#stun-usage-bind-run" title="stun_usage_bind_run ()">stun_usage_bind_run</a>, function in <a class="link" href="libnice-Bind.html" title="Bind">Bind</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-ICE.html#stun-usage-ice-conncheck-create" title="stun_usage_ice_conncheck_create ()">stun_usage_ice_conncheck_create</a>, function in <a class="link" href="libnice-ICE.html" title="ICE">ICE</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-ICE.html#stun-usage-ice-conncheck-create-reply" title="stun_usage_ice_conncheck_create_reply ()">stun_usage_ice_conncheck_create_reply</a>, function in <a class="link" href="libnice-ICE.html" title="ICE">ICE</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-ICE.html#stun-usage-ice-conncheck-priority" title="stun_usage_ice_conncheck_priority ()">stun_usage_ice_conncheck_priority</a>, function in <a class="link" href="libnice-ICE.html" title="ICE">ICE</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-ICE.html#stun-usage-ice-conncheck-process" title="stun_usage_ice_conncheck_process ()">stun_usage_ice_conncheck_process</a>, function in <a class="link" href="libnice-ICE.html" title="ICE">ICE</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-ICE.html#stun-usage-ice-conncheck-use-candidate" title="stun_usage_ice_conncheck_use_candidate ()">stun_usage_ice_conncheck_use_candidate</a>, function in <a class="link" href="libnice-ICE.html" title="ICE">ICE</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-TURN.html#stun-usage-turn-create" title="stun_usage_turn_create ()">stun_usage_turn_create</a>, function in <a class="link" href="libnice-TURN.html" title="TURN">TURN</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-TURN.html#stun-usage-turn-create-permission" title="stun_usage_turn_create_permission ()">stun_usage_turn_create_permission</a>, function in <a class="link" href="libnice-TURN.html" title="TURN">TURN</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-TURN.html#stun-usage-turn-create-refresh" title="stun_usage_turn_create_refresh ()">stun_usage_turn_create_refresh</a>, function in <a class="link" href="libnice-TURN.html" title="TURN">TURN</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-TURN.html#stun-usage-turn-process" title="stun_usage_turn_process ()">stun_usage_turn_process</a>, function in <a class="link" href="libnice-TURN.html" title="TURN">TURN</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-TURN.html#stun-usage-turn-refresh-process" title="stun_usage_turn_refresh_process ()">stun_usage_turn_refresh_process</a>, function in <a class="link" href="libnice-TURN.html" title="TURN">TURN</a>
+</dt>
+<dd></dd>
+<a name="idxT"></a><h3 class="title">T</h3>
+<dt>
+<a class="link" href="NiceCandidate.html#TurnServer" title="struct TurnServer">TurnServer</a>, struct in <a class="link" href="NiceCandidate.html" title="NiceCandidate">NiceCandidate</a>
+</dt>
+<dd></dd>
+<dt>
+<a class="link" href="libnice-STUN-Constants.html#TURN-MAGIC-COOKIE:CAPS" title="TURN_MAGIC_COOKIE">TURN_MAGIC_COOKIE</a>, macro in <a class="link" href="libnice-STUN-Constants.html" title="STUN Constants">STUN Constants</a>
+</dt>
+<dd></dd>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.29</div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>: libnice Reference Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets Vsnapshot">
+<link rel="home" href="index.html" title="libnice Reference Manual">
+<link rel="up" href="pt01.html" title="Part I. ICE Library">
+<link rel="prev" href="pt01.html" title="Part I. ICE Library">
+<link rel="next" href="NiceAgent.html" title="NiceAgent">
+<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="pt01.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="pt01.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="NiceAgent.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="chapter">
+<div class="titlepage"></div>
+<div class="toc"><dl class="toc">
+<dt>
+<span class="refentrytitle"><a href="NiceAgent.html">NiceAgent</a></span><span class="refpurpose"> — ICE agent API implementation</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="libnice-NiceAddress.html">NiceAddress</a></span><span class="refpurpose"> — IP address convenience library</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="NiceCandidate.html">NiceCandidate</a></span><span class="refpurpose"> — ICE candidate representation</span>
+</dt>
+</dl></div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.29</div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Libnice helper functions: libnice Reference Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets Vsnapshot">
+<link rel="home" href="index.html" title="libnice Reference Manual">
+<link rel="up" href="pt01.html" title="Part I. ICE Library">
+<link rel="prev" href="NiceCandidate.html" title="NiceCandidate">
+<link rel="next" href="libnice-Debug-messages.html" title="Debug messages">
+<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="pt01.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="NiceCandidate.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="libnice-Debug-messages.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="chapter">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="id-1.2.3"></a>Libnice helper functions</h2></div></div></div>
+<div class="toc"><dl class="toc">
+<dt>
+<span class="refentrytitle"><a href="libnice-Debug-messages.html">Debug messages</a></span><span class="refpurpose"> — Debug messages utility functions</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="libnice-Network-interfaces-discovery.html">Network interfaces discovery</a></span><span class="refpurpose"> — Utility functions to discover local network interfaces</span>
+</dt>
+</dl></div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.29</div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>: libnice Reference Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets Vsnapshot">
+<link rel="home" href="index.html" title="libnice Reference Manual">
+<link rel="up" href="pt02.html" title="Part II. STUN Library">
+<link rel="prev" href="pt02.html" title="Part II. STUN Library">
+<link rel="next" href="libnice-StunAgent.html" title="StunAgent">
+<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="pt02.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="libnice-StunAgent.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="chapter">
+<div class="titlepage"></div>
+<div class="toc"><dl class="toc">
+<dt>
+<span class="refentrytitle"><a href="libnice-StunAgent.html">StunAgent</a></span><span class="refpurpose"> — STUN agent for building and validating STUN messages</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="libnice-StunMessage.html">StunMessage</a></span><span class="refpurpose"> — STUN messages parsing and formatting functions</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="libnice-STUN-Constants.html">STUN Constants</a></span><span class="refpurpose"> — STUN constants</span>
+</dt>
+</dl></div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.29</div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>STUN usages: libnice Reference Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets Vsnapshot">
+<link rel="home" href="index.html" title="libnice Reference Manual">
+<link rel="up" href="pt02.html" title="Part II. STUN Library">
+<link rel="prev" href="libnice-STUN-Constants.html" title="STUN Constants">
+<link rel="next" href="libnice-Bind.html" title="Bind">
+<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="pt02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="libnice-STUN-Constants.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="libnice-Bind.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="chapter">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="id-1.3.3"></a>STUN usages</h2></div></div></div>
+<div class="toc"><dl class="toc">
+<dt>
+<span class="refentrytitle"><a href="libnice-Bind.html">Bind</a></span><span class="refpurpose"> — STUN Binding Usage</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="libnice-ICE.html">ICE</a></span><span class="refpurpose"> — STUN ICE Usage</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="libnice-TURN.html">TURN</a></span><span class="refpurpose"> — TURN Allocation Usage</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="libnice-Timer.html">Timer</a></span><span class="refpurpose"> — STUN timer Usage</span>
+</dt>
+</dl></div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.29</div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>: libnice Reference Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets Vsnapshot">
+<link rel="home" href="index.html" title="libnice Reference Manual">
+<link rel="up" href="pt03.html" title="Part III. Pseudo TCP Socket implementation">
+<link rel="prev" href="pt03.html" title="Part III. Pseudo TCP Socket implementation">
+<link rel="next" href="libnice-Pseudo-TCP-Socket.html" title="Pseudo TCP Socket">
+<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="pt03.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="pt03.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="libnice-Pseudo-TCP-Socket.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="chapter">
+<div class="titlepage"></div>
+<div class="toc"><dl class="toc"><dt>
+<span class="refentrytitle"><a href="libnice-Pseudo-TCP-Socket.html">Pseudo TCP Socket</a></span><span class="refpurpose"> — Pseudo TCP implementation</span>
+</dt></dl></div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.29</div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>libnice Reference Manual: libnice Reference Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets Vsnapshot">
+<link rel="home" href="index.html" title="libnice Reference Manual">
+<link rel="next" href="pt01.html" title="Part I. ICE Library">
+<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<div class="book">
+<div class="titlepage">
+<div>
+<div><table class="navigation" id="top" width="100%" cellpadding="2" cellspacing="0"><tr><th valign="middle"><p class="title">libnice Reference Manual</p></th></tr></table></div>
+<div><p class="releaseinfo">
+ The latest version of this documentation can be found on-line at
+ <a class="ulink" href="http://nice.freedesktop.org/libnice/index.html" target="_top">http://nice.freedesktop.org/libnice/</a>.
+ </p></div>
+</div>
+<hr>
+</div>
+<div class="toc"><dl class="toc">
+<dt><span class="part"><a href="pt01.html">I. ICE Library</a></span></dt>
+<dd><dl>
+<dt><span class="chapter"><a href="ch01.html"></a></span></dt>
+<dd><dl>
+<dt>
+<span class="refentrytitle"><a href="NiceAgent.html">NiceAgent</a></span><span class="refpurpose"> — ICE agent API implementation</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="libnice-NiceAddress.html">NiceAddress</a></span><span class="refpurpose"> — IP address convenience library</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="NiceCandidate.html">NiceCandidate</a></span><span class="refpurpose"> — ICE candidate representation</span>
+</dt>
+</dl></dd>
+<dt><span class="chapter"><a href="ch02.html">Libnice helper functions</a></span></dt>
+<dd><dl>
+<dt>
+<span class="refentrytitle"><a href="libnice-Debug-messages.html">Debug messages</a></span><span class="refpurpose"> — Debug messages utility functions</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="libnice-Network-interfaces-discovery.html">Network interfaces discovery</a></span><span class="refpurpose"> — Utility functions to discover local network interfaces</span>
+</dt>
+</dl></dd>
+</dl></dd>
+<dt><span class="part"><a href="pt02.html">II. STUN Library</a></span></dt>
+<dd><dl>
+<dt><span class="chapter"><a href="ch03.html"></a></span></dt>
+<dd><dl>
+<dt>
+<span class="refentrytitle"><a href="libnice-StunAgent.html">StunAgent</a></span><span class="refpurpose"> — STUN agent for building and validating STUN messages</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="libnice-StunMessage.html">StunMessage</a></span><span class="refpurpose"> — STUN messages parsing and formatting functions</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="libnice-STUN-Constants.html">STUN Constants</a></span><span class="refpurpose"> — STUN constants</span>
+</dt>
+</dl></dd>
+<dt><span class="chapter"><a href="ch04.html">STUN usages</a></span></dt>
+<dd><dl>
+<dt>
+<span class="refentrytitle"><a href="libnice-Bind.html">Bind</a></span><span class="refpurpose"> — STUN Binding Usage</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="libnice-ICE.html">ICE</a></span><span class="refpurpose"> — STUN ICE Usage</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="libnice-TURN.html">TURN</a></span><span class="refpurpose"> — TURN Allocation Usage</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="libnice-Timer.html">Timer</a></span><span class="refpurpose"> — STUN timer Usage</span>
+</dt>
+</dl></dd>
+</dl></dd>
+<dt><span class="part"><a href="pt03.html">III. Pseudo TCP Socket implementation</a></span></dt>
+<dd><dl>
+<dt><span class="chapter"><a href="ch05.html"></a></span></dt>
+<dd><dl><dt>
+<span class="refentrytitle"><a href="libnice-Pseudo-TCP-Socket.html">Pseudo TCP Socket</a></span><span class="refpurpose"> — Pseudo TCP implementation</span>
+</dt></dl></dd>
+</dl></dd>
+<dt><span class="part"><a href="pt04.html">IV. Appendices</a></span></dt>
+<dd><dl>
+<dt><span class="index"><a href="api-index-full.html">API Index</a></span></dt>
+<dt><span class="index"><a href="api-index-deprecated.html">Index of deprecated symbols</a></span></dt>
+<dt><span class="glossary"><a href="annotation-glossary.html">Annotation Glossary</a></span></dt>
+</dl></dd>
+</dl></div>
+<p>The libnice library contains the ICE library and the
+ STUN library as well as a Pseudo TCP socket implementation.
+ </p>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.29</div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Bind: libnice Reference Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets Vsnapshot">
+<link rel="home" href="index.html" title="libnice Reference Manual">
+<link rel="up" href="ch04.html" title="STUN usages">
+<link rel="prev" href="ch04.html" title="STUN usages">
+<link rel="next" href="libnice-ICE.html" title="ICE">
+<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts">
+<a href="#" class="shortcut">Top</a><span id="nav_description"> <span class="dim">|</span>
+ <a href="#libnice-Bind.description" class="shortcut">Description</a></span>
+</td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="ch04.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="ch04.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="libnice-ICE.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="refentry">
+<a name="libnice-Bind"></a><div class="titlepage"></div>
+<div class="refnamediv"><table width="100%"><tr>
+<td valign="top">
+<h2><span class="refentrytitle"><a name="libnice-Bind.top_of_page"></a>Bind</span></h2>
+<p>Bind — STUN Binding Usage</p>
+</td>
+<td class="gallery_image" valign="top" align="right"></td>
+</tr></table></div>
+<div class="refsect1">
+<a name="libnice-Bind.stability-level"></a><h2>Stability Level</h2>
+<acronym title="The intention of a Stable interface is to enable arbitrary third parties to
+develop applications to these interfaces, release them, and have confidence that
+they will run on all minor releases of the product (after the one in which the
+interface was introduced, and within the same major release). Even at a major
+release, incompatible changes are expected to be rare, and to have strong
+justifications.
+"><span class="acronym">Stable</span></acronym>, unless otherwise indicated
+</div>
+<div class="refsect1">
+<a name="libnice-Bind.functions"></a><h2>Functions</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="functions_return">
+<col class="functions_name">
+</colgroup>
+<tbody>
+<tr>
+<td class="function_type">
+<span class="returnvalue">size_t</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-Bind.html#stun-usage-bind-create" title="stun_usage_bind_create ()">stun_usage_bind_create</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="libnice-Bind.html#StunUsageBindReturn" title="enum StunUsageBindReturn"><span class="returnvalue">StunUsageBindReturn</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-Bind.html#stun-usage-bind-process" title="stun_usage_bind_process ()">stun_usage_bind_process</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">size_t</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-Bind.html#stun-usage-bind-keepalive" title="stun_usage_bind_keepalive ()">stun_usage_bind_keepalive</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="libnice-Bind.html#StunUsageBindReturn" title="enum StunUsageBindReturn"><span class="returnvalue">StunUsageBindReturn</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-Bind.html#stun-usage-bind-run" title="stun_usage_bind_run ()">stun_usage_bind_run</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect1">
+<a name="libnice-Bind.other"></a><h2>Types and Values</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="name">
+<col class="description">
+</colgroup>
+<tbody><tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="libnice-Bind.html#StunUsageBindReturn" title="enum StunUsageBindReturn">StunUsageBindReturn</a></td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect1">
+<a name="libnice-Bind.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include <stun/usages/bind.h>
+</pre>
+</div>
+<div class="refsect1">
+<a name="libnice-Bind.description"></a><h2>Description</h2>
+<p>The STUN Binding usage allows for easily creating and parsing STUN Binding
+requests and responses. It offers both an asynchronous and a synchronous API
+that uses the STUN timer usage.</p>
+</div>
+<div class="refsect1">
+<a name="libnice-Bind.functions_details"></a><h2>Functions</h2>
+<div class="refsect2">
+<a name="stun-usage-bind-create"></a><h3>stun_usage_bind_create ()</h3>
+<pre class="programlisting"><span class="returnvalue">size_t</span>
+stun_usage_bind_create (<em class="parameter"><code><a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><span class="type">uint8_t</span> *buffer</code></em>,
+ <em class="parameter"><code><span class="type">size_t</span> buffer_len</code></em>);</pre>
+<p>Create a new STUN binding request to use with a STUN server.</p>
+<div class="refsect3">
+<a name="stun-usage-bind-create.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a> to use to create the binding request</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> to build</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>The buffer to use for creating the <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buffer_len</p></td>
+<td class="parameter_description"><p>The size of the <em class="parameter"><code>buffer</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-usage-bind-create.returns"></a><h4>Returns</h4>
+<p> The length of the built message.</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-usage-bind-process"></a><h3>stun_usage_bind_process ()</h3>
+<pre class="programlisting"><a class="link" href="libnice-Bind.html#StunUsageBindReturn" title="enum StunUsageBindReturn"><span class="returnvalue">StunUsageBindReturn</span></a>
+stun_usage_bind_process (<em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><span class="type">struct sockaddr</span> *addr</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/camel/camel-camel-net-utils.html#socklen-t"><span class="type">socklen_t</span></a> *addrlen</code></em>,
+ <em class="parameter"><code><span class="type">struct sockaddr</span> *alternate_server</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/camel/camel-camel-net-utils.html#socklen-t"><span class="type">socklen_t</span></a> *alternate_server_len</code></em>);</pre>
+<p>Process a STUN binding response and extracts the mapped address from the STUN
+message. Also checks for the ALTERNATE-SERVER attribute.</p>
+<div class="refsect3">
+<a name="stun-usage-bind-process.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> to process</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>addr</p></td>
+<td class="parameter_description"><p>A pointer to a <a href="/usr/share/gtk-doc/html/camel/camel-camel-net-utils.html#sockaddr"><span class="type">sockaddr</span></a> structure to fill with the mapped address
+that the STUN server gives us</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>addrlen</p></td>
+<td class="parameter_description"><p>The length of <em class="parameter"><code>add</code></em>
+. rMust be set to the size of the <em class="parameter"><code>addr</code></em>
+socket
+address and will be set to the actual length of the socket address.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>alternate_server</p></td>
+<td class="parameter_description"><p>A pointer to a <a href="/usr/share/gtk-doc/html/camel/camel-camel-net-utils.html#sockaddr"><span class="type">sockaddr</span></a> structure to fill with the
+address of an alternate server to which we should send our new STUN
+binding request, in case the currently used STUN server is requesting the use
+of an alternate server. This argument will only be filled if the return value
+of the function is <a class="link" href="libnice-Bind.html#STUN-USAGE-BIND-RETURN-ALTERNATE-SERVER:CAPS"><span class="type">STUN_USAGE_BIND_RETURN_ALTERNATE_SERVER</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>alternate_server_len</p></td>
+<td class="parameter_description"><p>The length of <em class="parameter"><code>alternate_server</code></em>
+. Must be set to
+the size of the <em class="parameter"><code>alternate_server</code></em>
+socket address and will be set to the
+actual length of the socket address.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-usage-bind-process.returns"></a><h4>Returns</h4>
+<p> A <a class="link" href="libnice-Bind.html#StunUsageBindReturn" title="enum StunUsageBindReturn"><span class="type">StunUsageBindReturn</span></a> value.
+Note that <a class="link" href="libnice-Bind.html#STUN-USAGE-BIND-RETURN-TIMEOUT:CAPS"><span class="type">STUN_USAGE_BIND_RETURN_TIMEOUT</span></a> cannot be returned by this function</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-usage-bind-keepalive"></a><h3>stun_usage_bind_keepalive ()</h3>
+<pre class="programlisting"><span class="returnvalue">size_t</span>
+stun_usage_bind_keepalive (<em class="parameter"><code><a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><span class="type">uint8_t</span> *buf</code></em>,
+ <em class="parameter"><code><span class="type">size_t</span> len</code></em>);</pre>
+<p>Creates a STUN binding indication that can be used for a keepalive.
+Since this is an indication message, no STUN response will be generated
+and it can only be used as a keepalive message.</p>
+<div class="refsect3">
+<a name="stun-usage-bind-keepalive.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a> to use to build the message</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> to build</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buf</p></td>
+<td class="parameter_description"><p>The buffer to use for creating the <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>len</p></td>
+<td class="parameter_description"><p>The size of the <em class="parameter"><code>buf</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-usage-bind-keepalive.returns"></a><h4>Returns</h4>
+<p> The length of the message to send</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-usage-bind-run"></a><h3>stun_usage_bind_run ()</h3>
+<pre class="programlisting"><a class="link" href="libnice-Bind.html#StunUsageBindReturn" title="enum StunUsageBindReturn"><span class="returnvalue">StunUsageBindReturn</span></a>
+stun_usage_bind_run (<em class="parameter"><code>const <span class="type">struct sockaddr</span> *srv</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/camel/camel-camel-net-utils.html#socklen-t"><span class="type">socklen_t</span></a> srvlen</code></em>,
+ <em class="parameter"><code><span class="type">struct sockaddr_storage</span> *addr</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/camel/camel-camel-net-utils.html#socklen-t"><span class="type">socklen_t</span></a> *addrlen</code></em>);</pre>
+<p>This is a convenience function that will do a synchronous Binding request to
+a server and wait for its answer. It will create the socket transports and
+use the <a class="link" href="libnice-Timer.html#StunTimer" title="StunTimer"><span class="type">StunTimer</span></a> usage to send the request and handle the response.</p>
+<div class="refsect3">
+<a name="stun-usage-bind-run.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>srv</p></td>
+<td class="parameter_description"><p>A pointer to the <a href="/usr/share/gtk-doc/html/camel/camel-camel-net-utils.html#sockaddr"><span class="type">sockaddr</span></a> structure representing the STUN server's
+address</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>srvlen</p></td>
+<td class="parameter_description"><p>The length of <em class="parameter"><code>srv</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>addr</p></td>
+<td class="parameter_description"><p>A pointer to a <a href="/usr/share/gtk-doc/html/camel/camel-camel-net-utils.html#sockaddr"><span class="type">sockaddr</span></a> structure to fill with the mapped address
+that the STUN server gives us</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>addrlen</p></td>
+<td class="parameter_description"><p>The length of <em class="parameter"><code>addr</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-usage-bind-run.returns"></a><h4>Returns</h4>
+<p> A <a class="link" href="libnice-Bind.html#StunUsageBindReturn" title="enum StunUsageBindReturn"><span class="type">StunUsageBindReturn</span></a>.
+Possible return values are <a class="link" href="libnice-Bind.html#STUN-USAGE-BIND-RETURN-SUCCESS:CAPS"><span class="type">STUN_USAGE_BIND_RETURN_SUCCESS</span></a>,
+<a class="link" href="libnice-Bind.html#STUN-USAGE-BIND-RETURN-ERROR:CAPS"><span class="type">STUN_USAGE_BIND_RETURN_ERROR</span></a> and <a class="link" href="libnice-Bind.html#STUN-USAGE-BIND-RETURN-TIMEOUT:CAPS"><span class="type">STUN_USAGE_BIND_RETURN_TIMEOUT</span></a></p>
+</div>
+</div>
+</div>
+<div class="refsect1">
+<a name="libnice-Bind.other_details"></a><h2>Types and Values</h2>
+<div class="refsect2">
+<a name="StunUsageBindReturn"></a><h3>enum StunUsageBindReturn</h3>
+<p>Return value of <a class="link" href="libnice-Bind.html#stun-usage-bind-process" title="stun_usage_bind_process ()"><code class="function">stun_usage_bind_process()</code></a> and <a class="link" href="libnice-Bind.html#stun-usage-bind-run" title="stun_usage_bind_run ()"><code class="function">stun_usage_bind_run()</code></a> which
+allows you to see what status the function call returned.</p>
+<div class="refsect3">
+<a name="StunUsageBindReturn.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-USAGE-BIND-RETURN-SUCCESS:CAPS"></a>STUN_USAGE_BIND_RETURN_SUCCESS</p></td>
+<td class="enum_member_description">
+<p>The binding usage succeeded</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-USAGE-BIND-RETURN-ERROR:CAPS"></a>STUN_USAGE_BIND_RETURN_ERROR</p></td>
+<td class="enum_member_description">
+<p>There was an unknown error in the bind usage</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-USAGE-BIND-RETURN-INVALID:CAPS"></a>STUN_USAGE_BIND_RETURN_INVALID</p></td>
+<td class="enum_member_description">
+<p>The message is invalid and should be ignored</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-USAGE-BIND-RETURN-ALTERNATE-SERVER:CAPS"></a>STUN_USAGE_BIND_RETURN_ALTERNATE_SERVER</p></td>
+<td class="enum_member_description">
+<p>The binding request has an
+ALTERNATE-SERVER attribute</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-USAGE-BIND-RETURN-TIMEOUT:CAPS"></a>STUN_USAGE_BIND_RETURN_TIMEOUT</p></td>
+<td class="enum_member_description">
+<p>The binding was unsuccessful because it has
+timed out.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+</div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.29</div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Debug messages: libnice Reference Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets Vsnapshot">
+<link rel="home" href="index.html" title="libnice Reference Manual">
+<link rel="up" href="ch02.html" title="Libnice helper functions">
+<link rel="prev" href="ch02.html" title="Libnice helper functions">
+<link rel="next" href="libnice-Network-interfaces-discovery.html" title="Network interfaces discovery">
+<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts">
+<a href="#" class="shortcut">Top</a><span id="nav_description"> <span class="dim">|</span>
+ <a href="#libnice-Debug-messages.description" class="shortcut">Description</a></span>
+</td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="ch02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="ch02.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="libnice-Network-interfaces-discovery.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="refentry">
+<a name="libnice-Debug-messages"></a><div class="titlepage"></div>
+<div class="refnamediv"><table width="100%"><tr>
+<td valign="top">
+<h2><span class="refentrytitle"><a name="libnice-Debug-messages.top_of_page"></a>Debug messages</span></h2>
+<p>Debug messages — Debug messages utility functions</p>
+</td>
+<td class="gallery_image" valign="top" align="right"></td>
+</tr></table></div>
+<div class="refsect1">
+<a name="libnice-Debug-messages.stability-level"></a><h2>Stability Level</h2>
+<acronym title="Unstable interfaces are experimental or transitional. They are typically used to
+give outside developers early access to new or rapidly changing technology, or
+to provide an interim solution to a problem where a more general solution is
+anticipated. No claims are made about either source or binary compatibility from
+one minor release to the next.
+
+The Unstable interface level is a warning that these interfaces are subject to
+change without warning and should not be used in unbundled products.
+
+Given such caveats, customer impact need not be a factor when considering
+incompatible changes to an Unstable interface in a major or minor release.
+Nonetheless, when such changes are introduced, the changes should still be
+mentioned in the release notes for the affected release.
+"><span class="acronym">Unstable</span></acronym>, unless otherwise indicated
+</div>
+<div class="refsect1">
+<a name="libnice-Debug-messages.functions"></a><h2>Functions</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="functions_return">
+<col class="functions_name">
+</colgroup>
+<tbody>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-Debug-messages.html#nice-debug-enable" title="nice_debug_enable ()">nice_debug_enable</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-Debug-messages.html#nice-debug-disable" title="nice_debug_disable ()">nice_debug_disable</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect1">
+<a name="libnice-Debug-messages.description"></a><h2>Description</h2>
+<p>Libnice can output a lot of information when debug messages are enabled.
+This can significantly help track down problems and/or understand what
+it's doing.</p>
+<p>You can enable/disable the debug messages by calling <a class="link" href="libnice-Debug-messages.html#nice-debug-enable" title="nice_debug_enable ()"><code class="function">nice_debug_enable()</code></a>
+or <a class="link" href="libnice-Debug-messages.html#nice-debug-disable" title="nice_debug_disable ()"><code class="function">nice_debug_disable()</code></a> and choosing whether you want only ICE debug messages
+or also stun debug messages.</p>
+<p>By default, the debug messages are disabled, unless the environment
+variable NICE_DEBUG is set, in which case, it must contain a comma separated
+list of flags specifying which debug to enable.</p>
+<p> The currently available flags are "nice", "stun", "pseudotcp",
+"pseudotcp-verbose" or "all" to enable all debug messages.</p>
+<p> If the 'pseudotcp' flag is enabled, then 'pseudotcp-verbose' gets
+automatically disabled. This is to allow the use of the 'all' flag without
+having verbose messages from pseudotcp. You can enable verbose debug messages
+from the pseudotcp layer by specifying 'pseudotcp-verbose' without the
+'pseudotcp' flag.</p>
+<p>This API is unstable and is subject to change at any time...
+More flags are to come and a better API to enable/disable each flag
+should be added.</p>
+</div>
+<div class="refsect1">
+<a name="libnice-Debug-messages.functions_details"></a><h2>Functions</h2>
+<div class="refsect2">
+<a name="nice-debug-enable"></a><h3>nice_debug_enable ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+nice_debug_enable (<em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="type">gboolean</span></a> with_stun</code></em>);</pre>
+<p>Enables libnice debug output to the terminal. Note that the
+<code class="literal">G_MESSAGES_DEBUG</code> and <code class="literal">NICE_DEBUG</code> environment variables must be set to the
+set of logging domains to print, in order for any output to be printed. Set
+them to <code class="literal">all</code> to print all debugging messages, or any of the following
+domains:</p>
+<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
+<li class="listitem"><p><code class="literal">libnice-stun</code></p></li>
+<li class="listitem"><p><code class="literal">libnice-tests</code></p></li>
+<li class="listitem"><p><code class="literal">libnice-socket</code></p></li>
+<li class="listitem"><p><code class="literal">libnice</code></p></li>
+<li class="listitem"><p><code class="literal">libnice-pseudotcp</code></p></li>
+<li class="listitem"><p><code class="literal">libnice-pseudotcp-verbose</code></p></li>
+</ul></div>
+<div class="refsect3">
+<a name="nice-debug-enable.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>with_stun</p></td>
+<td class="parameter_description"><p>Also enable STUN debugging messages</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-debug-disable"></a><h3>nice_debug_disable ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+nice_debug_disable (<em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="type">gboolean</span></a> with_stun</code></em>);</pre>
+<p>Disables libnice debug output to the terminal</p>
+<div class="refsect3">
+<a name="nice-debug-disable.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>with_stun</p></td>
+<td class="parameter_description"><p>Also disable stun debugging messages</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+</div>
+</div>
+<div class="refsect1">
+<a name="libnice-Debug-messages.other_details"></a><h2>Types and Values</h2>
+</div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.29</div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>ICE: libnice Reference Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets Vsnapshot">
+<link rel="home" href="index.html" title="libnice Reference Manual">
+<link rel="up" href="ch04.html" title="STUN usages">
+<link rel="prev" href="libnice-Bind.html" title="Bind">
+<link rel="next" href="libnice-TURN.html" title="TURN">
+<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts">
+<a href="#" class="shortcut">Top</a><span id="nav_description"> <span class="dim">|</span>
+ <a href="#libnice-ICE.description" class="shortcut">Description</a></span>
+</td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="ch04.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="libnice-Bind.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="libnice-TURN.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="refentry">
+<a name="libnice-ICE"></a><div class="titlepage"></div>
+<div class="refnamediv"><table width="100%"><tr>
+<td valign="top">
+<h2><span class="refentrytitle"><a name="libnice-ICE.top_of_page"></a>ICE</span></h2>
+<p>ICE — STUN ICE Usage</p>
+</td>
+<td class="gallery_image" valign="top" align="right"></td>
+</tr></table></div>
+<div class="refsect1">
+<a name="libnice-ICE.stability-level"></a><h2>Stability Level</h2>
+<acronym title="The intention of a Stable interface is to enable arbitrary third parties to
+develop applications to these interfaces, release them, and have confidence that
+they will run on all minor releases of the product (after the one in which the
+interface was introduced, and within the same major release). Even at a major
+release, incompatible changes are expected to be rare, and to have strong
+justifications.
+"><span class="acronym">Stable</span></acronym>, unless otherwise indicated
+</div>
+<div class="refsect1">
+<a name="libnice-ICE.functions"></a><h2>Functions</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="functions_return">
+<col class="functions_name">
+</colgroup>
+<tbody>
+<tr>
+<td class="function_type">
+<span class="returnvalue">size_t</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-ICE.html#stun-usage-ice-conncheck-create" title="stun_usage_ice_conncheck_create ()">stun_usage_ice_conncheck_create</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="libnice-ICE.html#StunUsageIceReturn" title="enum StunUsageIceReturn"><span class="returnvalue">StunUsageIceReturn</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-ICE.html#stun-usage-ice-conncheck-process" title="stun_usage_ice_conncheck_process ()">stun_usage_ice_conncheck_process</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="libnice-ICE.html#StunUsageIceReturn" title="enum StunUsageIceReturn"><span class="returnvalue">StunUsageIceReturn</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-ICE.html#stun-usage-ice-conncheck-create-reply" title="stun_usage_ice_conncheck_create_reply ()">stun_usage_ice_conncheck_create_reply</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">uint32_t</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-ICE.html#stun-usage-ice-conncheck-priority" title="stun_usage_ice_conncheck_priority ()">stun_usage_ice_conncheck_priority</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">bool</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-ICE.html#stun-usage-ice-conncheck-use-candidate" title="stun_usage_ice_conncheck_use_candidate ()">stun_usage_ice_conncheck_use_candidate</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect1">
+<a name="libnice-ICE.other"></a><h2>Types and Values</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="name">
+<col class="description">
+</colgroup>
+<tbody>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="libnice-ICE.html#StunUsageIceCompatibility" title="enum StunUsageIceCompatibility">StunUsageIceCompatibility</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="libnice-ICE.html#StunUsageIceReturn" title="enum StunUsageIceReturn">StunUsageIceReturn</a></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect1">
+<a name="libnice-ICE.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include <stun/usages/ice.h>
+</pre>
+</div>
+<div class="refsect1">
+<a name="libnice-ICE.description"></a><h2>Description</h2>
+<p>The STUN ICE usage allows for easily creating and parsing STUN Binding
+requests and responses used for ICE connectivity checks. The API allows you
+to create a connectivity check message, parse a response or create a reply
+to an incoming connectivity check request.</p>
+</div>
+<div class="refsect1">
+<a name="libnice-ICE.functions_details"></a><h2>Functions</h2>
+<div class="refsect2">
+<a name="stun-usage-ice-conncheck-create"></a><h3>stun_usage_ice_conncheck_create ()</h3>
+<pre class="programlisting"><span class="returnvalue">size_t</span>
+stun_usage_ice_conncheck_create (<em class="parameter"><code><a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><span class="type">uint8_t</span> *buffer</code></em>,
+ <em class="parameter"><code><span class="type">size_t</span> buffer_len</code></em>,
+ <em class="parameter"><code>const <span class="type">uint8_t</span> *username</code></em>,
+ <em class="parameter"><code>const <span class="type">size_t</span> username_len</code></em>,
+ <em class="parameter"><code>const <span class="type">uint8_t</span> *password</code></em>,
+ <em class="parameter"><code>const <span class="type">size_t</span> password_len</code></em>,
+ <em class="parameter"><code><span class="type">bool</span> cand_use</code></em>,
+ <em class="parameter"><code><span class="type">bool</span> controlling</code></em>,
+ <em class="parameter"><code><span class="type">uint32_t</span> priority</code></em>,
+ <em class="parameter"><code><span class="type">uint64_t</span> tie</code></em>,
+ <em class="parameter"><code>const <span class="type">char</span> *candidate_identifier</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-ICE.html#StunUsageIceCompatibility" title="enum StunUsageIceCompatibility"><span class="type">StunUsageIceCompatibility</span></a> compatibility</code></em>);</pre>
+<p>Builds an ICE connectivity check STUN message.
+If the compatibility is not <a class="link" href="libnice-ICE.html#STUN-USAGE-ICE-COMPATIBILITY-RFC5245:CAPS"><span class="type">STUN_USAGE_ICE_COMPATIBILITY_RFC5245</span></a>, the
+<em class="parameter"><code>cand_use</code></em>
+, <em class="parameter"><code>controlling</code></em>
+, <em class="parameter"><code>priority</code></em>
+ and <em class="parameter"><code>tie</code></em>
+ arguments are not used.
+If the compatibility is not <a class="link" href="libnice-ICE.html#STUN-USAGE-ICE-COMPATIBILITY-MSICE2:CAPS"><span class="type">STUN_USAGE_ICE_COMPATIBILITY_MSICE2</span></a>, the
+<em class="parameter"><code>candidate_identifier</code></em>
+ argument is not used.</p>
+<div class="refsect3">
+<a name="stun-usage-ice-conncheck-create.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a> to use to build the request</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> to build</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>The buffer to use for creating the <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buffer_len</p></td>
+<td class="parameter_description"><p>The size of the <em class="parameter"><code>buffer</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>username</p></td>
+<td class="parameter_description"><p>The username to use in the request</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>username_len</p></td>
+<td class="parameter_description"><p>The length of <em class="parameter"><code>username</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>password</p></td>
+<td class="parameter_description"><p>The key to use for building the MESSAGE-INTEGRITY</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>password_len</p></td>
+<td class="parameter_description"><p>The length of <em class="parameter"><code>password</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>cand_use</p></td>
+<td class="parameter_description"><p>Set to <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> to append the USE-CANDIDATE flag to the request</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>controlling</p></td>
+<td class="parameter_description"><p>Set to <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> if you are the controlling agent or set to
+<a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> if you are the controlled agent.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>priority</p></td>
+<td class="parameter_description"><p>The value of the PRIORITY attribute</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>tie</p></td>
+<td class="parameter_description"><p>The value of the tie-breaker to put in the ICE-CONTROLLED or
+ICE-CONTROLLING attribute</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>candidate_identifier</p></td>
+<td class="parameter_description"><p>The foundation value to put in the
+CANDIDATE-IDENTIFIER attribute</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>compatibility</p></td>
+<td class="parameter_description"><p>The compatibility mode to use for building the conncheck
+request</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-usage-ice-conncheck-create.returns"></a><h4>Returns</h4>
+<p> The length of the message built.</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-usage-ice-conncheck-process"></a><h3>stun_usage_ice_conncheck_process ()</h3>
+<pre class="programlisting"><a class="link" href="libnice-ICE.html#StunUsageIceReturn" title="enum StunUsageIceReturn"><span class="returnvalue">StunUsageIceReturn</span></a>
+stun_usage_ice_conncheck_process (<em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><span class="type">struct sockaddr_storage</span> *addr</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/camel/camel-camel-net-utils.html#socklen-t"><span class="type">socklen_t</span></a> *addrlen</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-ICE.html#StunUsageIceCompatibility" title="enum StunUsageIceCompatibility"><span class="type">StunUsageIceCompatibility</span></a> compatibility</code></em>);</pre>
+<p>Process an ICE connectivity check STUN message and retrieve the
+mapped address from the message</p>
+<p> See also <a class="link" href="libnice-ICE.html#stun-usage-ice-conncheck-priority" title="stun_usage_ice_conncheck_priority ()"><code class="function">stun_usage_ice_conncheck_priority()</code></a> and
+<a class="link" href="libnice-ICE.html#stun-usage-ice-conncheck-use-candidate" title="stun_usage_ice_conncheck_use_candidate ()"><code class="function">stun_usage_ice_conncheck_use_candidate()</code></a> </p>
+<div class="refsect3">
+<a name="stun-usage-ice-conncheck-process.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> to process</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>addr</p></td>
+<td class="parameter_description"><p>A pointer to a <a href="/usr/share/gtk-doc/html/camel/camel-camel-net-utils.html#sockaddr"><span class="type">sockaddr</span></a> structure to fill with the mapped address
+that the STUN connectivity check response contains</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>addrlen</p></td>
+<td class="parameter_description"><p>The length of <em class="parameter"><code>addr</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>compatibility</p></td>
+<td class="parameter_description"><p>The compatibility mode to use for processing the conncheck
+response</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-usage-ice-conncheck-process.returns"></a><h4>Returns</h4>
+<p> A <a class="link" href="libnice-ICE.html#StunUsageIceReturn" title="enum StunUsageIceReturn"><span class="type">StunUsageIceReturn</span></a> value</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-usage-ice-conncheck-create-reply"></a><h3>stun_usage_ice_conncheck_create_reply ()</h3>
+<pre class="programlisting"><a class="link" href="libnice-ICE.html#StunUsageIceReturn" title="enum StunUsageIceReturn"><span class="returnvalue">StunUsageIceReturn</span></a>
+stun_usage_ice_conncheck_create_reply (<em class="parameter"><code><a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *req</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><span class="type">uint8_t</span> *buf</code></em>,
+ <em class="parameter"><code><span class="type">size_t</span> *plen</code></em>,
+ <em class="parameter"><code>const <span class="type">struct sockaddr_storage</span> *src</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/camel/camel-camel-net-utils.html#socklen-t"><span class="type">socklen_t</span></a> srclen</code></em>,
+ <em class="parameter"><code><span class="type">bool</span> *control</code></em>,
+ <em class="parameter"><code><span class="type">uint64_t</span> tie</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-ICE.html#StunUsageIceCompatibility" title="enum StunUsageIceCompatibility"><span class="type">StunUsageIceCompatibility</span></a> compatibility</code></em>);</pre>
+<p>Tries to parse a STUN connectivity check request and builds a
+response accordingly.</p>
+<div class="note"><p>
+ In case of error, the <em class="parameter"><code>msg</code></em> is filled with the appropriate error response
+ to be sent and the value of <em class="parameter"><code>plen</code></em> is set to the size of that message.
+ If <em class="parameter"><code>plen</code></em> has a size of 0, then no error response should be sent.
+ </p></div>
+<div class="refsect3">
+<a name="stun-usage-ice-conncheck-create-reply.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a> to use to build the response</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>req</p></td>
+<td class="parameter_description"><p>The original STUN request to reply to</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> to build</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buf</p></td>
+<td class="parameter_description"><p>The buffer to use for creating the <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>plen</p></td>
+<td class="parameter_description"><p>A pointer containing the size of the <em class="parameter"><code>buffer</code></em>
+on input.
+Will contain the length of the message built on output.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>src</p></td>
+<td class="parameter_description"><p>A pointer to a <a href="/usr/share/gtk-doc/html/camel/camel-camel-net-utils.html#sockaddr"><span class="type">sockaddr</span></a> structure containing the source address from
+which the request was received. Will be used as the mapped address in the
+response</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>srclen</p></td>
+<td class="parameter_description"><p>The length of <em class="parameter"><code>addr</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>control</p></td>
+<td class="parameter_description"><p>Set to <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> if you are the controlling agent or set to
+<a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> if you are the controlled agent.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>tie</p></td>
+<td class="parameter_description"><p>The value of the tie-breaker to put in the ICE-CONTROLLED or
+ICE-CONTROLLING attribute</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>compatibility</p></td>
+<td class="parameter_description"><p>The compatibility mode to use for building the conncheck
+response</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-usage-ice-conncheck-create-reply.returns"></a><h4>Returns</h4>
+<p> A <a class="link" href="libnice-ICE.html#StunUsageIceReturn" title="enum StunUsageIceReturn"><span class="type">StunUsageIceReturn</span></a> value</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-usage-ice-conncheck-priority"></a><h3>stun_usage_ice_conncheck_priority ()</h3>
+<pre class="programlisting"><span class="returnvalue">uint32_t</span>
+stun_usage_ice_conncheck_priority (<em class="parameter"><code>const <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>);</pre>
+<p>Extracts the priority from a STUN message.</p>
+<div class="refsect3">
+<a name="stun-usage-ice-conncheck-priority.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> to parse</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-usage-ice-conncheck-priority.returns"></a><h4>Returns</h4>
+<p> host byte order priority, or 0 if not specified.</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-usage-ice-conncheck-use-candidate"></a><h3>stun_usage_ice_conncheck_use_candidate ()</h3>
+<pre class="programlisting"><span class="returnvalue">bool</span>
+stun_usage_ice_conncheck_use_candidate
+ (<em class="parameter"><code>const <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>);</pre>
+<p>Extracts the USE-CANDIDATE attribute flag from a STUN message.</p>
+<div class="refsect3">
+<a name="stun-usage-ice-conncheck-use-candidate.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> to parse</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-usage-ice-conncheck-use-candidate.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> if the flag is set, <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> if not.</p>
+</div>
+</div>
+</div>
+<div class="refsect1">
+<a name="libnice-ICE.other_details"></a><h2>Types and Values</h2>
+<div class="refsect2">
+<a name="StunUsageIceCompatibility"></a><h3>enum StunUsageIceCompatibility</h3>
+<p>This enum defines which compatibility modes this ICE usage can use</p>
+<div class="warning">
+<em class="parameter"><code>STUN_USAGE_ICE_COMPATIBILITY_DRAFT19</code></em> and
+<em class="parameter"><code>STUN_USAGE_ICE_COMPATIBILITY_WLM2009</code></em> are deprecated and should not be used
+in newly-written code. They are kept for compatibility reasons and represent
+the same compatibilities as <em class="parameter"><code>STUN_USAGE_ICE_COMPATIBILITY_RFC5245</code></em> and
+<em class="parameter"><code>STUN_USAGE_ICE_COMPATIBILITY_MSICE2</code></em> respectively.</div>
+<div class="refsect3">
+<a name="StunUsageIceCompatibility.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-USAGE-ICE-COMPATIBILITY-RFC5245:CAPS"></a>STUN_USAGE_ICE_COMPATIBILITY_RFC5245</p></td>
+<td class="enum_member_description">
+<p>The ICE compatibility with RFC 5245</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-USAGE-ICE-COMPATIBILITY-GOOGLE:CAPS"></a>STUN_USAGE_ICE_COMPATIBILITY_GOOGLE</p></td>
+<td class="enum_member_description">
+<p>The ICE compatibility with Google's
+implementation of ICE</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-USAGE-ICE-COMPATIBILITY-MSN:CAPS"></a>STUN_USAGE_ICE_COMPATIBILITY_MSN</p></td>
+<td class="enum_member_description">
+<p>The ICE compatibility with MSN's
+implementation of ICE</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-USAGE-ICE-COMPATIBILITY-MSICE2:CAPS"></a>STUN_USAGE_ICE_COMPATIBILITY_MSICE2</p></td>
+<td class="enum_member_description">
+<p>The ICE compatibility with [MS-ICE2]
+specification</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-USAGE-ICE-COMPATIBILITY-DRAFT19:CAPS"></a>STUN_USAGE_ICE_COMPATIBILITY_DRAFT19</p></td>
+<td class="enum_member_description">
+<p>The ICE compatibility with draft 19</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-USAGE-ICE-COMPATIBILITY-WLM2009:CAPS"></a>STUN_USAGE_ICE_COMPATIBILITY_WLM2009</p></td>
+<td class="enum_member_description">
+<p>An alias
+for <em class="parameter"><code>STUN_USAGE_ICE_COMPATIBILITY_MSICE2</code></em>
+</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="StunUsageIceReturn"></a><h3>enum StunUsageIceReturn</h3>
+<p>Return value of <a class="link" href="libnice-ICE.html#stun-usage-ice-conncheck-process" title="stun_usage_ice_conncheck_process ()"><code class="function">stun_usage_ice_conncheck_process()</code></a> and
+<a class="link" href="libnice-ICE.html#stun-usage-ice-conncheck-create-reply" title="stun_usage_ice_conncheck_create_reply ()"><code class="function">stun_usage_ice_conncheck_create_reply()</code></a> which allows you to see what
+status the function call returned.</p>
+<div class="refsect3">
+<a name="StunUsageIceReturn.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-USAGE-ICE-RETURN-SUCCESS:CAPS"></a>STUN_USAGE_ICE_RETURN_SUCCESS</p></td>
+<td class="enum_member_description">
+<p>The function succeeded</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-USAGE-ICE-RETURN-ERROR:CAPS"></a>STUN_USAGE_ICE_RETURN_ERROR</p></td>
+<td class="enum_member_description">
+<p>There was an unspecified error</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-USAGE-ICE-RETURN-INVALID:CAPS"></a>STUN_USAGE_ICE_RETURN_INVALID</p></td>
+<td class="enum_member_description">
+<p>The message is invalid for processing</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-USAGE-ICE-RETURN-ROLE-CONFLICT:CAPS"></a>STUN_USAGE_ICE_RETURN_ROLE_CONFLICT</p></td>
+<td class="enum_member_description">
+<p>A role conflict was detected</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-USAGE-ICE-RETURN-INVALID-REQUEST:CAPS"></a>STUN_USAGE_ICE_RETURN_INVALID_REQUEST</p></td>
+<td class="enum_member_description">
+<p>The message is an not a request</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-USAGE-ICE-RETURN-INVALID-METHOD:CAPS"></a>STUN_USAGE_ICE_RETURN_INVALID_METHOD</p></td>
+<td class="enum_member_description">
+<p>The method of the request is invalid</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-USAGE-ICE-RETURN-MEMORY-ERROR:CAPS"></a>STUN_USAGE_ICE_RETURN_MEMORY_ERROR</p></td>
+<td class="enum_member_description">
+<p>The buffer size is too small to hold
+the STUN reply</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-USAGE-ICE-RETURN-INVALID-ADDRESS:CAPS"></a>STUN_USAGE_ICE_RETURN_INVALID_ADDRESS</p></td>
+<td class="enum_member_description">
+<p>The mapped address argument has
+an invalid address family</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-USAGE-ICE-RETURN-NO-MAPPED-ADDRESS:CAPS"></a>STUN_USAGE_ICE_RETURN_NO_MAPPED_ADDRESS</p></td>
+<td class="enum_member_description">
+<p>The response is valid but no
+MAPPED-ADDRESS or XOR-MAPPED-ADDRESS attribute was found</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+</div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.29</div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Network interfaces discovery: libnice Reference Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets Vsnapshot">
+<link rel="home" href="index.html" title="libnice Reference Manual">
+<link rel="up" href="ch02.html" title="Libnice helper functions">
+<link rel="prev" href="libnice-Debug-messages.html" title="Debug messages">
+<link rel="next" href="pt02.html" title="Part II. STUN Library">
+<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts">
+<a href="#" class="shortcut">Top</a><span id="nav_description"> <span class="dim">|</span>
+ <a href="#libnice-Network-interfaces-discovery.description" class="shortcut">Description</a></span>
+</td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="ch02.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="libnice-Debug-messages.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="pt02.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="refentry">
+<a name="libnice-Network-interfaces-discovery"></a><div class="titlepage"></div>
+<div class="refnamediv"><table width="100%"><tr>
+<td valign="top">
+<h2><span class="refentrytitle"><a name="libnice-Network-interfaces-discovery.top_of_page"></a>Network interfaces discovery</span></h2>
+<p>Network interfaces discovery — Utility functions to discover local network interfaces</p>
+</td>
+<td class="gallery_image" valign="top" align="right"></td>
+</tr></table></div>
+<div class="refsect1">
+<a name="libnice-Network-interfaces-discovery.stability-level"></a><h2>Stability Level</h2>
+<acronym title="The intention of a Stable interface is to enable arbitrary third parties to
+develop applications to these interfaces, release them, and have confidence that
+they will run on all minor releases of the product (after the one in which the
+interface was introduced, and within the same major release). Even at a major
+release, incompatible changes are expected to be rare, and to have strong
+justifications.
+"><span class="acronym">Stable</span></acronym>, unless otherwise indicated
+</div>
+<div class="refsect1">
+<a name="libnice-Network-interfaces-discovery.functions"></a><h2>Functions</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="functions_return">
+<col class="functions_name">
+</colgroup>
+<tbody>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="returnvalue">gchar</span></a> *
+</td>
+<td class="function_name">
+<a class="link" href="libnice-Network-interfaces-discovery.html#nice-interfaces-get-ip-for-interface" title="nice_interfaces_get_ip_for_interface ()">nice_interfaces_get_ip_for_interface</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Doubly-Linked-Lists.html#GList"><span class="returnvalue">GList</span></a> *
+</td>
+<td class="function_name">
+<a class="link" href="libnice-Network-interfaces-discovery.html#nice-interfaces-get-local-interfaces" title="nice_interfaces_get_local_interfaces ()">nice_interfaces_get_local_interfaces</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Doubly-Linked-Lists.html#GList"><span class="returnvalue">GList</span></a> *
+</td>
+<td class="function_name">
+<a class="link" href="libnice-Network-interfaces-discovery.html#nice-interfaces-get-local-ips" title="nice_interfaces_get_local_ips ()">nice_interfaces_get_local_ips</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect1">
+<a name="libnice-Network-interfaces-discovery.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include <interfaces.h>
+</pre>
+</div>
+<div class="refsect1">
+<a name="libnice-Network-interfaces-discovery.description"></a><h2>Description</h2>
+<p>These utility functions allow the discovery of local network interfaces
+in a portable manner, they also allow finding the local ip addresses or
+the address allocated to a network interface.</p>
+</div>
+<div class="refsect1">
+<a name="libnice-Network-interfaces-discovery.functions_details"></a><h2>Functions</h2>
+<div class="refsect2">
+<a name="nice-interfaces-get-ip-for-interface"></a><h3>nice_interfaces_get_ip_for_interface ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="returnvalue">gchar</span></a> *
+nice_interfaces_get_ip_for_interface (<em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *interface_name</code></em>);</pre>
+<p>Retrieves the IP address of an interface by its name. If this fails, <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS"><code class="literal">NULL</code></a>
+is returned.</p>
+<div class="refsect3">
+<a name="nice-interfaces-get-ip-for-interface.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>interface_name</p></td>
+<td class="parameter_description"><p>name of local interface</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-interfaces-get-ip-for-interface.returns"></a><h4>Returns</h4>
+<p>a newly-allocated string with the IP
+address. </p>
+<p><span class="annotation">[<acronym title="NULL may be passed as the value in, out, in-out; or as a return value."><span class="acronym">nullable</span></acronym>][<acronym title="Free data after the code is done."><span class="acronym">transfer full</span></acronym>]</span></p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-interfaces-get-local-interfaces"></a><h3>nice_interfaces_get_local_interfaces ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Doubly-Linked-Lists.html#GList"><span class="returnvalue">GList</span></a> *
+nice_interfaces_get_local_interfaces (<em class="parameter"><code><span class="type">void</span></code></em>);</pre>
+<p>Get the list of local interfaces</p>
+<div class="refsect3">
+<a name="nice-interfaces-get-local-interfaces.returns"></a><h4>Returns</h4>
+<p>a newly-allocated <a href="/usr/share/gtk-doc/html/glib/glib-Doubly-Linked-Lists.html#GList"><span class="type">GList</span></a> of
+strings. The caller must free it. </p>
+<p><span class="annotation">[<acronym title="Generics and defining elements of containers and arrays."><span class="acronym">element-type</span></acronym> utf8][<acronym title="Free data after the code is done."><span class="acronym">transfer full</span></acronym>]</span></p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-interfaces-get-local-ips"></a><h3>nice_interfaces_get_local_ips ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Doubly-Linked-Lists.html#GList"><span class="returnvalue">GList</span></a> *
+nice_interfaces_get_local_ips (<em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="type">gboolean</span></a> include_loopback</code></em>);</pre>
+<p>Get a list of local ipv4 interface addresses</p>
+<div class="refsect3">
+<a name="nice-interfaces-get-local-ips.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>include_loopback</p></td>
+<td class="parameter_description"><p>Include any loopback devices</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-interfaces-get-local-ips.returns"></a><h4>Returns</h4>
+<p>a newly-allocated <a href="/usr/share/gtk-doc/html/glib/glib-Doubly-Linked-Lists.html#GList"><span class="type">GList</span></a> of
+strings. The caller must free it. </p>
+<p><span class="annotation">[<acronym title="Generics and defining elements of containers and arrays."><span class="acronym">element-type</span></acronym> utf8][<acronym title="Free data after the code is done."><span class="acronym">transfer full</span></acronym>]</span></p>
+</div>
+</div>
+</div>
+<div class="refsect1">
+<a name="libnice-Network-interfaces-discovery.other_details"></a><h2>Types and Values</h2>
+</div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.29</div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>NiceAddress: libnice Reference Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets Vsnapshot">
+<link rel="home" href="index.html" title="libnice Reference Manual">
+<link rel="up" href="ch01.html" title="">
+<link rel="prev" href="NiceAgent.html" title="NiceAgent">
+<link rel="next" href="NiceCandidate.html" title="NiceCandidate">
+<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts">
+<a href="#" class="shortcut">Top</a><span id="nav_description"> <span class="dim">|</span>
+ <a href="#libnice-NiceAddress.description" class="shortcut">Description</a></span>
+</td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="ch01.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="NiceAgent.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="NiceCandidate.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="refentry">
+<a name="libnice-NiceAddress"></a><div class="titlepage"></div>
+<div class="refnamediv"><table width="100%"><tr>
+<td valign="top">
+<h2><span class="refentrytitle"><a name="libnice-NiceAddress.top_of_page"></a>NiceAddress</span></h2>
+<p>NiceAddress — IP address convenience library</p>
+</td>
+<td class="gallery_image" valign="top" align="right"></td>
+</tr></table></div>
+<div class="refsect1">
+<a name="libnice-NiceAddress.stability-level"></a><h2>Stability Level</h2>
+<acronym title="The intention of a Stable interface is to enable arbitrary third parties to
+develop applications to these interfaces, release them, and have confidence that
+they will run on all minor releases of the product (after the one in which the
+interface was introduced, and within the same major release). Even at a major
+release, incompatible changes are expected to be rare, and to have strong
+justifications.
+"><span class="acronym">Stable</span></acronym>, unless otherwise indicated
+</div>
+<div class="refsect1">
+<a name="libnice-NiceAddress.functions"></a><h2>Functions</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="functions_return">
+<col class="functions_name">
+</colgroup>
+<tbody>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-NiceAddress.html#nice-address-init" title="nice_address_init ()">nice_address_init</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="returnvalue">NiceAddress</span></a> *
+</td>
+<td class="function_name">
+<a class="link" href="libnice-NiceAddress.html#nice-address-new" title="nice_address_new ()">nice_address_new</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-NiceAddress.html#nice-address-free" title="nice_address_free ()">nice_address_free</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="returnvalue">NiceAddress</span></a> *
+</td>
+<td class="function_name">
+<a class="link" href="libnice-NiceAddress.html#nice-address-dup" title="nice_address_dup ()">nice_address_dup</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-NiceAddress.html#nice-address-set-ipv4" title="nice_address_set_ipv4 ()">nice_address_set_ipv4</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-NiceAddress.html#nice-address-set-ipv6" title="nice_address_set_ipv6 ()">nice_address_set_ipv6</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-NiceAddress.html#nice-address-set-port" title="nice_address_set_port ()">nice_address_set_port</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="returnvalue">guint</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-NiceAddress.html#nice-address-get-port" title="nice_address_get_port ()">nice_address_get_port</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-NiceAddress.html#nice-address-set-from-string" title="nice_address_set_from_string ()">nice_address_set_from_string</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-NiceAddress.html#nice-address-set-from-sockaddr" title="nice_address_set_from_sockaddr ()">nice_address_set_from_sockaddr</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-NiceAddress.html#nice-address-copy-to-sockaddr" title="nice_address_copy_to_sockaddr ()">nice_address_copy_to_sockaddr</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-NiceAddress.html#nice-address-equal" title="nice_address_equal ()">nice_address_equal</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-NiceAddress.html#nice-address-equal-no-port" title="nice_address_equal_no_port ()">nice_address_equal_no_port</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-NiceAddress.html#nice-address-to-string" title="nice_address_to_string ()">nice_address_to_string</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-NiceAddress.html#nice-address-is-private" title="nice_address_is_private ()">nice_address_is_private</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-NiceAddress.html#nice-address-is-valid" title="nice_address_is_valid ()">nice_address_is_valid</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">int</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-NiceAddress.html#nice-address-ip-version" title="nice_address_ip_version ()">nice_address_ip_version</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect1">
+<a name="libnice-NiceAddress.other"></a><h2>Types and Values</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="name">
+<col class="description">
+</colgroup>
+<tbody>
+<tr>
+<td class="datatype_keyword"> </td>
+<td class="function_name"><a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress">NiceAddress</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="libnice-NiceAddress.html#NICE-ADDRESS-STRING-LEN:CAPS" title="NICE_ADDRESS_STRING_LEN">NICE_ADDRESS_STRING_LEN</a></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect1">
+<a name="libnice-NiceAddress.description"></a><h2>Description</h2>
+<p>The <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> structure will allow you to easily set/get and modify an IPv4
+or IPv6 address in order to communicate with the <a class="link" href="NiceAgent.html" title="NiceAgent"><span class="type">NiceAgent</span></a>.</p>
+</div>
+<div class="refsect1">
+<a name="libnice-NiceAddress.functions_details"></a><h2>Functions</h2>
+<div class="refsect2">
+<a name="nice-address-init"></a><h3>nice_address_init ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+nice_address_init (<em class="parameter"><code><a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> *addr</code></em>);</pre>
+<p>Initialize a <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> into an undefined address</p>
+<div class="refsect3">
+<a name="nice-address-init.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>addr</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> to init</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-address-new"></a><h3>nice_address_new ()</h3>
+<pre class="programlisting"><a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="returnvalue">NiceAddress</span></a> *
+nice_address_new (<em class="parameter"><code><span class="type">void</span></code></em>);</pre>
+<p>Create a new <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> with undefined address
+You must free it with <a class="link" href="libnice-NiceAddress.html#nice-address-free" title="nice_address_free ()"><code class="function">nice_address_free()</code></a></p>
+<div class="refsect3">
+<a name="nice-address-new.returns"></a><h4>Returns</h4>
+<p> The new <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a></p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-address-free"></a><h3>nice_address_free ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+nice_address_free (<em class="parameter"><code><a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> *addr</code></em>);</pre>
+<p>Frees a <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> created with <a class="link" href="libnice-NiceAddress.html#nice-address-new" title="nice_address_new ()"><code class="function">nice_address_new()</code></a> or <a class="link" href="libnice-NiceAddress.html#nice-address-dup" title="nice_address_dup ()"><code class="function">nice_address_dup()</code></a></p>
+<div class="refsect3">
+<a name="nice-address-free.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>addr</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> to free</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-address-dup"></a><h3>nice_address_dup ()</h3>
+<pre class="programlisting"><a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="returnvalue">NiceAddress</span></a> *
+nice_address_dup (<em class="parameter"><code>const <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> *addr</code></em>);</pre>
+<p>Creates a new <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> with the same address as <em class="parameter"><code>addr</code></em>
+</p>
+<div class="refsect3">
+<a name="nice-address-dup.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>addr</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> to dup</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-address-dup.returns"></a><h4>Returns</h4>
+<p> The new <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a></p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-address-set-ipv4"></a><h3>nice_address_set_ipv4 ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+nice_address_set_ipv4 (<em class="parameter"><code><a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> *addr</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint32"><span class="type">guint32</span></a> addr_ipv4</code></em>);</pre>
+<p>Set <em class="parameter"><code>addr</code></em>
+ to an IPv4 address using the data from <em class="parameter"><code>addr_ipv4</code></em>
+</p>
+<div class="note"><p>
+ This function will reset the port to 0, so make sure you call it before
+ <a class="link" href="libnice-NiceAddress.html#nice-address-set-port" title="nice_address_set_port ()"><code class="function">nice_address_set_port()</code></a>
+ </p></div>
+<div class="refsect3">
+<a name="nice-address-set-ipv4.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>addr</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> to modify</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>addr_ipv4</p></td>
+<td class="parameter_description"><p>The IPv4 address</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-address-set-ipv6"></a><h3>nice_address_set_ipv6 ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+nice_address_set_ipv6 (<em class="parameter"><code><a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> *addr</code></em>,
+ <em class="parameter"><code>const <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guchar"><span class="type">guchar</span></a> *addr_ipv6</code></em>);</pre>
+<p>Set <em class="parameter"><code>addr</code></em>
+ to an IPv6 address using the data from <em class="parameter"><code>addr_ipv6</code></em>
+</p>
+<div class="note"><p>
+ This function will reset the port to 0, so make sure you call it before
+ <a class="link" href="libnice-NiceAddress.html#nice-address-set-port" title="nice_address_set_port ()"><code class="function">nice_address_set_port()</code></a>
+ </p></div>
+<div class="refsect3">
+<a name="nice-address-set-ipv6.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>addr</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> to modify</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>addr_ipv6</p></td>
+<td class="parameter_description"><p>The IPv6 address</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-address-set-port"></a><h3>nice_address_set_port ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+nice_address_set_port (<em class="parameter"><code><a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> *addr</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a> port</code></em>);</pre>
+<p>Set the port of <em class="parameter"><code>addr</code></em>
+ to <em class="parameter"><code>port</code></em>
+</p>
+<div class="refsect3">
+<a name="nice-address-set-port.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>addr</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> to modify</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>port</p></td>
+<td class="parameter_description"><p>The port to set</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-address-get-port"></a><h3>nice_address_get_port ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="returnvalue">guint</span></a>
+nice_address_get_port (<em class="parameter"><code>const <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> *addr</code></em>);</pre>
+<p>Retreive the port of <em class="parameter"><code>addr</code></em>
+</p>
+<div class="refsect3">
+<a name="nice-address-get-port.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>addr</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> to query</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-address-get-port.returns"></a><h4>Returns</h4>
+<p> The port of <em class="parameter"><code>addr</code></em>
+</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-address-set-from-string"></a><h3>nice_address_set_from_string ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+nice_address_set_from_string (<em class="parameter"><code><a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> *addr</code></em>,
+ <em class="parameter"><code>const <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *str</code></em>);</pre>
+<p>Sets an IPv4 or IPv6 address from the string <em class="parameter"><code>str</code></em>
+</p>
+<div class="refsect3">
+<a name="nice-address-set-from-string.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>addr</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> to modify</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>str</p></td>
+<td class="parameter_description"><p>The string to set</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-address-set-from-string.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> if success, <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> on error</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-address-set-from-sockaddr"></a><h3>nice_address_set_from_sockaddr ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+nice_address_set_from_sockaddr (<em class="parameter"><code><a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> *addr</code></em>,
+ <em class="parameter"><code>const <span class="type">struct sockaddr</span> *sin</code></em>);</pre>
+<p>Sets an IPv4 or IPv6 address from the sockaddr structure <em class="parameter"><code>sin</code></em>
+</p>
+<div class="refsect3">
+<a name="nice-address-set-from-sockaddr.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>addr</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> to modify</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>sin</p></td>
+<td class="parameter_description"><p>The sockaddr to set</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-address-copy-to-sockaddr"></a><h3>nice_address_copy_to_sockaddr ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+nice_address_copy_to_sockaddr (<em class="parameter"><code>const <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> *addr</code></em>,
+ <em class="parameter"><code><span class="type">struct sockaddr</span> *sin</code></em>);</pre>
+<p>Fills the sockaddr structure <em class="parameter"><code>sin</code></em>
+ with the address contained in <em class="parameter"><code>addr</code></em>
+</p>
+<div class="refsect3">
+<a name="nice-address-copy-to-sockaddr.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>addr</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> to query</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>sin</p></td>
+<td class="parameter_description"><p>The sockaddr to fill</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-address-equal"></a><h3>nice_address_equal ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+nice_address_equal (<em class="parameter"><code>const <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> *a</code></em>,
+ <em class="parameter"><code>const <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> *b</code></em>);</pre>
+<p>Compares two <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> structures to see if they contain the same address
+and the same port.</p>
+<div class="refsect3">
+<a name="nice-address-equal.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>a</p></td>
+<td class="parameter_description"><p>First <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> to compare</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>b</p></td>
+<td class="parameter_description"><p>Second <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> to compare</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-address-equal.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> if <em class="parameter"><code>a</code></em>
+and <em class="parameter"><code>b</code></em>
+are the same address, <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> if they are different</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-address-equal-no-port"></a><h3>nice_address_equal_no_port ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+nice_address_equal_no_port (<em class="parameter"><code>const <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> *a</code></em>,
+ <em class="parameter"><code>const <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> *b</code></em>);</pre>
+<p>Compares two <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> structures to see if they contain the same address,
+ignoring the port.</p>
+<div class="refsect3">
+<a name="nice-address-equal-no-port.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>a</p></td>
+<td class="parameter_description"><p>First <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> to compare</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>b</p></td>
+<td class="parameter_description"><p>Second <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> to compare</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-address-equal-no-port.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> if <em class="parameter"><code>a</code></em>
+and <em class="parameter"><code>b</code></em>
+are the same address, <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> if they
+are different</p>
+</div>
+<p class="since">Since: <a class="link" href="ix12.html#api-index-0.1.8">0.1.8</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-address-to-string"></a><h3>nice_address_to_string ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+nice_address_to_string (<em class="parameter"><code>const <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> *addr</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *dst</code></em>);</pre>
+<p>Transforms the address <em class="parameter"><code>addr</code></em>
+ into a human readable string</p>
+<div class="refsect3">
+<a name="nice-address-to-string.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>addr</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> to query</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>dst</p></td>
+<td class="parameter_description"><p>The string to fill</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-address-is-private"></a><h3>nice_address_is_private ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+nice_address_is_private (<em class="parameter"><code>const <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> *addr</code></em>);</pre>
+<p>Verifies if the address in <em class="parameter"><code>addr</code></em>
+ is a private address or not</p>
+<div class="refsect3">
+<a name="nice-address-is-private.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>addr</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> to query</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-address-is-private.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> if <em class="parameter"><code>addr</code></em>
+is a private address, <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> otherwise</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-address-is-valid"></a><h3>nice_address_is_valid ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+nice_address_is_valid (<em class="parameter"><code>const <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> *addr</code></em>);</pre>
+<p>Validate whether the <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> <em class="parameter"><code>addr</code></em>
+ is a valid IPv4 or IPv6 address</p>
+<div class="refsect3">
+<a name="nice-address-is-valid.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>addr</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> to query</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-address-is-valid.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> if <em class="parameter"><code>addr</code></em>
+is valid, <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> otherwise</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="nice-address-ip-version"></a><h3>nice_address_ip_version ()</h3>
+<pre class="programlisting"><span class="returnvalue">int</span>
+nice_address_ip_version (<em class="parameter"><code>const <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> *addr</code></em>);</pre>
+<p>Returns the IP version of the address</p>
+<div class="refsect3">
+<a name="nice-address-ip-version.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>addr</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> to query</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="nice-address-ip-version.returns"></a><h4>Returns</h4>
+<p> 4 for IPv4, 6 for IPv6 and 0 for undefined address</p>
+</div>
+</div>
+</div>
+<div class="refsect1">
+<a name="libnice-NiceAddress.other_details"></a><h2>Types and Values</h2>
+<div class="refsect2">
+<a name="NiceAddress"></a><h3>NiceAddress</h3>
+<pre class="programlisting">typedef struct {
+ union
+ {
+ struct sockaddr addr;
+ struct sockaddr_in ip4;
+ struct sockaddr_in6 ip6;
+ } s;
+} NiceAddress;
+</pre>
+<p>The <a class="link" href="libnice-NiceAddress.html#NiceAddress" title="NiceAddress"><span class="type">NiceAddress</span></a> structure that represents an IPv4 or IPv6 address.</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="NICE-ADDRESS-STRING-LEN:CAPS"></a><h3>NICE_ADDRESS_STRING_LEN</h3>
+<pre class="programlisting">#define NICE_ADDRESS_STRING_LEN INET6_ADDRSTRLEN
+</pre>
+<p>The maximum string length representation of an address.
+When using <a class="link" href="libnice-NiceAddress.html#nice-address-to-string" title="nice_address_to_string ()"><code class="function">nice_address_to_string()</code></a> make sure the string has a size of
+at least <a class="link" href="libnice-NiceAddress.html#NICE-ADDRESS-STRING-LEN:CAPS" title="NICE_ADDRESS_STRING_LEN"><code class="literal">NICE_ADDRESS_STRING_LEN</code></a></p>
+</div>
+</div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.29</div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Pseudo TCP Socket: libnice Reference Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets Vsnapshot">
+<link rel="home" href="index.html" title="libnice Reference Manual">
+<link rel="up" href="ch05.html" title="">
+<link rel="prev" href="ch05.html" title="">
+<link rel="next" href="pt04.html" title="Part IV. Appendices">
+<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts">
+<a href="#" class="shortcut">Top</a><span id="nav_description"> <span class="dim">|</span>
+ <a href="#libnice-Pseudo-TCP-Socket.description" class="shortcut">Description</a></span><span id="nav_hierarchy"> <span class="dim">|</span>
+ <a href="#libnice-Pseudo-TCP-Socket.object-hierarchy" class="shortcut">Object Hierarchy</a></span><span id="nav_properties"> <span class="dim">|</span>
+ <a href="#libnice-Pseudo-TCP-Socket.properties" class="shortcut">Properties</a></span>
+</td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="ch05.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="ch05.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="pt04.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="refentry">
+<a name="libnice-Pseudo-TCP-Socket"></a><div class="titlepage"></div>
+<div class="refnamediv"><table width="100%"><tr>
+<td valign="top">
+<h2><span class="refentrytitle"><a name="libnice-Pseudo-TCP-Socket.top_of_page"></a>Pseudo TCP Socket</span></h2>
+<p>Pseudo TCP Socket — Pseudo TCP implementation</p>
+</td>
+<td class="gallery_image" valign="top" align="right"></td>
+</tr></table></div>
+<div class="refsect1">
+<a name="libnice-Pseudo-TCP-Socket.stability-level"></a><h2>Stability Level</h2>
+<acronym title="The intention of a Stable interface is to enable arbitrary third parties to
+develop applications to these interfaces, release them, and have confidence that
+they will run on all minor releases of the product (after the one in which the
+interface was introduced, and within the same major release). Even at a major
+release, incompatible changes are expected to be rare, and to have strong
+justifications.
+"><span class="acronym">Stable</span></acronym>, unless otherwise indicated
+</div>
+<div class="refsect1">
+<a name="libnice-Pseudo-TCP-Socket.functions"></a><h2>Functions</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="functions_return">
+<col class="functions_name">
+</colgroup>
+<tbody>
+<tr>
+<td class="function_type">
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="returnvalue">PseudoTcpSocket</span></a> *
+</td>
+<td class="function_name">
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-new" title="pseudo_tcp_socket_new ()">pseudo_tcp_socket_new</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-connect" title="pseudo_tcp_socket_connect ()">pseudo_tcp_socket_connect</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gint"><span class="returnvalue">gint</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-recv" title="pseudo_tcp_socket_recv ()">pseudo_tcp_socket_recv</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gint"><span class="returnvalue">gint</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-send" title="pseudo_tcp_socket_send ()">pseudo_tcp_socket_send</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-close" title="pseudo_tcp_socket_close ()">pseudo_tcp_socket_close</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-shutdown" title="pseudo_tcp_socket_shutdown ()">pseudo_tcp_socket_shutdown</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-is-closed" title="pseudo_tcp_socket_is_closed ()">pseudo_tcp_socket_is_closed</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-is-closed-remotely" title="pseudo_tcp_socket_is_closed_remotely ()">pseudo_tcp_socket_is_closed_remotely</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">int</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-get-error" title="pseudo_tcp_socket_get_error ()">pseudo_tcp_socket_get_error</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-get-next-clock" title="pseudo_tcp_socket_get_next_clock ()">pseudo_tcp_socket_get_next_clock</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-notify-clock" title="pseudo_tcp_socket_notify_clock ()">pseudo_tcp_socket_notify_clock</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-notify-mtu" title="pseudo_tcp_socket_notify_mtu ()">pseudo_tcp_socket_notify_mtu</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-notify-packet" title="pseudo_tcp_socket_notify_packet ()">pseudo_tcp_socket_notify_packet</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-set-debug-level" title="pseudo_tcp_set_debug_level ()">pseudo_tcp_set_debug_level</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gint"><span class="returnvalue">gint</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-get-available-bytes" title="pseudo_tcp_socket_get_available_bytes ()">pseudo_tcp_socket_get_available_bytes</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-can-send" title="pseudo_tcp_socket_can_send ()">pseudo_tcp_socket_can_send</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gsize"><span class="returnvalue">gsize</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-get-available-send-space" title="pseudo_tcp_socket_get_available_send_space ()">pseudo_tcp_socket_get_available_send_space</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-notify-message" title="pseudo_tcp_socket_notify_message ()">pseudo_tcp_socket_notify_message</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-set-time" title="pseudo_tcp_socket_set_time ()">pseudo_tcp_socket_set_time</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect1">
+<a name="libnice-Pseudo-TCP-Socket.properties"></a><h2>Properties</h2>
+<div class="informaltable"><table class="informaltable" border="0">
+<colgroup>
+<col width="150px" class="properties_type">
+<col width="300px" class="properties_name">
+<col width="200px" class="properties_flags">
+</colgroup>
+<tbody>
+<tr>
+<td class="property_type"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a></td>
+<td class="property_name"><a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket--ack-delay" title="The “ack-delay” property">ack-delay</a></td>
+<td class="property_flags">Read / Write</td>
+</tr>
+<tr>
+<td class="property_type"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gpointer"><span class="type">gpointer</span></a></td>
+<td class="property_name"><a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket--callbacks" title="The “callbacks” property">callbacks</a></td>
+<td class="property_flags">Read / Write</td>
+</tr>
+<tr>
+<td class="property_type"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a></td>
+<td class="property_name"><a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket--conversation" title="The “conversation” property">conversation</a></td>
+<td class="property_flags">Read / Write / Construct Only</td>
+</tr>
+<tr>
+<td class="property_type"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="type">gboolean</span></a></td>
+<td class="property_name"><a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket--no-delay" title="The “no-delay” property">no-delay</a></td>
+<td class="property_flags">Read / Write</td>
+</tr>
+<tr>
+<td class="property_type"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a></td>
+<td class="property_name"><a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket--rcv-buf" title="The “rcv-buf” property">rcv-buf</a></td>
+<td class="property_flags">Read / Write</td>
+</tr>
+<tr>
+<td class="property_type"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a></td>
+<td class="property_name"><a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket--snd-buf" title="The “snd-buf” property">snd-buf</a></td>
+<td class="property_flags">Read / Write</td>
+</tr>
+<tr>
+<td class="property_type"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a></td>
+<td class="property_name"><a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket--state" title="The “state” property">state</a></td>
+<td class="property_flags">Read</td>
+</tr>
+<tr>
+<td class="property_type"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="type">gboolean</span></a></td>
+<td class="property_name"><a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket--support-fin-ack" title="The “support-fin-ack” property">support-fin-ack</a></td>
+<td class="property_flags">Read / Write / Construct Only</td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<a name="PseudoTcpSocket"></a><div class="refsect1">
+<a name="libnice-Pseudo-TCP-Socket.other"></a><h2>Types and Values</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="name">
+<col class="description">
+</colgroup>
+<tbody>
+<tr>
+<td class="datatype_keyword"> </td>
+<td class="function_name"><a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket-struct" title="PseudoTcpSocket">PseudoTcpSocket</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpState" title="enum PseudoTcpState">PseudoTcpState</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpWriteResult" title="enum PseudoTcpWriteResult">PseudoTcpWriteResult</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword"> </td>
+<td class="function_name"><a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpCallbacks" title="PseudoTcpCallbacks">PseudoTcpCallbacks</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpDebugLevel" title="enum PseudoTcpDebugLevel">PseudoTcpDebugLevel</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpShutdown" title="enum PseudoTcpShutdown">PseudoTcpShutdown</a></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect1">
+<a name="libnice-Pseudo-TCP-Socket.object-hierarchy"></a><h2>Object Hierarchy</h2>
+<pre class="screen"> <a href="/usr/share/gtk-doc/html/gobject/gobject-Enumeration-and-Flag-Types.html">GEnum</a>
+ <span class="lineart">├──</span> PseudoTcpDebugLevel
+ <span class="lineart">├──</span> PseudoTcpShutdown
+ <span class="lineart">├──</span> PseudoTcpState
+ <span class="lineart">╰──</span> PseudoTcpWriteResult
+ <a href="/usr/share/gtk-doc/html/gobject/gobject-The-Base-Object-Type.html#GObject-struct">GObject</a>
+ <span class="lineart">╰──</span> PseudoTcpSocket
+</pre>
+</div>
+<div class="refsect1">
+<a name="libnice-Pseudo-TCP-Socket.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include <pseudotcp.h>
+</pre>
+</div>
+<div class="refsect1">
+<a name="libnice-Pseudo-TCP-Socket.description"></a><h2>Description</h2>
+<p>The <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> is an object implementing a Pseudo Tcp Socket for use
+over UDP.
+The socket will implement a subset of the TCP stack to allow for a reliable
+transport over non-reliable sockets (such as UDP).</p>
+<p>See the file tests/test-pseudotcp.c in the source package for an example
+of how to use the object.</p>
+</div>
+<div class="refsect1">
+<a name="libnice-Pseudo-TCP-Socket.functions_details"></a><h2>Functions</h2>
+<div class="refsect2">
+<a name="pseudo-tcp-socket-new"></a><h3>pseudo_tcp_socket_new ()</h3>
+<pre class="programlisting"><a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="returnvalue">PseudoTcpSocket</span></a> *
+pseudo_tcp_socket_new (<em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint32"><span class="type">guint32</span></a> conversation</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpCallbacks" title="PseudoTcpCallbacks"><span class="type">PseudoTcpCallbacks</span></a> *callbacks</code></em>);</pre>
+<p>Creates a new <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> for the specified conversation</p>
+<div class="note">
+<p>
+ The <em class="parameter"><code>callbacks</code></em> must be non-NULL, in order to get notified of packets the
+ socket needs to send.
+ </p>
+<p>
+ If the <em class="parameter"><code>callbacks</code></em> structure was dynamicly allocated, it can be freed
+ after the call <em class="parameter"><code>pseudo_tcp_socket_new</code></em>
+ </p>
+</div>
+<div class="refsect3">
+<a name="pseudo-tcp-socket-new.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>conversation</p></td>
+<td class="parameter_description"><p>The conversation id for the socket.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>callbacks</p></td>
+<td class="parameter_description"><p>A pointer to the <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpCallbacks" title="PseudoTcpCallbacks"><span class="type">PseudoTcpCallbacks</span></a> structure for getting
+notified of the <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> events.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="pseudo-tcp-socket-new.returns"></a><h4>Returns</h4>
+<p> The new <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> object, <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS"><code class="literal">NULL</code></a> on error</p>
+</div>
+<p class="since">Since: <a class="link" href="ix08.html#api-index-0.0.11">0.0.11</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="pseudo-tcp-socket-connect"></a><h3>pseudo_tcp_socket_connect ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+pseudo_tcp_socket_connect (<em class="parameter"><code><a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> *self</code></em>);</pre>
+<p>Connects the <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> to the peer with the same conversation id.
+The connection will only be successful after the
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpCallbacks" title="PseudoTcpCallbacks"><code class="literal">PseudoTcpCallbacks</code></a>:PseudoTcpOpened callback is called</p>
+<div class="refsect3">
+<a name="pseudo-tcp-socket-connect.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>self</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> object.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="pseudo-tcp-socket-connect.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> on success, <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> on failure (not in <a href="/usr/share/gtk-doc/html/libnice/libnice-Pseudo-TCP-Socket.html#TCP-LISTEN:CAPS"><code class="literal">TCP_LISTEN</code></a> state)</p>
+<p> See also: <a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-get-error" title="pseudo_tcp_socket_get_error ()"><code class="function">pseudo_tcp_socket_get_error()</code></a> </p>
+</div>
+<p class="since">Since: <a class="link" href="ix08.html#api-index-0.0.11">0.0.11</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="pseudo-tcp-socket-recv"></a><h3>pseudo_tcp_socket_recv ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gint"><span class="returnvalue">gint</span></a>
+pseudo_tcp_socket_recv (<em class="parameter"><code><a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> *self</code></em>,
+ <em class="parameter"><code><span class="type">char</span> *buffer</code></em>,
+ <em class="parameter"><code><span class="type">size_t</span> len</code></em>);</pre>
+<p>Receive data from the socket.</p>
+<div class="note">
+<p>
+ Only call this on the <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpCallbacks" title="PseudoTcpCallbacks"><code class="literal">PseudoTcpCallbacks</code></a>:PseudoTcpReadable callback.
+ </p>
+<p>
+ This function should be called in a loop. If this function does not
+ return -1 with EWOULDBLOCK as the error, the
+ <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpCallbacks" title="PseudoTcpCallbacks"><code class="literal">PseudoTcpCallbacks</code></a>:PseudoTcpReadable callback will not be called again.
+ </p>
+</div>
+<div class="refsect3">
+<a name="pseudo-tcp-socket-recv.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>self</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> object.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>The buffer to fill with received data</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>len</p></td>
+<td class="parameter_description"><p>The length of <em class="parameter"><code>buffer</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="pseudo-tcp-socket-recv.returns"></a><h4>Returns</h4>
+<p> The number of bytes received or -1 in case of error</p>
+<p> See also: <a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-get-error" title="pseudo_tcp_socket_get_error ()"><code class="function">pseudo_tcp_socket_get_error()</code></a> </p>
+</div>
+<p class="since">Since: <a class="link" href="ix08.html#api-index-0.0.11">0.0.11</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="pseudo-tcp-socket-send"></a><h3>pseudo_tcp_socket_send ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gint"><span class="returnvalue">gint</span></a>
+pseudo_tcp_socket_send (<em class="parameter"><code><a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> *self</code></em>,
+ <em class="parameter"><code>const <span class="type">char</span> *buffer</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint32"><span class="type">guint32</span></a> len</code></em>);</pre>
+<p>Send data on the socket.</p>
+<div class="note"><p>
+ If this function return -1 with EWOULDBLOCK as the error, or if the return
+ value is lower than <em class="parameter"><code>len</code></em>, then the <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpCallbacks" title="PseudoTcpCallbacks"><code class="literal">PseudoTcpCallbacks</code></a>:PseudoTcpWritable
+ callback will be called when the socket will become writable.
+ </p></div>
+<div class="refsect3">
+<a name="pseudo-tcp-socket-send.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>self</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> object.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>The buffer with data to send</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>len</p></td>
+<td class="parameter_description"><p>The length of <em class="parameter"><code>buffer</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="pseudo-tcp-socket-send.returns"></a><h4>Returns</h4>
+<p> The number of bytes sent or -1 in case of error</p>
+<p> See also: <a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-get-error" title="pseudo_tcp_socket_get_error ()"><code class="function">pseudo_tcp_socket_get_error()</code></a> </p>
+</div>
+<p class="since">Since: <a class="link" href="ix08.html#api-index-0.0.11">0.0.11</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="pseudo-tcp-socket-close"></a><h3>pseudo_tcp_socket_close ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+pseudo_tcp_socket_close (<em class="parameter"><code><a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> *self</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="type">gboolean</span></a> force</code></em>);</pre>
+<p>Close the socket for sending. If <em class="parameter"><code>force</code></em>
+ is set to <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a>, the socket will
+finish sending pending data before closing. If it is set to <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a>, the socket
+will discard pending data and close the connection immediately (sending a TCP
+RST segment).</p>
+<p>The socket will be closed in both directions – sending and receiving – and
+any pending received data must be read before calling this function, by
+calling <a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-recv" title="pseudo_tcp_socket_recv ()"><code class="function">pseudo_tcp_socket_recv()</code></a> until it blocks. If any pending data is in
+the receive buffer when <a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-close" title="pseudo_tcp_socket_close ()"><code class="function">pseudo_tcp_socket_close()</code></a> is called, a TCP RST
+segment will be sent to the peer to notify it of the data loss.</p>
+<div class="note"><p>
+ The <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpCallbacks" title="PseudoTcpCallbacks"><code class="literal">PseudoTcpCallbacks</code></a>:PseudoTcpClosed callback will not be called once
+ the socket gets closed. It is only used for aborted connection.
+ Instead, the socket gets closed when the <a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-get-next-clock" title="pseudo_tcp_socket_get_next_clock ()"><code class="function">pseudo_tcp_socket_get_next_clock()</code></a>
+ function returns FALSE.
+ </p></div>
+<p> See also: <a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-get-next-clock" title="pseudo_tcp_socket_get_next_clock ()"><code class="function">pseudo_tcp_socket_get_next_clock()</code></a> </p>
+<div class="refsect3">
+<a name="pseudo-tcp-socket-close.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>self</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> object.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>force</p></td>
+<td class="parameter_description"><p><a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> to close the socket forcefully, <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> to close it gracefully</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="ix08.html#api-index-0.0.11">0.0.11</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="pseudo-tcp-socket-shutdown"></a><h3>pseudo_tcp_socket_shutdown ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+pseudo_tcp_socket_shutdown (<em class="parameter"><code><a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> *self</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpShutdown" title="enum PseudoTcpShutdown"><span class="type">PseudoTcpShutdown</span></a> how</code></em>);</pre>
+<p>Shut down sending, receiving, or both on the socket, depending on the value
+of <em class="parameter"><code>how</code></em>
+. The behaviour of <a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-send" title="pseudo_tcp_socket_send ()"><code class="function">pseudo_tcp_socket_send()</code></a> and
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-recv" title="pseudo_tcp_socket_recv ()"><code class="function">pseudo_tcp_socket_recv()</code></a> will immediately change after this function returns
+(depending on the value of <em class="parameter"><code>how</code></em>
+), though the socket may continue to process
+network traffic in the background even if sending or receiving data is
+forbidden.</p>
+<p>This is equivalent to the POSIX <code class="function">shutdown()</code> function. Setting <em class="parameter"><code>how</code></em>
+ to
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#PSEUDO-TCP-SHUTDOWN-RDWR:CAPS"><code class="literal">PSEUDO_TCP_SHUTDOWN_RDWR</code></a> is equivalent to calling <a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-close" title="pseudo_tcp_socket_close ()"><code class="function">pseudo_tcp_socket_close()</code></a>.</p>
+<div class="refsect3">
+<a name="pseudo-tcp-socket-shutdown.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>self</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> object.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>how</p></td>
+<td class="parameter_description"><p>The directions of the connection to shut down.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="ix12.html#api-index-0.1.8">0.1.8</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="pseudo-tcp-socket-is-closed"></a><h3>pseudo_tcp_socket_is_closed ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+pseudo_tcp_socket_is_closed (<em class="parameter"><code><a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> *self</code></em>);</pre>
+<p>Gets whether the socket is closed, with the shutdown handshake completed,
+and both peers no longer able to read or write data to the connection.</p>
+<div class="refsect3">
+<a name="pseudo-tcp-socket-is-closed.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>self</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> object.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="pseudo-tcp-socket-is-closed.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> if the socket is closed in both directions, <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> otherwise</p>
+</div>
+<p class="since">Since: <a class="link" href="ix12.html#api-index-0.1.8">0.1.8</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="pseudo-tcp-socket-is-closed-remotely"></a><h3>pseudo_tcp_socket_is_closed_remotely ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+pseudo_tcp_socket_is_closed_remotely (<em class="parameter"><code><a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> *self</code></em>);</pre>
+<p>Gets whether the socket has been closed on the remote peer’s side of the
+connection (i.e. whether <a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-close" title="pseudo_tcp_socket_close ()"><code class="function">pseudo_tcp_socket_close()</code></a> has been called there).
+This is guaranteed to return <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> if <a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-is-closed" title="pseudo_tcp_socket_is_closed ()"><code class="function">pseudo_tcp_socket_is_closed()</code></a> returns
+<a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a>. It will not return <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> after <a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-close" title="pseudo_tcp_socket_close ()"><code class="function">pseudo_tcp_socket_close()</code></a> is called
+until a FIN segment is received from the remote peer.</p>
+<div class="refsect3">
+<a name="pseudo-tcp-socket-is-closed-remotely.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>self</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> object.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="pseudo-tcp-socket-is-closed-remotely.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> if the remote peer has closed its side of the connection,
+<a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> otherwise</p>
+</div>
+<p class="since">Since: <a class="link" href="ix12.html#api-index-0.1.8">0.1.8</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="pseudo-tcp-socket-get-error"></a><h3>pseudo_tcp_socket_get_error ()</h3>
+<pre class="programlisting"><span class="returnvalue">int</span>
+pseudo_tcp_socket_get_error (<em class="parameter"><code><a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> *self</code></em>);</pre>
+<p>Return the last encountered error.</p>
+<div class="note">
+<p>
+ The return value can be :
+ </p>
+<p>
+ EINVAL (for <a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-connect" title="pseudo_tcp_socket_connect ()"><code class="function">pseudo_tcp_socket_connect()</code></a>).
+ </p>
+<p>
+ </p>
+<p>
+ EWOULDBLOCK or ENOTCONN (for <a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-recv" title="pseudo_tcp_socket_recv ()"><code class="function">pseudo_tcp_socket_recv()</code></a> and
+ <a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-send" title="pseudo_tcp_socket_send ()"><code class="function">pseudo_tcp_socket_send()</code></a>).
+ </p>
+<p>
+ </p>
+</div>
+<div class="refsect3">
+<a name="pseudo-tcp-socket-get-error.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>self</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> object.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="pseudo-tcp-socket-get-error.returns"></a><h4>Returns</h4>
+<p> The error code</p>
+<p> See also: <a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-connect" title="pseudo_tcp_socket_connect ()"><code class="function">pseudo_tcp_socket_connect()</code></a> </p>
+<p> See also: <a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-recv" title="pseudo_tcp_socket_recv ()"><code class="function">pseudo_tcp_socket_recv()</code></a> </p>
+<p> See also: <a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-send" title="pseudo_tcp_socket_send ()"><code class="function">pseudo_tcp_socket_send()</code></a> </p>
+</div>
+<p class="since">Since: <a class="link" href="ix08.html#api-index-0.0.11">0.0.11</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="pseudo-tcp-socket-get-next-clock"></a><h3>pseudo_tcp_socket_get_next_clock ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+pseudo_tcp_socket_get_next_clock (<em class="parameter"><code><a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> *self</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint64"><span class="type">guint64</span></a> *timeout</code></em>);</pre>
+<p>Call this to determine the timeout needed before the next time call
+to <a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-notify-clock" title="pseudo_tcp_socket_notify_clock ()"><code class="function">pseudo_tcp_socket_notify_clock()</code></a> should be made.</p>
+<div class="refsect3">
+<a name="pseudo-tcp-socket-get-next-clock.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>self</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> object.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>timeout</p></td>
+<td class="parameter_description"><p>A pointer to be filled with the new timeout.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="pseudo-tcp-socket-get-next-clock.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> if <em class="parameter"><code>timeout</code></em>
+was filled, <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> if the socket is closed and
+ready to be destroyed.</p>
+<p> See also: <a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-notify-clock" title="pseudo_tcp_socket_notify_clock ()"><code class="function">pseudo_tcp_socket_notify_clock()</code></a> </p>
+</div>
+<p class="since">Since: <a class="link" href="ix08.html#api-index-0.0.11">0.0.11</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="pseudo-tcp-socket-notify-clock"></a><h3>pseudo_tcp_socket_notify_clock ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+pseudo_tcp_socket_notify_clock (<em class="parameter"><code><a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> *self</code></em>);</pre>
+<p>Start the processing of receiving data, pending data or syn/acks.
+Call this based on timeout value returned by
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-get-next-clock" title="pseudo_tcp_socket_get_next_clock ()"><code class="function">pseudo_tcp_socket_get_next_clock()</code></a>.
+It's ok to call this too frequently.</p>
+<p> See also: <a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-get-next-clock" title="pseudo_tcp_socket_get_next_clock ()"><code class="function">pseudo_tcp_socket_get_next_clock()</code></a> </p>
+<div class="refsect3">
+<a name="pseudo-tcp-socket-notify-clock.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>self</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> object.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="ix08.html#api-index-0.0.11">0.0.11</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="pseudo-tcp-socket-notify-mtu"></a><h3>pseudo_tcp_socket_notify_mtu ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+pseudo_tcp_socket_notify_mtu (<em class="parameter"><code><a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> *self</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint16"><span class="type">guint16</span></a> mtu</code></em>);</pre>
+<p>Set the MTU of the socket</p>
+<div class="refsect3">
+<a name="pseudo-tcp-socket-notify-mtu.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>self</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> object.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>mtu</p></td>
+<td class="parameter_description"><p>The new MTU of the socket</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="ix08.html#api-index-0.0.11">0.0.11</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="pseudo-tcp-socket-notify-packet"></a><h3>pseudo_tcp_socket_notify_packet ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+pseudo_tcp_socket_notify_packet (<em class="parameter"><code><a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> *self</code></em>,
+ <em class="parameter"><code>const <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gchar"><span class="type">gchar</span></a> *buffer</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint32"><span class="type">guint32</span></a> len</code></em>);</pre>
+<p>Notify the <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> when a new packet arrives</p>
+<div class="refsect3">
+<a name="pseudo-tcp-socket-notify-packet.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>self</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> object.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>The buffer containing the received data</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>len</p></td>
+<td class="parameter_description"><p>The length of <em class="parameter"><code>buffer</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="pseudo-tcp-socket-notify-packet.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> if the packet was processed successfully, <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> otherwise</p>
+</div>
+<p class="since">Since: <a class="link" href="ix08.html#api-index-0.0.11">0.0.11</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="pseudo-tcp-set-debug-level"></a><h3>pseudo_tcp_set_debug_level ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+pseudo_tcp_set_debug_level (<em class="parameter"><code><a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpDebugLevel" title="enum PseudoTcpDebugLevel"><span class="type">PseudoTcpDebugLevel</span></a> level</code></em>);</pre>
+<p>Sets the debug level to enable/disable normal/verbose debug messages.</p>
+<div class="refsect3">
+<a name="pseudo-tcp-set-debug-level.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>level</p></td>
+<td class="parameter_description"><p>The level of debug to set</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="ix08.html#api-index-0.0.11">0.0.11</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="pseudo-tcp-socket-get-available-bytes"></a><h3>pseudo_tcp_socket_get_available_bytes ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gint"><span class="returnvalue">gint</span></a>
+pseudo_tcp_socket_get_available_bytes (<em class="parameter"><code><a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> *self</code></em>);</pre>
+<p>Gets the number of bytes of data in the buffer that can be read without
+receiving more packets from the network.</p>
+<div class="refsect3">
+<a name="pseudo-tcp-socket-get-available-bytes.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>self</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> object.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="pseudo-tcp-socket-get-available-bytes.returns"></a><h4>Returns</h4>
+<p> The number of bytes or -1 if the connection is not established</p>
+</div>
+<p class="since">Since: <a class="link" href="ix10.html#api-index-0.1.5">0.1.5</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="pseudo-tcp-socket-can-send"></a><h3>pseudo_tcp_socket_can_send ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+pseudo_tcp_socket_can_send (<em class="parameter"><code><a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> *self</code></em>);</pre>
+<p>Returns if there is space in the send buffer to send any data.</p>
+<div class="refsect3">
+<a name="pseudo-tcp-socket-can-send.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>self</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> object.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="pseudo-tcp-socket-can-send.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> if data can be sent, <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> otherwise</p>
+</div>
+<p class="since">Since: <a class="link" href="ix10.html#api-index-0.1.5">0.1.5</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="pseudo-tcp-socket-get-available-send-space"></a><h3>pseudo_tcp_socket_get_available_send_space ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gsize"><span class="returnvalue">gsize</span></a>
+pseudo_tcp_socket_get_available_send_space
+ (<em class="parameter"><code><a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> *self</code></em>);</pre>
+<p>Gets the number of bytes of space available in the transmission buffer.</p>
+<div class="refsect3">
+<a name="pseudo-tcp-socket-get-available-send-space.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>self</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> object.</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="pseudo-tcp-socket-get-available-send-space.returns"></a><h4>Returns</h4>
+<p> The number of bytes, or 0 if the connection is not established.</p>
+</div>
+<p class="since">Since: <a class="link" href="ix10.html#api-index-0.1.5">0.1.5</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="pseudo-tcp-socket-notify-message"></a><h3>pseudo_tcp_socket_notify_message ()</h3>
+<pre class="programlisting"><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="returnvalue">gboolean</span></a>
+pseudo_tcp_socket_notify_message (<em class="parameter"><code><a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> *self</code></em>,
+ <em class="parameter"><code><a class="link" href="NiceAgent.html#NiceInputMessage" title="NiceInputMessage"><span class="type">NiceInputMessage</span></a> *message</code></em>);</pre>
+<p>Notify the <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> that a new message has arrived, and enqueue the
+data in its buffers to the <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a>’s receive buffer.</p>
+<div class="refsect3">
+<a name="pseudo-tcp-socket-notify-message.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>self</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> object.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>message</p></td>
+<td class="parameter_description"><p>A <a class="link" href="NiceAgent.html#NiceInputMessage" title="NiceInputMessage"><span class="type">NiceInputMessage</span></a> containing the received data.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="pseudo-tcp-socket-notify-message.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> if the packet was processed successfully, <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> otherwise</p>
+</div>
+<p class="since">Since: <a class="link" href="ix10.html#api-index-0.1.5">0.1.5</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="pseudo-tcp-socket-set-time"></a><h3>pseudo_tcp_socket_set_time ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+pseudo_tcp_socket_set_time (<em class="parameter"><code><a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> *self</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint32"><span class="type">guint32</span></a> current_time</code></em>);</pre>
+<p>Sets the current monotonic time to be used by the TCP socket when calculating
+timeouts and expiry times. If this function is not called, or is called with
+<em class="parameter"><code>current_time</code></em>
+ as zero, <a href="/usr/share/gtk-doc/html/glib/glib-Date-and-Time-Functions.html#g-get-monotonic-time"><code class="function">g_get_monotonic_time()</code></a> will be used. Otherwise, the
+specified <em class="parameter"><code>current_time</code></em>
+ will be used until it is updated by calling this
+function again.</p>
+<p>This function is intended for testing only, and should not be used in
+production code.</p>
+<div class="refsect3">
+<a name="pseudo-tcp-socket-set-time.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>self</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> object.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>current_time</p></td>
+<td class="parameter_description"><p>Current monotonic time, in milliseconds; or zero to use the
+system monotonic clock.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="ix12.html#api-index-0.1.8">0.1.8</a></p>
+</div>
+</div>
+<div class="refsect1">
+<a name="libnice-Pseudo-TCP-Socket.other_details"></a><h2>Types and Values</h2>
+<div class="refsect2">
+<a name="PseudoTcpSocket-struct"></a><h3>PseudoTcpSocket</h3>
+<pre class="programlisting">typedef struct _PseudoTcpSocket PseudoTcpSocket;</pre>
+<p>The <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> is the GObject implementing the Pseudo TCP Socket</p>
+<p class="since">Since: <a class="link" href="ix08.html#api-index-0.0.11">0.0.11</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="PseudoTcpState"></a><h3>enum PseudoTcpState</h3>
+<p>An enum representing the state of the <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a>. These states
+correspond to the TCP states in RFC 793.</p>
+<p> See also: <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket--state" title="The “state” property"><span class="type">“state”</span></a> </p>
+<div class="refsect3">
+<a name="PseudoTcpState.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="PSEUDO-TCP-LISTEN:CAPS"></a>PSEUDO_TCP_LISTEN</p></td>
+<td class="enum_member_description">
+<p>The socket's initial state. The socket isn't connected and is
+listening for an incoming connection</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="PSEUDO-TCP-SYN-SENT:CAPS"></a>PSEUDO_TCP_SYN_SENT</p></td>
+<td class="enum_member_description">
+<p>The socket has sent a connection request (SYN) packet and is
+waiting for an answer</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="PSEUDO-TCP-SYN-RECEIVED:CAPS"></a>PSEUDO_TCP_SYN_RECEIVED</p></td>
+<td class="enum_member_description">
+<p>The socket has received a connection request (SYN) packet.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="PSEUDO-TCP-ESTABLISHED:CAPS"></a>PSEUDO_TCP_ESTABLISHED</p></td>
+<td class="enum_member_description">
+<p>The socket is connected</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="PSEUDO-TCP-CLOSED:CAPS"></a>PSEUDO_TCP_CLOSED</p></td>
+<td class="enum_member_description">
+<p>The socket has been closed</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="PSEUDO-TCP-FIN-WAIT-1:CAPS"></a>PSEUDO_TCP_FIN_WAIT_1</p></td>
+<td class="enum_member_description">
+<p>The socket has been closed locally but not remotely
+(Since: 0.1.8)</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="PSEUDO-TCP-FIN-WAIT-2:CAPS"></a>PSEUDO_TCP_FIN_WAIT_2</p></td>
+<td class="enum_member_description">
+<p>The socket has been closed locally but not remotely
+(Since: 0.1.8)</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="PSEUDO-TCP-CLOSING:CAPS"></a>PSEUDO_TCP_CLOSING</p></td>
+<td class="enum_member_description">
+<p>The socket has been closed locally and remotely
+(Since: 0.1.8)</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="PSEUDO-TCP-TIME-WAIT:CAPS"></a>PSEUDO_TCP_TIME_WAIT</p></td>
+<td class="enum_member_description">
+<p>The socket has been closed locally and remotely
+(Since: 0.1.8)</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="PSEUDO-TCP-CLOSE-WAIT:CAPS"></a>PSEUDO_TCP_CLOSE_WAIT</p></td>
+<td class="enum_member_description">
+<p>The socket has been closed remotely but not locally
+(Since: 0.1.8)</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="PSEUDO-TCP-LAST-ACK:CAPS"></a>PSEUDO_TCP_LAST_ACK</p></td>
+<td class="enum_member_description">
+<p>The socket has been closed locally and remotely
+(Since: 0.1.8)</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="ix08.html#api-index-0.0.11">0.0.11</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="PseudoTcpWriteResult"></a><h3>enum PseudoTcpWriteResult</h3>
+<p>An enum representing the result value of the write operation requested by
+the <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a>.</p>
+<p> See also: <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpCallbacks" title="PseudoTcpCallbacks"><code class="literal">PseudoTcpCallbacks</code></a>:WritePacket </p>
+<div class="refsect3">
+<a name="PseudoTcpWriteResult.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="WR-SUCCESS:CAPS"></a>WR_SUCCESS</p></td>
+<td class="enum_member_description">
+<p>The write operation was successful</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="WR-TOO-LARGE:CAPS"></a>WR_TOO_LARGE</p></td>
+<td class="enum_member_description">
+<p>The socket type requires that message be sent atomically
+and the size of the message to be sent made this impossible.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="WR-FAIL:CAPS"></a>WR_FAIL</p></td>
+<td class="enum_member_description">
+<p>There was an error sending the message</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="ix08.html#api-index-0.0.11">0.0.11</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="PseudoTcpCallbacks"></a><h3>PseudoTcpCallbacks</h3>
+<pre class="programlisting">typedef struct {
+ gpointer user_data;
+ void (*PseudoTcpOpened) (PseudoTcpSocket *tcp, gpointer data);
+ void (*PseudoTcpReadable) (PseudoTcpSocket *tcp, gpointer data);
+ void (*PseudoTcpWritable) (PseudoTcpSocket *tcp, gpointer data);
+ void (*PseudoTcpClosed) (PseudoTcpSocket *tcp, guint32 error, gpointer data);
+ PseudoTcpWriteResult (*WritePacket) (PseudoTcpSocket *tcp,
+ const gchar * buffer, guint32 len, gpointer data);
+} PseudoTcpCallbacks;
+</pre>
+<p>A structure containing callbacks functions that will be called by the
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> when some events happen.</p>
+<p> See also: <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpWriteResult" title="enum PseudoTcpWriteResult"><span class="type">PseudoTcpWriteResult</span></a> </p>
+<div class="refsect3">
+<a name="PseudoTcpCallbacks.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="struct_members_name">
+<col class="struct_members_description">
+<col width="200px" class="struct_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="struct_member_name"><p><a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gpointer"><span class="type">gpointer</span></a> <em class="structfield"><code><a name="PseudoTcpCallbacks.user-data"></a>user_data</code></em>;</p></td>
+<td class="struct_member_description"><p>A user defined pointer to be passed to the callbacks</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><em class="structfield"><code><a name="PseudoTcpCallbacks.PseudoTcpOpened"></a>PseudoTcpOpened</code></em> ()</p></td>
+<td class="struct_member_description"><p>The <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> is now connected</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><em class="structfield"><code><a name="PseudoTcpCallbacks.PseudoTcpReadable"></a>PseudoTcpReadable</code></em> ()</p></td>
+<td class="struct_member_description"><p>The socket is readable</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><em class="structfield"><code><a name="PseudoTcpCallbacks.PseudoTcpWritable"></a>PseudoTcpWritable</code></em> ()</p></td>
+<td class="struct_member_description"><p>The socket is writable</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><em class="structfield"><code><a name="PseudoTcpCallbacks.PseudoTcpClosed"></a>PseudoTcpClosed</code></em> ()</p></td>
+<td class="struct_member_description"><p>The socket was closed (both sides)</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><em class="structfield"><code><a name="PseudoTcpCallbacks.WritePacket"></a>WritePacket</code></em> ()</p></td>
+<td class="struct_member_description"><p>This callback is called when the socket needs to send data.</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="ix08.html#api-index-0.0.11">0.0.11</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="PseudoTcpDebugLevel"></a><h3>enum PseudoTcpDebugLevel</h3>
+<p>Valid values of debug levels to be set.</p>
+<div class="refsect3">
+<a name="PseudoTcpDebugLevel.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="PSEUDO-TCP-DEBUG-NONE:CAPS"></a>PSEUDO_TCP_DEBUG_NONE</p></td>
+<td class="enum_member_description">
+<p>Disable debug messages</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="PSEUDO-TCP-DEBUG-NORMAL:CAPS"></a>PSEUDO_TCP_DEBUG_NORMAL</p></td>
+<td class="enum_member_description">
+<p>Enable basic debug messages</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="PSEUDO-TCP-DEBUG-VERBOSE:CAPS"></a>PSEUDO_TCP_DEBUG_VERBOSE</p></td>
+<td class="enum_member_description">
+<p>Enable verbose debug messages</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="ix08.html#api-index-0.0.11">0.0.11</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="PseudoTcpShutdown"></a><h3>enum PseudoTcpShutdown</h3>
+<p>Options for which parts of a connection to shut down when calling
+<a class="link" href="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-shutdown" title="pseudo_tcp_socket_shutdown ()"><code class="function">pseudo_tcp_socket_shutdown()</code></a>. These correspond to the values passed to POSIX
+<code class="function">shutdown()</code>.</p>
+<div class="refsect3">
+<a name="PseudoTcpShutdown.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="PSEUDO-TCP-SHUTDOWN-RD:CAPS"></a>PSEUDO_TCP_SHUTDOWN_RD</p></td>
+<td class="enum_member_description">
+<p>Shut down the local reader only</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="PSEUDO-TCP-SHUTDOWN-WR:CAPS"></a>PSEUDO_TCP_SHUTDOWN_WR</p></td>
+<td class="enum_member_description">
+<p>Shut down the local writer only</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="PSEUDO-TCP-SHUTDOWN-RDWR:CAPS"></a>PSEUDO_TCP_SHUTDOWN_RDWR</p></td>
+<td class="enum_member_description">
+<p>Shut down both reading and writing</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="ix12.html#api-index-0.1.8">0.1.8</a></p>
+</div>
+</div>
+<div class="refsect1">
+<a name="libnice-Pseudo-TCP-Socket.property-details"></a><h2>Property Details</h2>
+<div class="refsect2">
+<a name="PseudoTcpSocket--ack-delay"></a><h3>The <code class="literal">“ack-delay”</code> property</h3>
+<pre class="programlisting"> “ack-delay” <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a></pre>
+<p>Delayed ACK timeout (in milliseconds).</p>
+<p>Flags: Read / Write</p>
+<p>Default value: 100</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="PseudoTcpSocket--callbacks"></a><h3>The <code class="literal">“callbacks”</code> property</h3>
+<pre class="programlisting"> “callbacks” <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gpointer"><span class="type">gpointer</span></a></pre>
+<p>Structure with the callbacks to call when PseudoTcp events happen.</p>
+<p>Flags: Read / Write</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="PseudoTcpSocket--conversation"></a><h3>The <code class="literal">“conversation”</code> property</h3>
+<pre class="programlisting"> “conversation” <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a></pre>
+<p>The TCP Conversation ID.</p>
+<p>Flags: Read / Write / Construct Only</p>
+<p>Default value: 0</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="PseudoTcpSocket--no-delay"></a><h3>The <code class="literal">“no-delay”</code> property</h3>
+<pre class="programlisting"> “no-delay” <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="type">gboolean</span></a></pre>
+<p>Disable the Nagle algorithm (like the TCP_NODELAY option).</p>
+<p>Flags: Read / Write</p>
+<p>Default value: FALSE</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="PseudoTcpSocket--rcv-buf"></a><h3>The <code class="literal">“rcv-buf”</code> property</h3>
+<pre class="programlisting"> “rcv-buf” <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a></pre>
+<p>Receive Buffer size.</p>
+<p>Flags: Read / Write</p>
+<p>Allowed values: >= 1</p>
+<p>Default value: 61440</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="PseudoTcpSocket--snd-buf"></a><h3>The <code class="literal">“snd-buf”</code> property</h3>
+<pre class="programlisting"> “snd-buf” <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a></pre>
+<p>Send Buffer size.</p>
+<p>Flags: Read / Write</p>
+<p>Allowed values: >= 1</p>
+<p>Default value: 92160</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="PseudoTcpSocket--state"></a><h3>The <code class="literal">“state”</code> property</h3>
+<pre class="programlisting"> “state” <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#guint"><span class="type">guint</span></a></pre>
+<p>The current state (enum PseudoTcpState) of the PseudoTcp socket.</p>
+<p>Flags: Read</p>
+<p>Allowed values: <= 4</p>
+<p>Default value: 0</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="PseudoTcpSocket--support-fin-ack"></a><h3>The <code class="literal">“support-fin-ack”</code> property</h3>
+<pre class="programlisting"> “support-fin-ack” <a href="/usr/share/gtk-doc/html/glib/glib-Basic-Types.html#gboolean"><span class="type">gboolean</span></a></pre>
+<p>Whether to support the FIN–ACK extension to the pseudo-TCP protocol for
+this socket. The extension is only compatible with other libnice pseudo-TCP
+stacks, and not with Jingle pseudo-TCP stacks. If enabled, support is
+negotiatied on connection setup, so it is safe for a <a class="link" href="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket"><span class="type">PseudoTcpSocket</span></a> with
+support enabled to be used with one with it disabled, or with a Jingle
+pseudo-TCP socket which doesn’t support it at all.</p>
+<p>Support is enabled by default.</p>
+<p>Flags: Read / Write / Construct Only</p>
+<p>Default value: TRUE</p>
+<p class="since">Since: <a class="link" href="ix12.html#api-index-0.1.8">0.1.8</a></p>
+</div>
+</div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.29</div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>STUN Constants: libnice Reference Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets Vsnapshot">
+<link rel="home" href="index.html" title="libnice Reference Manual">
+<link rel="up" href="ch03.html" title="">
+<link rel="prev" href="libnice-StunMessage.html" title="StunMessage">
+<link rel="next" href="ch04.html" title="STUN usages">
+<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts">
+<a href="#" class="shortcut">Top</a><span id="nav_description"> <span class="dim">|</span>
+ <a href="#libnice-STUN-Constants.description" class="shortcut">Description</a></span>
+</td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="ch03.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="libnice-StunMessage.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="ch04.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="refentry">
+<a name="libnice-STUN-Constants"></a><div class="titlepage"></div>
+<div class="refnamediv"><table width="100%"><tr>
+<td valign="top">
+<h2><span class="refentrytitle"><a name="libnice-STUN-Constants.top_of_page"></a>STUN Constants</span></h2>
+<p>STUN Constants — STUN constants</p>
+</td>
+<td class="gallery_image" valign="top" align="right"></td>
+</tr></table></div>
+<div class="refsect1">
+<a name="libnice-STUN-Constants.stability-level"></a><h2>Stability Level</h2>
+<acronym title="The intention of a Stable interface is to enable arbitrary third parties to
+develop applications to these interfaces, release them, and have confidence that
+they will run on all minor releases of the product (after the one in which the
+interface was introduced, and within the same major release). Even at a major
+release, incompatible changes are expected to be rare, and to have strong
+justifications.
+"><span class="acronym">Stable</span></acronym>, unless otherwise indicated
+</div>
+<div class="refsect1">
+<a name="libnice-STUN-Constants.other"></a><h2>Types and Values</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="name">
+<col class="description">
+</colgroup>
+<tbody>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="libnice-STUN-Constants.html#STUN-AGENT-MAX-SAVED-IDS:CAPS" title="STUN_AGENT_MAX_SAVED_IDS">STUN_AGENT_MAX_SAVED_IDS</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="libnice-STUN-Constants.html#STUN-AGENT-MAX-UNKNOWN-ATTRIBUTES:CAPS" title="STUN_AGENT_MAX_UNKNOWN_ATTRIBUTES">STUN_AGENT_MAX_UNKNOWN_ATTRIBUTES</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="libnice-STUN-Constants.html#STUN-ATTRIBUTE-HEADER-LENGTH:CAPS" title="STUN_ATTRIBUTE_HEADER_LENGTH">STUN_ATTRIBUTE_HEADER_LENGTH</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="libnice-STUN-Constants.html#STUN-ATTRIBUTE-LENGTH-LEN:CAPS" title="STUN_ATTRIBUTE_LENGTH_LEN">STUN_ATTRIBUTE_LENGTH_LEN</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="libnice-STUN-Constants.html#STUN-ATTRIBUTE-LENGTH-POS:CAPS" title="STUN_ATTRIBUTE_LENGTH_POS">STUN_ATTRIBUTE_LENGTH_POS</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="libnice-STUN-Constants.html#STUN-ATTRIBUTE-TYPE-LEN:CAPS" title="STUN_ATTRIBUTE_TYPE_LEN">STUN_ATTRIBUTE_TYPE_LEN</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="libnice-STUN-Constants.html#STUN-ATTRIBUTE-TYPE-POS:CAPS" title="STUN_ATTRIBUTE_TYPE_POS">STUN_ATTRIBUTE_TYPE_POS</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="libnice-STUN-Constants.html#STUN-ATTRIBUTE-VALUE-POS:CAPS" title="STUN_ATTRIBUTE_VALUE_POS">STUN_ATTRIBUTE_VALUE_POS</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="libnice-STUN-Constants.html#STUN-ID-LEN:CAPS" title="STUN_ID_LEN">STUN_ID_LEN</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="libnice-STUN-Constants.html#STUN-MAGIC-COOKIE:CAPS" title="STUN_MAGIC_COOKIE">STUN_MAGIC_COOKIE</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="libnice-STUN-Constants.html#STUN-MAX-MESSAGE-SIZE:CAPS" title="STUN_MAX_MESSAGE_SIZE">STUN_MAX_MESSAGE_SIZE</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="libnice-STUN-Constants.html#STUN-MAX-MESSAGE-SIZE-IPV4:CAPS" title="STUN_MAX_MESSAGE_SIZE_IPV4">STUN_MAX_MESSAGE_SIZE_IPV4</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="libnice-STUN-Constants.html#STUN-MAX-MESSAGE-SIZE-IPV6:CAPS" title="STUN_MAX_MESSAGE_SIZE_IPV6">STUN_MAX_MESSAGE_SIZE_IPV6</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="libnice-STUN-Constants.html#STUN-MESSAGE-ATTRIBUTES-POS:CAPS" title="STUN_MESSAGE_ATTRIBUTES_POS">STUN_MESSAGE_ATTRIBUTES_POS</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="libnice-STUN-Constants.html#STUN-MESSAGE-HEADER-LENGTH:CAPS" title="STUN_MESSAGE_HEADER_LENGTH">STUN_MESSAGE_HEADER_LENGTH</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="libnice-STUN-Constants.html#STUN-MESSAGE-LENGTH-LEN:CAPS" title="STUN_MESSAGE_LENGTH_LEN">STUN_MESSAGE_LENGTH_LEN</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="libnice-STUN-Constants.html#STUN-MESSAGE-LENGTH-POS:CAPS" title="STUN_MESSAGE_LENGTH_POS">STUN_MESSAGE_LENGTH_POS</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="libnice-STUN-Constants.html#STUN-MESSAGE-TRANS-ID-LEN:CAPS" title="STUN_MESSAGE_TRANS_ID_LEN">STUN_MESSAGE_TRANS_ID_LEN</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="libnice-STUN-Constants.html#STUN-MESSAGE-TRANS-ID-POS:CAPS" title="STUN_MESSAGE_TRANS_ID_POS">STUN_MESSAGE_TRANS_ID_POS</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="libnice-STUN-Constants.html#STUN-MESSAGE-TYPE-LEN:CAPS" title="STUN_MESSAGE_TYPE_LEN">STUN_MESSAGE_TYPE_LEN</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="libnice-STUN-Constants.html#STUN-MESSAGE-TYPE-POS:CAPS" title="STUN_MESSAGE_TYPE_POS">STUN_MESSAGE_TYPE_POS</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="libnice-STUN-Constants.html#TURN-MAGIC-COOKIE:CAPS" title="TURN_MAGIC_COOKIE">TURN_MAGIC_COOKIE</a></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect1">
+<a name="libnice-STUN-Constants.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include <stun/constants.h>
+</pre>
+</div>
+<div class="refsect1">
+<a name="libnice-STUN-Constants.description"></a><h2>Description</h2>
+<p>Various constants defining parts of the STUN and TURN protocols and
+on-the-wire packet formats.</p>
+</div>
+<div class="refsect1">
+<a name="libnice-STUN-Constants.functions_details"></a><h2>Functions</h2>
+<p></p>
+</div>
+<div class="refsect1">
+<a name="libnice-STUN-Constants.other_details"></a><h2>Types and Values</h2>
+<div class="refsect2">
+<a name="STUN-AGENT-MAX-SAVED-IDS:CAPS"></a><h3>STUN_AGENT_MAX_SAVED_IDS</h3>
+<pre class="programlisting">#define STUN_AGENT_MAX_SAVED_IDS 200
+</pre>
+<p>Maximum number of simultaneously ongoing STUN transactions.</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="STUN-AGENT-MAX-UNKNOWN-ATTRIBUTES:CAPS"></a><h3>STUN_AGENT_MAX_UNKNOWN_ATTRIBUTES</h3>
+<pre class="programlisting">#define STUN_AGENT_MAX_UNKNOWN_ATTRIBUTES 256
+</pre>
+<p>Maximum number of unknown attribute which can be handled in a single STUN
+message.</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="STUN-ATTRIBUTE-HEADER-LENGTH:CAPS"></a><h3>STUN_ATTRIBUTE_HEADER_LENGTH</h3>
+<pre class="programlisting">#define STUN_ATTRIBUTE_HEADER_LENGTH STUN_ATTRIBUTE_VALUE_POS
+</pre>
+<p>Length of a single STUN attribute header (in bytes).</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="STUN-ATTRIBUTE-LENGTH-LEN:CAPS"></a><h3>STUN_ATTRIBUTE_LENGTH_LEN</h3>
+<pre class="programlisting">#define STUN_ATTRIBUTE_LENGTH_LEN 2
+</pre>
+<p>Length of the length field of a STUN attribute (in bytes).</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="STUN-ATTRIBUTE-LENGTH-POS:CAPS"></a><h3>STUN_ATTRIBUTE_LENGTH_POS</h3>
+<pre class="programlisting">#define STUN_ATTRIBUTE_LENGTH_POS</pre>
+<p>Offset of the length field of a STUN attribute (in bytes).</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="STUN-ATTRIBUTE-TYPE-LEN:CAPS"></a><h3>STUN_ATTRIBUTE_TYPE_LEN</h3>
+<pre class="programlisting">#define STUN_ATTRIBUTE_TYPE_LEN 2
+</pre>
+<p>Length of the type field of a STUN attribute (in bytes).</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="STUN-ATTRIBUTE-TYPE-POS:CAPS"></a><h3>STUN_ATTRIBUTE_TYPE_POS</h3>
+<pre class="programlisting">#define STUN_ATTRIBUTE_TYPE_POS 0
+</pre>
+<p>Offset of the type field of a STUN attribute (in bytes).</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="STUN-ATTRIBUTE-VALUE-POS:CAPS"></a><h3>STUN_ATTRIBUTE_VALUE_POS</h3>
+<pre class="programlisting">#define STUN_ATTRIBUTE_VALUE_POS</pre>
+<p>Offset of the value field of a STUN attribute (in bytes).</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="STUN-ID-LEN:CAPS"></a><h3>STUN_ID_LEN</h3>
+<pre class="programlisting">#define STUN_ID_LEN 16
+</pre>
+<p>Length of the ID field of a STUN message (in bytes).</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="STUN-MAGIC-COOKIE:CAPS"></a><h3>STUN_MAGIC_COOKIE</h3>
+<pre class="programlisting">#define STUN_MAGIC_COOKIE 0x2112A442
+</pre>
+<p>Magic cookie value used to identify STUN messages.</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="STUN-MAX-MESSAGE-SIZE:CAPS"></a><h3>STUN_MAX_MESSAGE_SIZE</h3>
+<pre class="programlisting">#define STUN_MAX_MESSAGE_SIZE 65552
+</pre>
+<p>The Maximum size of a STUN message</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="STUN-MAX-MESSAGE-SIZE-IPV4:CAPS"></a><h3>STUN_MAX_MESSAGE_SIZE_IPV4</h3>
+<pre class="programlisting">#define STUN_MAX_MESSAGE_SIZE_IPV4 576
+</pre>
+<p>Maximum size of a STUN message sent over IPv4 (in bytes).</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="STUN-MAX-MESSAGE-SIZE-IPV6:CAPS"></a><h3>STUN_MAX_MESSAGE_SIZE_IPV6</h3>
+<pre class="programlisting">#define STUN_MAX_MESSAGE_SIZE_IPV6 1280
+</pre>
+<p>Maximum size of a STUN message sent over IPv6 (in bytes).</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="STUN-MESSAGE-ATTRIBUTES-POS:CAPS"></a><h3>STUN_MESSAGE_ATTRIBUTES_POS</h3>
+<pre class="programlisting">#define STUN_MESSAGE_ATTRIBUTES_POS</pre>
+<p>Offset of the attributes of a STUN message (in bytes).</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="STUN-MESSAGE-HEADER-LENGTH:CAPS"></a><h3>STUN_MESSAGE_HEADER_LENGTH</h3>
+<pre class="programlisting">#define STUN_MESSAGE_HEADER_LENGTH STUN_MESSAGE_ATTRIBUTES_POS
+</pre>
+<p>Total length of a STUN message header (in bytes).</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="STUN-MESSAGE-LENGTH-LEN:CAPS"></a><h3>STUN_MESSAGE_LENGTH_LEN</h3>
+<pre class="programlisting">#define STUN_MESSAGE_LENGTH_LEN 2
+</pre>
+<p>Length of the length field of a STUN message (in bytes).</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="STUN-MESSAGE-LENGTH-POS:CAPS"></a><h3>STUN_MESSAGE_LENGTH_POS</h3>
+<pre class="programlisting">#define STUN_MESSAGE_LENGTH_POS</pre>
+<p>Offset of the length field of a STUN message (in bytes).</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="STUN-MESSAGE-TRANS-ID-LEN:CAPS"></a><h3>STUN_MESSAGE_TRANS_ID_LEN</h3>
+<pre class="programlisting">#define STUN_MESSAGE_TRANS_ID_LEN 16
+</pre>
+<p>Length of the transaction ID field of a STUN message (in bytes).</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="STUN-MESSAGE-TRANS-ID-POS:CAPS"></a><h3>STUN_MESSAGE_TRANS_ID_POS</h3>
+<pre class="programlisting">#define STUN_MESSAGE_TRANS_ID_POS</pre>
+<p>Offset of the transaction ID field of a STUN message (in bytes).</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="STUN-MESSAGE-TYPE-LEN:CAPS"></a><h3>STUN_MESSAGE_TYPE_LEN</h3>
+<pre class="programlisting">#define STUN_MESSAGE_TYPE_LEN 2
+</pre>
+<p>Length of the type field of a STUN message (in bytes).</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="STUN-MESSAGE-TYPE-POS:CAPS"></a><h3>STUN_MESSAGE_TYPE_POS</h3>
+<pre class="programlisting">#define STUN_MESSAGE_TYPE_POS 0
+</pre>
+<p>Offset of the type field of a STUN message (in bytes).</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="TURN-MAGIC-COOKIE:CAPS"></a><h3>TURN_MAGIC_COOKIE</h3>
+<pre class="programlisting">#define TURN_MAGIC_COOKIE 0x72c64bc6
+</pre>
+<p>Magic cookie value used to identify TURN messages.</p>
+</div>
+</div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.29</div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>StunAgent: libnice Reference Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets Vsnapshot">
+<link rel="home" href="index.html" title="libnice Reference Manual">
+<link rel="up" href="ch03.html" title="">
+<link rel="prev" href="ch03.html" title="">
+<link rel="next" href="libnice-StunMessage.html" title="StunMessage">
+<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts">
+<a href="#" class="shortcut">Top</a><span id="nav_description"> <span class="dim">|</span>
+ <a href="#libnice-StunAgent.description" class="shortcut">Description</a></span>
+</td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="ch03.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="ch03.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="libnice-StunMessage.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="refentry">
+<a name="libnice-StunAgent"></a><div class="titlepage"></div>
+<div class="refnamediv"><table width="100%"><tr>
+<td valign="top">
+<h2><span class="refentrytitle"><a name="libnice-StunAgent.top_of_page"></a>StunAgent</span></h2>
+<p>StunAgent — STUN agent for building and validating STUN messages</p>
+</td>
+<td class="gallery_image" valign="top" align="right"></td>
+</tr></table></div>
+<div class="refsect1">
+<a name="libnice-StunAgent.stability-level"></a><h2>Stability Level</h2>
+<acronym title="The intention of a Stable interface is to enable arbitrary third parties to
+develop applications to these interfaces, release them, and have confidence that
+they will run on all minor releases of the product (after the one in which the
+interface was introduced, and within the same major release). Even at a major
+release, incompatible changes are expected to be rare, and to have strong
+justifications.
+"><span class="acronym">Stable</span></acronym>, unless otherwise indicated
+</div>
+<div class="refsect1">
+<a name="libnice-StunAgent.functions"></a><h2>Functions</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="functions_return">
+<col class="functions_name">
+</colgroup>
+<tbody>
+<tr>
+<td class="function_type">
+<span class="returnvalue">bool</span>
+</td>
+<td class="function_name">
+<span class="c_punctuation">(</span><a class="link" href="libnice-StunAgent.html#StunMessageIntegrityValidate" title="StunMessageIntegrityValidate ()">*StunMessageIntegrityValidate</a><span class="c_punctuation">)</span> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<span class="c_punctuation">(</span><a class="link" href="libnice-StunAgent.html#StunDebugHandler" title="StunDebugHandler ()">*StunDebugHandler</a><span class="c_punctuation">)</span> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunAgent.html#stun-agent-init" title="stun_agent_init ()">stun_agent_init</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="libnice-StunAgent.html#StunValidationStatus" title="enum StunValidationStatus"><span class="returnvalue">StunValidationStatus</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunAgent.html#stun-agent-validate" title="stun_agent_validate ()">stun_agent_validate</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">bool</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunAgent.html#stun-agent-default-validater" title="stun_agent_default_validater ()">stun_agent_default_validater</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">bool</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunAgent.html#stun-agent-init-request" title="stun_agent_init_request ()">stun_agent_init_request</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">bool</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunAgent.html#stun-agent-init-indication" title="stun_agent_init_indication ()">stun_agent_init_indication</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">bool</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunAgent.html#stun-agent-init-response" title="stun_agent_init_response ()">stun_agent_init_response</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">bool</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunAgent.html#stun-agent-init-error" title="stun_agent_init_error ()">stun_agent_init_error</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">size_t</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunAgent.html#stun-agent-build-unknown-attributes-error" title="stun_agent_build_unknown_attributes_error ()">stun_agent_build_unknown_attributes_error</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">size_t</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunAgent.html#stun-agent-finish-message" title="stun_agent_finish_message ()">stun_agent_finish_message</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">bool</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunAgent.html#stun-agent-forget-transaction" title="stun_agent_forget_transaction ()">stun_agent_forget_transaction</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunAgent.html#stun-agent-set-software" title="stun_agent_set_software ()">stun_agent_set_software</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunAgent.html#stun-debug-enable" title="stun_debug_enable ()">stun_debug_enable</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunAgent.html#stun-debug-disable" title="stun_debug_disable ()">stun_debug_disable</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunAgent.html#stun-set-debug-handler" title="stun_set_debug_handler ()">stun_set_debug_handler</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect1">
+<a name="libnice-StunAgent.other"></a><h2>Types and Values</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="name">
+<col class="description">
+</colgroup>
+<tbody>
+<tr>
+<td class="typedef_keyword">typedef</td>
+<td class="function_name"><a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent">StunAgent</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="libnice-StunAgent.html#StunCompatibility" title="enum StunCompatibility">StunCompatibility</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="libnice-StunAgent.html#StunAgentUsageFlags" title="enum StunAgentUsageFlags">StunAgentUsageFlags</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="libnice-StunAgent.html#StunValidationStatus" title="enum StunValidationStatus">StunValidationStatus</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword"> </td>
+<td class="function_name"><a class="link" href="libnice-StunAgent.html#StunDefaultValidaterData" title="StunDefaultValidaterData">StunDefaultValidaterData</a></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect1">
+<a name="libnice-StunAgent.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include <stun/stunagent.h>
+</pre>
+</div>
+<div class="refsect1">
+<a name="libnice-StunAgent.description"></a><h2>Description</h2>
+<p>The STUN Agent allows you to create and validate STUN messages easily.
+It's main purpose is to make sure the building and validation methods used
+are compatible with the RFC you create it with. It also tracks the transaction
+ids of the requests you send, so you can validate if a STUN response you
+received should be processed by that agent or not.</p>
+</div>
+<div class="refsect1">
+<a name="libnice-StunAgent.functions_details"></a><h2>Functions</h2>
+<div class="refsect2">
+<a name="StunMessageIntegrityValidate"></a><h3>StunMessageIntegrityValidate ()</h3>
+<pre class="programlisting"><span class="returnvalue">bool</span>
+<span class="c_punctuation">(</span>*StunMessageIntegrityValidate<span class="c_punctuation">)</span> (<em class="parameter"><code><a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *message</code></em>,
+ <em class="parameter"><code><span class="type">uint8_t</span> *username</code></em>,
+ <em class="parameter"><code><span class="type">uint16_t</span> username_len</code></em>,
+ <em class="parameter"><code><span class="type">uint8_t</span> **password</code></em>,
+ <em class="parameter"><code><span class="type">size_t</span> *password_len</code></em>,
+ <em class="parameter"><code><span class="type">void</span> *user_data</code></em>);</pre>
+<p>This is the prototype for the <em class="parameter"><code>validater</code></em>
+ argument of the <a class="link" href="libnice-StunAgent.html#stun-agent-validate" title="stun_agent_validate ()"><code class="function">stun_agent_validate()</code></a>
+function.</p>
+<p> See also: <a class="link" href="libnice-StunAgent.html#stun-agent-validate" title="stun_agent_validate ()"><code class="function">stun_agent_validate()</code></a> </p>
+<div class="refsect3">
+<a name="StunMessageIntegrityValidate.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>message</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> being validated</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>username</p></td>
+<td class="parameter_description"><p>The username found in the <em class="parameter"><code>message</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>username_len</p></td>
+<td class="parameter_description"><p>The length of <em class="parameter"><code>username</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>password</p></td>
+<td class="parameter_description"><p>The password associated with that username. This argument is a
+pointer to a byte array that must be set by the validater function.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>password_len</p></td>
+<td class="parameter_description"><p>The length of <em class="parameter"><code>password</code></em>
+which must also be set by the
+validater function.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>user_data</p></td>
+<td class="parameter_description"><p>Data to give the function</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="StunMessageIntegrityValidate.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> if the authentication was successful,
+<a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> if the authentication failed</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="StunDebugHandler"></a><h3>StunDebugHandler ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+<span class="c_punctuation">(</span>*StunDebugHandler<span class="c_punctuation">)</span> (<em class="parameter"><code>const <span class="type">char</span> *format</code></em>,
+ <em class="parameter"><code><span class="type">va_list</span> ap</code></em>);</pre>
+<p>Callback for a debug message from the STUN code.</p>
+<div class="refsect3">
+<a name="StunDebugHandler.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>format</p></td>
+<td class="parameter_description"><p>printf()-style debug message format string</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>ap</p></td>
+<td class="parameter_description"><p>Parameters to substitute into message placeholders</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-agent-init"></a><h3>stun_agent_init ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+stun_agent_init (<em class="parameter"><code><a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code>const <span class="type">uint16_t</span> *known_attributes</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunAgent.html#StunCompatibility" title="enum StunCompatibility"><span class="type">StunCompatibility</span></a> compatibility</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunAgent.html#StunAgentUsageFlags" title="enum StunAgentUsageFlags"><span class="type">StunAgentUsageFlags</span></a> usage_flags</code></em>);</pre>
+<p>This function must be called to initialize an agent before it is being used.</p>
+<div class="note">
+<p>
+ The <em class="parameter"><code>known_attributes</code></em> data must exist in memory as long as the <em class="parameter"><code>agent</code></em> is used
+ </p>
+<p>
+ If the <a class="link" href="libnice-StunAgent.html#STUN-AGENT-USAGE-SHORT-TERM-CREDENTIALS:CAPS"><span class="type">STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS</span></a> and
+ <a class="link" href="libnice-StunAgent.html#STUN-AGENT-USAGE-LONG-TERM-CREDENTIALS:CAPS"><span class="type">STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS</span></a> usage flags are not set, then the
+ agent will default in using the short term credentials mechanism
+ </p>
+<p>
+ The <a class="link" href="libnice-StunAgent.html#STUN-AGENT-USAGE-USE-FINGERPRINT:CAPS"><span class="type">STUN_AGENT_USAGE_USE_FINGERPRINT</span></a> and <a class="link" href="libnice-StunAgent.html#STUN-AGENT-USAGE-ADD-SOFTWARE:CAPS"><span class="type">STUN_AGENT_USAGE_ADD_SOFTWARE</span></a>
+ usage flags are only valid if the <a class="link" href="libnice-StunAgent.html#STUN-COMPATIBILITY-RFC5389:CAPS"><span class="type">STUN_COMPATIBILITY_RFC5389</span></a> or
+ <a class="link" href="libnice-StunAgent.html#STUN-COMPATIBILITY-MSICE2:CAPS"><span class="type">STUN_COMPATIBILITY_MSICE2</span></a> <em class="parameter"><code>compatibility</code></em> is used
+ </p>
+</div>
+<div class="refsect3">
+<a name="stun-agent-init.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a> to initialize</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>known_attributes</p></td>
+<td class="parameter_description"><p>An array of <span class="type">uint16_t</span> specifying which attributes should
+be known by the agent. Any STUN message received that contains a mandatory
+attribute that is not in this array will yield a
+<a class="link" href="libnice-StunAgent.html#STUN-VALIDATION-UNKNOWN-REQUEST-ATTRIBUTE:CAPS"><span class="type">STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE</span></a> or a
+<a class="link" href="libnice-StunAgent.html#STUN-VALIDATION-UNKNOWN-ATTRIBUTE:CAPS"><span class="type">STUN_VALIDATION_UNKNOWN_ATTRIBUTE</span></a> error when calling <a class="link" href="libnice-StunAgent.html#stun-agent-validate" title="stun_agent_validate ()"><code class="function">stun_agent_validate()</code></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>compatibility</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunAgent.html#StunCompatibility" title="enum StunCompatibility"><span class="type">StunCompatibility</span></a> to use for this agent. This will affect
+how the agent builds and validates the STUN messages</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>usage_flags</p></td>
+<td class="parameter_description"><p>A bitflag using <a class="link" href="libnice-StunAgent.html#StunAgentUsageFlags" title="enum StunAgentUsageFlags"><span class="type">StunAgentUsageFlags</span></a> values to define which
+STUN usages the agent should use.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-agent-validate"></a><h3>stun_agent_validate ()</h3>
+<pre class="programlisting"><a class="link" href="libnice-StunAgent.html#StunValidationStatus" title="enum StunValidationStatus"><span class="returnvalue">StunValidationStatus</span></a>
+stun_agent_validate (<em class="parameter"><code><a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code>const <span class="type">uint8_t</span> *buffer</code></em>,
+ <em class="parameter"><code><span class="type">size_t</span> buffer_len</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunAgent.html#StunMessageIntegrityValidate" title="StunMessageIntegrityValidate ()"><span class="type">StunMessageIntegrityValidate</span></a> validater</code></em>,
+ <em class="parameter"><code><span class="type">void</span> *validater_data</code></em>);</pre>
+<p>This function is used to validate an inbound STUN message and transform its
+data buffer into a <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a>. It will take care of various validation
+algorithms to make sure that the STUN message is valid and correctly
+authenticated.</p>
+<p> See also: <a class="link" href="libnice-StunAgent.html#stun-agent-default-validater" title="stun_agent_default_validater ()"><code class="function">stun_agent_default_validater()</code></a> </p>
+<div class="refsect3">
+<a name="stun-agent-validate.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> to build</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>The data buffer of the STUN message</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buffer_len</p></td>
+<td class="parameter_description"><p>The length of <em class="parameter"><code>buffer</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>validater</p></td>
+<td class="parameter_description"><p>A <a class="link" href="libnice-StunAgent.html#StunMessageIntegrityValidate" title="StunMessageIntegrityValidate ()"><span class="type">StunMessageIntegrityValidate</span></a> function callback that will
+be called if the agent needs to validate a MESSAGE-INTEGRITY attribute. It
+will only be called if the agent finds a message that needs authentication
+and a USERNAME is present in the STUN message, but no password is known.
+The validater will not be called if the <a class="link" href="libnice-StunAgent.html#STUN-AGENT-USAGE-IGNORE-CREDENTIALS:CAPS"><span class="type">STUN_AGENT_USAGE_IGNORE_CREDENTIALS</span></a>
+usage flag is set on the agent, and it will always be called if the
+<a class="link" href="libnice-StunAgent.html#STUN-AGENT-USAGE-FORCE-VALIDATER:CAPS"><span class="type">STUN_AGENT_USAGE_FORCE_VALIDATER</span></a> usage flag is set on the agent.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>validater_data</p></td>
+<td class="parameter_description"><p>A user data to give to the <em class="parameter"><code>validater</code></em>
+callback when it gets
+called.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-agent-validate.returns"></a><h4>Returns</h4>
+<p> A <a class="link" href="libnice-StunAgent.html#StunValidationStatus" title="enum StunValidationStatus"><span class="type">StunValidationStatus</span></a></p>
+<div class="note"><p>
+if the return value is different from <a class="link" href="libnice-StunAgent.html#STUN-VALIDATION-NOT-STUN:CAPS"><span class="type">STUN_VALIDATION_NOT_STUN</span></a> or
+<a class="link" href="libnice-StunAgent.html#STUN-VALIDATION-INCOMPLETE-STUN:CAPS"><span class="type">STUN_VALIDATION_INCOMPLETE_STUN</span></a>, then the <em class="parameter"><code>msg</code></em> argument will contain a valid
+STUN message that can be used.
+This means that you can use the <em class="parameter"><code>msg</code></em> variable as the <em class="parameter"><code>request</code></em> argument to
+functions like <a class="link" href="libnice-StunAgent.html#stun-agent-init-error" title="stun_agent_init_error ()"><code class="function">stun_agent_init_error()</code></a> or
+<a class="link" href="libnice-StunAgent.html#stun-agent-build-unknown-attributes-error" title="stun_agent_build_unknown_attributes_error ()"><code class="function">stun_agent_build_unknown_attributes_error()</code></a>.
+If the return value is <a class="link" href="libnice-StunAgent.html#STUN-VALIDATION-BAD-REQUEST:CAPS"><span class="type">STUN_VALIDATION_BAD_REQUEST</span></a>,
+<a class="link" href="libnice-StunAgent.html#STUN-VALIDATION-UNAUTHORIZED:CAPS"><span class="type">STUN_VALIDATION_UNAUTHORIZED</span></a> or <a class="link" href="libnice-StunAgent.html#STUN-VALIDATION-UNAUTHORIZED-BAD-REQUEST:CAPS"><span class="type">STUN_VALIDATION_UNAUTHORIZED_BAD_REQUEST</span></a>
+then the <em class="parameter"><code>key</code></em> in the <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> will not be set, so that error responses
+will not have a MESSAGE-INTEGRITY attribute.
+</p></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-agent-default-validater"></a><h3>stun_agent_default_validater ()</h3>
+<pre class="programlisting"><span class="returnvalue">bool</span>
+stun_agent_default_validater (<em class="parameter"><code><a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *message</code></em>,
+ <em class="parameter"><code><span class="type">uint8_t</span> *username</code></em>,
+ <em class="parameter"><code><span class="type">uint16_t</span> username_len</code></em>,
+ <em class="parameter"><code><span class="type">uint8_t</span> **password</code></em>,
+ <em class="parameter"><code><span class="type">size_t</span> *password_len</code></em>,
+ <em class="parameter"><code><span class="type">void</span> *user_data</code></em>);</pre>
+<p>This is a helper function to be used with <a class="link" href="libnice-StunAgent.html#stun-agent-validate" title="stun_agent_validate ()"><code class="function">stun_agent_validate()</code></a>. If no
+complicated processing of the username needs to be done, this function can
+be used with <a class="link" href="libnice-StunAgent.html#stun-agent-validate" title="stun_agent_validate ()"><code class="function">stun_agent_validate()</code></a> to quickly and easily match the username
+of a STUN message with its password. Its <em class="parameter"><code>user_data</code></em>
+ argument must be an array
+of <a class="link" href="libnice-StunAgent.html#StunDefaultValidaterData" title="StunDefaultValidaterData"><span class="type">StunDefaultValidaterData</span></a> which will allow us to map a username to a
+password</p>
+<p> See also: <a class="link" href="libnice-StunAgent.html#stun-agent-validate" title="stun_agent_validate ()"><code class="function">stun_agent_validate()</code></a> </p>
+<div class="refsect3">
+<a name="stun-agent-default-validater.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>message</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> being validated</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>username</p></td>
+<td class="parameter_description"><p>The username found in the <em class="parameter"><code>message</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>username_len</p></td>
+<td class="parameter_description"><p>The length of <em class="parameter"><code>username</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>password</p></td>
+<td class="parameter_description"><p>The password associated with that username. This argument is a
+pointer to a byte array that must be set by the validater function.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>password_len</p></td>
+<td class="parameter_description"><p>The length of <em class="parameter"><code>password</code></em>
+which must also be set by the
+validater function.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>user_data</p></td>
+<td class="parameter_description"><p>This must be an array of <a class="link" href="libnice-StunAgent.html#StunDefaultValidaterData" title="StunDefaultValidaterData"><span class="type">StunDefaultValidaterData</span></a> structures.
+The last element in the array must have a username set to NULL</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-agent-default-validater.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> if the authentication was successful,
+<a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> if the authentication failed</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-agent-init-request"></a><h3>stun_agent_init_request ()</h3>
+<pre class="programlisting"><span class="returnvalue">bool</span>
+stun_agent_init_request (<em class="parameter"><code><a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><span class="type">uint8_t</span> *buffer</code></em>,
+ <em class="parameter"><code><span class="type">size_t</span> buffer_len</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMethod" title="enum StunMethod"><span class="type">StunMethod</span></a> m</code></em>);</pre>
+<p>Creates a new STUN message of class <a class="link" href="libnice-StunMessage.html#STUN-REQUEST:CAPS"><span class="type">STUN_REQUEST</span></a> and with the method <em class="parameter"><code>m</code></em>
+</p>
+<div class="refsect3">
+<a name="stun-agent-init-request.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> to build</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>The buffer to use in the <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buffer_len</p></td>
+<td class="parameter_description"><p>The length of the buffer</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>m</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMethod" title="enum StunMethod"><span class="type">StunMethod</span></a> of the request</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-agent-init-request.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> if the message was initialized correctly, <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> otherwise</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-agent-init-indication"></a><h3>stun_agent_init_indication ()</h3>
+<pre class="programlisting"><span class="returnvalue">bool</span>
+stun_agent_init_indication (<em class="parameter"><code><a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><span class="type">uint8_t</span> *buffer</code></em>,
+ <em class="parameter"><code><span class="type">size_t</span> buffer_len</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMethod" title="enum StunMethod"><span class="type">StunMethod</span></a> m</code></em>);</pre>
+<p>Creates a new STUN message of class <a class="link" href="libnice-StunMessage.html#STUN-INDICATION:CAPS"><span class="type">STUN_INDICATION</span></a> and with the method <em class="parameter"><code>m</code></em>
+</p>
+<div class="refsect3">
+<a name="stun-agent-init-indication.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> to build</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>The buffer to use in the <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buffer_len</p></td>
+<td class="parameter_description"><p>The length of the buffer</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>m</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMethod" title="enum StunMethod"><span class="type">StunMethod</span></a> of the indication</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-agent-init-indication.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> if the message was initialized correctly, <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> otherwise</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-agent-init-response"></a><h3>stun_agent_init_response ()</h3>
+<pre class="programlisting"><span class="returnvalue">bool</span>
+stun_agent_init_response (<em class="parameter"><code><a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><span class="type">uint8_t</span> *buffer</code></em>,
+ <em class="parameter"><code><span class="type">size_t</span> buffer_len</code></em>,
+ <em class="parameter"><code>const <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *request</code></em>);</pre>
+<p>Creates a new STUN message of class <a class="link" href="libnice-StunMessage.html#STUN-RESPONSE:CAPS"><span class="type">STUN_RESPONSE</span></a> and with the same method
+and transaction ID as the message <em class="parameter"><code>request</code></em>
+. This will also copy the pointer
+to the key that was used to authenticate the request, so you won't need to
+specify the key with <a class="link" href="libnice-StunAgent.html#stun-agent-finish-message" title="stun_agent_finish_message ()"><code class="function">stun_agent_finish_message()</code></a></p>
+<div class="refsect3">
+<a name="stun-agent-init-response.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> to build</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>The buffer to use in the <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buffer_len</p></td>
+<td class="parameter_description"><p>The length of the buffer</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>request</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> of class <a class="link" href="libnice-StunMessage.html#STUN-REQUEST:CAPS"><span class="type">STUN_REQUEST</span></a> that this response is for</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-agent-init-response.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> if the message was initialized correctly, <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> otherwise</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-agent-init-error"></a><h3>stun_agent_init_error ()</h3>
+<pre class="programlisting"><span class="returnvalue">bool</span>
+stun_agent_init_error (<em class="parameter"><code><a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><span class="type">uint8_t</span> *buffer</code></em>,
+ <em class="parameter"><code><span class="type">size_t</span> buffer_len</code></em>,
+ <em class="parameter"><code>const <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *request</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunError" title="enum StunError"><span class="type">StunError</span></a> err</code></em>);</pre>
+<p>Creates a new STUN message of class <a class="link" href="libnice-StunMessage.html#STUN-ERROR:CAPS"><span class="type">STUN_ERROR</span></a> and with the same method
+and transaction ID as the message <em class="parameter"><code>request</code></em>
+. This will also copy the pointer
+to the key that was used to authenticate the request (if authenticated),
+so you won't need to specify the key with <a class="link" href="libnice-StunAgent.html#stun-agent-finish-message" title="stun_agent_finish_message ()"><code class="function">stun_agent_finish_message()</code></a>.
+It will then add the ERROR-CODE attribute with code <em class="parameter"><code>err</code></em>
+ and the associated
+string.</p>
+<div class="refsect3">
+<a name="stun-agent-init-error.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> to build</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>The buffer to use in the <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buffer_len</p></td>
+<td class="parameter_description"><p>The length of the buffer</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>request</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> of class <a class="link" href="libnice-StunMessage.html#STUN-REQUEST:CAPS"><span class="type">STUN_REQUEST</span></a> that this error response
+is for</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>err</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunError" title="enum StunError"><span class="type">StunError</span></a> to put in the ERROR-CODE attribute of the error response</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-agent-init-error.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> if the message was initialized correctly, <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> otherwise</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-agent-build-unknown-attributes-error"></a><h3>stun_agent_build_unknown_attributes_error ()</h3>
+<pre class="programlisting"><span class="returnvalue">size_t</span>
+stun_agent_build_unknown_attributes_error
+ (<em class="parameter"><code><a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><span class="type">uint8_t</span> *buffer</code></em>,
+ <em class="parameter"><code><span class="type">size_t</span> buffer_len</code></em>,
+ <em class="parameter"><code>const <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *request</code></em>);</pre>
+<p>Creates a new STUN message of class <a class="link" href="libnice-StunMessage.html#STUN-ERROR:CAPS"><span class="type">STUN_ERROR</span></a> and with the same method
+and transaction ID as the message <em class="parameter"><code>request</code></em>
+. It will then add the ERROR-CODE
+attribute with code <a class="link" href="libnice-StunMessage.html#STUN-ERROR-UNKNOWN-ATTRIBUTE:CAPS"><span class="type">STUN_ERROR_UNKNOWN_ATTRIBUTE</span></a> and add all the unknown
+mandatory attributes from the <em class="parameter"><code>request</code></em>
+ STUN message in the
+<a class="link" href="libnice-StunMessage.html#STUN-ATTRIBUTE-UNKNOWN-ATTRIBUTES:CAPS"><span class="type">STUN_ATTRIBUTE_UNKNOWN_ATTRIBUTES</span></a> attribute, it will then finish the message
+by calling <a class="link" href="libnice-StunAgent.html#stun-agent-finish-message" title="stun_agent_finish_message ()"><code class="function">stun_agent_finish_message()</code></a></p>
+<div class="refsect3">
+<a name="stun-agent-build-unknown-attributes-error.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> to build</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>The buffer to use in the <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buffer_len</p></td>
+<td class="parameter_description"><p>The length of the buffer</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>request</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> of class <a class="link" href="libnice-StunMessage.html#STUN-REQUEST:CAPS"><span class="type">STUN_REQUEST</span></a> that this response is for</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-agent-build-unknown-attributes-error.returns"></a><h4>Returns</h4>
+<p> The size of the message built</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-agent-finish-message"></a><h3>stun_agent_finish_message ()</h3>
+<pre class="programlisting"><span class="returnvalue">size_t</span>
+stun_agent_finish_message (<em class="parameter"><code><a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code>const <span class="type">uint8_t</span> *key</code></em>,
+ <em class="parameter"><code><span class="type">size_t</span> key_len</code></em>);</pre>
+<p>This function will 'finish' a message and make it ready to be sent. It will
+add the MESSAGE-INTEGRITY and FINGERPRINT attributes if necessary. If the
+STUN message has a <a class="link" href="libnice-StunMessage.html#STUN-REQUEST:CAPS"><span class="type">STUN_REQUEST</span></a> class, it will save the transaction id of
+the message in the agent for future matching of the response.</p>
+<p>See also: <a class="link" href="libnice-StunAgent.html#stun-agent-forget-transaction" title="stun_agent_forget_transaction ()"><code class="function">stun_agent_forget_transaction()</code></a></p>
+<div class="refsect3">
+<a name="stun-agent-finish-message.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> to finish</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>key</p></td>
+<td class="parameter_description"><p>The key to use for the MESSAGE-INTEGRITY attribute</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>key_len</p></td>
+<td class="parameter_description"><p>The length of the <em class="parameter"><code>key</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-agent-finish-message.returns"></a><h4>Returns</h4>
+<p> The final size of the message built or 0 if an error occured</p>
+<div class="note">
+<p>
+The return value must always be checked. a value of 0 means the either
+the buffer's size is too small to contain the finishing attributes
+(MESSAGE-INTEGRITY, FINGERPRINT), or that there is no more free slots
+for saving the sent id in the agent's state.
+</p>
+<p>
+Everytime <a class="link" href="libnice-StunAgent.html#stun-agent-finish-message" title="stun_agent_finish_message ()"><code class="function">stun_agent_finish_message()</code></a> is called for a <a class="link" href="libnice-StunMessage.html#STUN-REQUEST:CAPS"><span class="type">STUN_REQUEST</span></a>
+message, you must make sure to call <a class="link" href="libnice-StunAgent.html#stun-agent-forget-transaction" title="stun_agent_forget_transaction ()"><code class="function">stun_agent_forget_transaction()</code></a> in
+case the response times out and is never received. This is to avoid
+filling up the <a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a>'s sent ids state preventing any further
+use of the <a class="link" href="libnice-StunAgent.html#stun-agent-finish-message" title="stun_agent_finish_message ()"><code class="function">stun_agent_finish_message()</code></a>
+</p>
+</div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-agent-forget-transaction"></a><h3>stun_agent_forget_transaction ()</h3>
+<pre class="programlisting"><span class="returnvalue">bool</span>
+stun_agent_forget_transaction (<em class="parameter"><code><a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunTransactionId" title="StunTransactionId"><span class="type">StunTransactionId</span></a> id</code></em>);</pre>
+<p>This function is used to make the <a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a> forget about a previously
+created transaction.</p>
+<p>
+This function should be called when a STUN request was previously
+created with <a class="link" href="libnice-StunAgent.html#stun-agent-finish-message" title="stun_agent_finish_message ()"><code class="function">stun_agent_finish_message()</code></a> and for which no response was ever
+received (timed out). The <a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a> keeps a list of the sent transactions
+in order to validate the responses received. If the response is never received
+this will allow the <a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a> to forget about the timed out transaction and
+free its slot for future transactions.
+</p>
+<div class="refsect3">
+<a name="stun-agent-forget-transaction.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>id</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunTransactionId" title="StunTransactionId"><span class="type">StunTransactionId</span></a> of the transaction to forget</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-agent-forget-transaction.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> if the transaction was found, <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> otherwise</p>
+</div>
+<p class="since">Since: <a class="link" href="ix04.html#api-index-0.0.6">0.0.6</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-agent-set-software"></a><h3>stun_agent_set_software ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+stun_agent_set_software (<em class="parameter"><code><a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code>const <span class="type">char</span> *software</code></em>);</pre>
+<p>This function will set the value of the SOFTWARE attribute to be added to
+STUN requests, responses and error responses.</p>
+<p>
+Calling this function will automatically enable the addition of the SOFTWARE
+attribute for RFC5389 and MSICE2 compatibility modes.
+
+</p>
+<div class="note">
+<p>
+ The <em class="parameter"><code>software</code></em> argument must be in UTF-8 encoding and only the first
+ 128 characters will be sent.
+ </p>
+<p>
+ The value of the <em class="parameter"><code>software</code></em> argument must stay valid throughout the life of
+ the StunAgent's life. Do not free its content.
+ </p>
+</div>
+<div class="refsect3">
+<a name="stun-agent-set-software.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>software</p></td>
+<td class="parameter_description"><p>The value of the SOFTWARE attribute to add.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="ix07.html#api-index-0.0.10">0.0.10</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-debug-enable"></a><h3>stun_debug_enable ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+stun_debug_enable (<em class="parameter"><code><span class="type">void</span></code></em>);</pre>
+<p>Enable debug messages to stderr</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-debug-disable"></a><h3>stun_debug_disable ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+stun_debug_disable (<em class="parameter"><code><span class="type">void</span></code></em>);</pre>
+<p>Disable debug messages to stderr</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-set-debug-handler"></a><h3>stun_set_debug_handler ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+stun_set_debug_handler (<em class="parameter"><code><a class="link" href="libnice-StunAgent.html#StunDebugHandler" title="StunDebugHandler ()"><span class="type">StunDebugHandler</span></a> handler</code></em>);</pre>
+<p>Set a callback function to be invoked for each debug message from the STUN
+code. The callback will only be invoked if STUN debugging is enabled using
+<a class="link" href="libnice-StunAgent.html#stun-debug-enable" title="stun_debug_enable ()"><code class="function">stun_debug_enable()</code></a>.</p>
+<p>The default callback prints the formatted debug message to stderr.</p>
+<div class="refsect3">
+<a name="stun-set-debug-handler.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>handler</p></td>
+<td class="parameter_description"><p>Handler for STUN debug messages, or <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS"><code class="literal">NULL</code></a> to use the
+default. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="NULL may be passed as the value in, out, in-out; or as a return value."><span class="acronym">nullable</span></acronym>]</span></td>
+</tr></tbody>
+</table></div>
+</div>
+</div>
+</div>
+<div class="refsect1">
+<a name="libnice-StunAgent.other_details"></a><h2>Types and Values</h2>
+<div class="refsect2">
+<a name="StunAgent"></a><h3>StunAgent</h3>
+<pre class="programlisting">typedef struct stun_agent_t StunAgent;
+</pre>
+<p>An opaque structure representing the STUN agent.</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="StunCompatibility"></a><h3>enum StunCompatibility</h3>
+<p>Enum that specifies the STUN compatibility mode of the <a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a></p>
+<div class="warning">
+<em class="parameter"><code>STUN_COMPATIBILITY_WLM2009</code></em> is deprecated and should not be used
+in newly-written code. It is kept for compatibility reasons and represents
+the same compatibility as <em class="parameter"><code>STUN_COMPATIBILITY_MSICE2</code></em>.</div>
+<div class="refsect3">
+<a name="StunCompatibility.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-COMPATIBILITY-RFC3489:CAPS"></a>STUN_COMPATIBILITY_RFC3489</p></td>
+<td class="enum_member_description">
+<p>Use the STUN specifications compatible with
+RFC 3489</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-COMPATIBILITY-RFC5389:CAPS"></a>STUN_COMPATIBILITY_RFC5389</p></td>
+<td class="enum_member_description">
+<p>Use the STUN specifications compatible with
+RFC 5389</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-COMPATIBILITY-MSICE2:CAPS"></a>STUN_COMPATIBILITY_MSICE2</p></td>
+<td class="enum_member_description">
+<p>Use the STUN specifications compatible with
+[MS-ICE2] (a mix between RFC3489 and RFC5389)</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-COMPATIBILITY-OC2007:CAPS"></a>STUN_COMPATIBILITY_OC2007</p></td>
+<td class="enum_member_description">
+<p>Use the STUN specifications compatible with
+Microsoft Office Communicator 2007 (basically RFC3489 with swapped
+REALM and NONCE attribute hex IDs, attributes are not aligned)</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-COMPATIBILITY-WLM2009:CAPS"></a>STUN_COMPATIBILITY_WLM2009</p></td>
+<td class="enum_member_description">
+<p>An alias for <em class="parameter"><code>STUN_COMPATIBILITY_MSICE2</code></em>
+</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-COMPATIBILITY-LAST:CAPS"></a>STUN_COMPATIBILITY_LAST</p></td>
+<td class="enum_member_description">
+<p>Dummy last compatibility mode</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="StunAgentUsageFlags"></a><h3>enum StunAgentUsageFlags</h3>
+<p>This enum defines a bitflag usages for a <a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a> and they will define how
+the agent should behave, independently of the compatibility mode it uses.</p>
+<p> See also: <a class="link" href="libnice-StunAgent.html#stun-agent-init" title="stun_agent_init ()"><code class="function">stun_agent_init()</code></a> </p>
+<p> See also: <a class="link" href="libnice-StunAgent.html#stun-agent-validate" title="stun_agent_validate ()"><code class="function">stun_agent_validate()</code></a> </p>
+<div class="refsect3">
+<a name="StunAgentUsageFlags.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-AGENT-USAGE-SHORT-TERM-CREDENTIALS:CAPS"></a>STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS</p></td>
+<td class="enum_member_description">
+<p>The agent should be using the short
+term credentials mechanism for authenticating STUN messages</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-AGENT-USAGE-LONG-TERM-CREDENTIALS:CAPS"></a>STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS</p></td>
+<td class="enum_member_description">
+<p>The agent should be using the long
+term credentials mechanism for authenticating STUN messages</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-AGENT-USAGE-USE-FINGERPRINT:CAPS"></a>STUN_AGENT_USAGE_USE_FINGERPRINT</p></td>
+<td class="enum_member_description">
+<p>The agent should add the FINGERPRINT
+attribute to the STUN messages it creates.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-AGENT-USAGE-ADD-SOFTWARE:CAPS"></a>STUN_AGENT_USAGE_ADD_SOFTWARE</p></td>
+<td class="enum_member_description">
+<p>The agent should add the SOFTWARE attribute
+to the STUN messages it creates. Calling <a class="link" href="NiceAgent.html#nice-agent-set-software" title="nice_agent_set_software ()"><code class="function">nice_agent_set_software()</code></a> will have
+the same effect as enabling this Usage. STUN Indications do not have the
+SOFTWARE attributes added to them though. The SOFTWARE attribute is only
+added for the RFC5389 and MSICE2 compatibility modes.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-AGENT-USAGE-IGNORE-CREDENTIALS:CAPS"></a>STUN_AGENT_USAGE_IGNORE_CREDENTIALS</p></td>
+<td class="enum_member_description">
+<p>The agent should ignore any credentials
+in the STUN messages it receives (the MESSAGE-INTEGRITY attribute
+will never be validated by <a class="link" href="libnice-StunAgent.html#stun-agent-validate" title="stun_agent_validate ()"><code class="function">stun_agent_validate()</code></a>)</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-AGENT-USAGE-NO-INDICATION-AUTH:CAPS"></a>STUN_AGENT_USAGE_NO_INDICATION_AUTH</p></td>
+<td class="enum_member_description">
+<p>The agent should ignore credentials
+in the STUN messages it receives if the <a class="link" href="libnice-StunMessage.html#StunClass" title="enum StunClass"><span class="type">StunClass</span></a> of the message is
+<a class="link" href="libnice-StunMessage.html#STUN-INDICATION:CAPS"><span class="type">STUN_INDICATION</span></a> (some implementation require <a class="link" href="libnice-StunMessage.html#STUN-INDICATION:CAPS"><span class="type">STUN_INDICATION</span></a> messages to
+be authenticated, while others never add a MESSAGE-INTEGRITY attribute to a
+<a class="link" href="libnice-StunMessage.html#STUN-INDICATION:CAPS"><span class="type">STUN_INDICATION</span></a> message)</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-AGENT-USAGE-FORCE-VALIDATER:CAPS"></a>STUN_AGENT_USAGE_FORCE_VALIDATER</p></td>
+<td class="enum_member_description">
+<p>The agent should always try to validate
+the password of a STUN message, even if it already knows what the password
+should be (a response to a previously created request). This means that the
+<a class="link" href="libnice-StunAgent.html#StunMessageIntegrityValidate" title="StunMessageIntegrityValidate ()"><span class="type">StunMessageIntegrityValidate</span></a> callback will always be called when there is
+a MESSAGE-INTEGRITY attribute.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-AGENT-USAGE-NO-ALIGNED-ATTRIBUTES:CAPS"></a>STUN_AGENT_USAGE_NO_ALIGNED_ATTRIBUTES</p></td>
+<td class="enum_member_description">
+<p>The agent should not assume STUN
+attributes are aligned on 32-bit boundaries when parsing messages and also
+do not add padding when creating messages.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="StunValidationStatus"></a><h3>enum StunValidationStatus</h3>
+<p>This enum is used as the return value of <a class="link" href="libnice-StunAgent.html#stun-agent-validate" title="stun_agent_validate ()"><code class="function">stun_agent_validate()</code></a> and represents
+the status result of the validation of a STUN message.</p>
+<div class="refsect3">
+<a name="StunValidationStatus.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-VALIDATION-SUCCESS:CAPS"></a>STUN_VALIDATION_SUCCESS</p></td>
+<td class="enum_member_description">
+<p>The message is validated</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-VALIDATION-NOT-STUN:CAPS"></a>STUN_VALIDATION_NOT_STUN</p></td>
+<td class="enum_member_description">
+<p>This is not a valid STUN message</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-VALIDATION-INCOMPLETE-STUN:CAPS"></a>STUN_VALIDATION_INCOMPLETE_STUN</p></td>
+<td class="enum_member_description">
+<p>The message seems to be valid but incomplete</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-VALIDATION-BAD-REQUEST:CAPS"></a>STUN_VALIDATION_BAD_REQUEST</p></td>
+<td class="enum_member_description">
+<p>The message does not have the cookie or the
+fingerprint while the agent needs it with its usage</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-VALIDATION-UNAUTHORIZED-BAD-REQUEST:CAPS"></a>STUN_VALIDATION_UNAUTHORIZED_BAD_REQUEST</p></td>
+<td class="enum_member_description">
+<p>The message is valid but
+unauthorized with no username and message-integrity attributes.
+A BAD_REQUEST error must be generated</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-VALIDATION-UNAUTHORIZED:CAPS"></a>STUN_VALIDATION_UNAUTHORIZED</p></td>
+<td class="enum_member_description">
+<p>The message is valid but unauthorized as
+the username/password do not match.
+An UNAUTHORIZED error must be generated</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-VALIDATION-UNMATCHED-RESPONSE:CAPS"></a>STUN_VALIDATION_UNMATCHED_RESPONSE</p></td>
+<td class="enum_member_description">
+<p>The message is valid but this is a
+response/error that doesn't match a previously sent request</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-VALIDATION-UNKNOWN-REQUEST-ATTRIBUTE:CAPS"></a>STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE</p></td>
+<td class="enum_member_description">
+<p>The message is valid but
+contains one or more unknown comprehension attributes.
+<a class="link" href="libnice-StunAgent.html#stun-agent-build-unknown-attributes-error" title="stun_agent_build_unknown_attributes_error ()"><code class="function">stun_agent_build_unknown_attributes_error()</code></a> should be called</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-VALIDATION-UNKNOWN-ATTRIBUTE:CAPS"></a>STUN_VALIDATION_UNKNOWN_ATTRIBUTE</p></td>
+<td class="enum_member_description">
+<p>The message is valid but contains one
+or more unknown comprehension attributes. This is a response, or error,
+or indication message and no error response should be sent</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="StunDefaultValidaterData"></a><h3>StunDefaultValidaterData</h3>
+<pre class="programlisting">typedef struct {
+ uint8_t *username;
+ size_t username_len;
+ uint8_t *password;
+ size_t password_len;
+} StunDefaultValidaterData;
+</pre>
+<p>This structure is used as an element of the user_data to the
+<a class="link" href="libnice-StunAgent.html#stun-agent-default-validater" title="stun_agent_default_validater ()"><code class="function">stun_agent_default_validater()</code></a> function for authenticating a STUN
+message during validationg.</p>
+<p> See also: <a class="link" href="libnice-StunAgent.html#stun-agent-default-validater" title="stun_agent_default_validater ()"><code class="function">stun_agent_default_validater()</code></a> </p>
+<div class="refsect3">
+<a name="StunDefaultValidaterData.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="struct_members_name">
+<col class="struct_members_description">
+<col width="200px" class="struct_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="struct_member_name"><p><span class="type">uint8_t</span> *<em class="structfield"><code><a name="StunDefaultValidaterData.username"></a>username</code></em>;</p></td>
+<td class="struct_member_description"><p>The username</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><span class="type">size_t</span> <em class="structfield"><code><a name="StunDefaultValidaterData.username-len"></a>username_len</code></em>;</p></td>
+<td class="struct_member_description"><p>The length of the <em class="parameter"><code>username</code></em>
+</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><span class="type">uint8_t</span> *<em class="structfield"><code><a name="StunDefaultValidaterData.password"></a>password</code></em>;</p></td>
+<td class="struct_member_description"><p>The password</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><span class="type">size_t</span> <em class="structfield"><code><a name="StunDefaultValidaterData.password-len"></a>password_len</code></em>;</p></td>
+<td class="struct_member_description"><p>The length of the <em class="parameter"><code>password</code></em>
+</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+</div>
+<div class="refsect1">
+<a name="libnice-StunAgent.see-also"></a><h2>See Also</h2>
+<p><a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p>
+</div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.29</div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>StunMessage: libnice Reference Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets Vsnapshot">
+<link rel="home" href="index.html" title="libnice Reference Manual">
+<link rel="up" href="ch03.html" title="">
+<link rel="prev" href="libnice-StunAgent.html" title="StunAgent">
+<link rel="next" href="libnice-STUN-Constants.html" title="STUN Constants">
+<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts">
+<a href="#" class="shortcut">Top</a><span id="nav_description"> <span class="dim">|</span>
+ <a href="#libnice-StunMessage.description" class="shortcut">Description</a></span>
+</td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="ch03.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="libnice-StunAgent.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="libnice-STUN-Constants.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="refentry">
+<a name="libnice-StunMessage"></a><div class="titlepage"></div>
+<div class="refnamediv"><table width="100%"><tr>
+<td valign="top">
+<h2><span class="refentrytitle"><a name="libnice-StunMessage.top_of_page"></a>StunMessage</span></h2>
+<p>StunMessage — STUN messages parsing and formatting functions</p>
+</td>
+<td class="gallery_image" valign="top" align="right"></td>
+</tr></table></div>
+<div class="refsect1">
+<a name="libnice-StunMessage.stability-level"></a><h2>Stability Level</h2>
+<acronym title="The intention of a Stable interface is to enable arbitrary third parties to
+develop applications to these interfaces, release them, and have confidence that
+they will run on all minor releases of the product (after the one in which the
+interface was introduced, and within the same major release). Even at a major
+release, incompatible changes are expected to be rare, and to have strong
+justifications.
+"><span class="acronym">Stable</span></acronym>, unless otherwise indicated
+</div>
+<div class="refsect1">
+<a name="libnice-StunMessage.functions"></a><h2>Functions</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="functions_return">
+<col class="functions_name">
+</colgroup>
+<tbody>
+<tr>
+<td class="function_type">
+<span class="returnvalue">bool</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunMessage.html#stun-message-init" title="stun_message_init ()">stun_message_init</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">uint16_t</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunMessage.html#stun-message-length" title="stun_message_length ()">stun_message_length</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">const <span class="returnvalue">void</span> *
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunMessage.html#stun-message-find" title="stun_message_find ()">stun_message_find</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="returnvalue">StunMessageReturn</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunMessage.html#stun-message-find-flag" title="stun_message_find_flag ()">stun_message_find_flag</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="returnvalue">StunMessageReturn</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunMessage.html#stun-message-find32" title="stun_message_find32 ()">stun_message_find32</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="returnvalue">StunMessageReturn</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunMessage.html#stun-message-find64" title="stun_message_find64 ()">stun_message_find64</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="returnvalue">StunMessageReturn</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunMessage.html#stun-message-find-string" title="stun_message_find_string ()">stun_message_find_string</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="returnvalue">StunMessageReturn</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunMessage.html#stun-message-find-addr" title="stun_message_find_addr ()">stun_message_find_addr</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="returnvalue">StunMessageReturn</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunMessage.html#stun-message-find-xor-addr" title="stun_message_find_xor_addr ()">stun_message_find_xor_addr</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="returnvalue">StunMessageReturn</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunMessage.html#stun-message-find-xor-addr-full" title="stun_message_find_xor_addr_full ()">stun_message_find_xor_addr_full</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="returnvalue">StunMessageReturn</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunMessage.html#stun-message-find-error" title="stun_message_find_error ()">stun_message_find_error</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span> *
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunMessage.html#stun-message-append" title="stun_message_append ()">stun_message_append</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="returnvalue">StunMessageReturn</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunMessage.html#stun-message-append-bytes" title="stun_message_append_bytes ()">stun_message_append_bytes</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="returnvalue">StunMessageReturn</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunMessage.html#stun-message-append-flag" title="stun_message_append_flag ()">stun_message_append_flag</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="returnvalue">StunMessageReturn</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunMessage.html#stun-message-append32" title="stun_message_append32 ()">stun_message_append32</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="returnvalue">StunMessageReturn</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunMessage.html#stun-message-append64" title="stun_message_append64 ()">stun_message_append64</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="returnvalue">StunMessageReturn</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunMessage.html#stun-message-append-string" title="stun_message_append_string ()">stun_message_append_string</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="returnvalue">StunMessageReturn</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunMessage.html#stun-message-append-addr" title="stun_message_append_addr ()">stun_message_append_addr</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="returnvalue">StunMessageReturn</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunMessage.html#stun-message-append-xor-addr" title="stun_message_append_xor_addr ()">stun_message_append_xor_addr</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="returnvalue">StunMessageReturn</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunMessage.html#stun-message-append-xor-addr-full" title="stun_message_append_xor_addr_full ()">stun_message_append_xor_addr_full</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="returnvalue">StunMessageReturn</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunMessage.html#stun-message-append-error" title="stun_message_append_error ()">stun_message_append_error</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">int</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunMessage.html#stun-message-validate-buffer-length" title="stun_message_validate_buffer_length ()">stun_message_validate_buffer_length</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">ssize_t</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunMessage.html#stun-message-validate-buffer-length-fast" title="stun_message_validate_buffer_length_fast ()">stun_message_validate_buffer_length_fast</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunMessage.html#stun-message-id" title="stun_message_id ()">stun_message_id</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="libnice-StunMessage.html#StunClass" title="enum StunClass"><span class="returnvalue">StunClass</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunMessage.html#stun-message-get-class" title="stun_message_get_class ()">stun_message_get_class</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="libnice-StunMessage.html#StunMethod" title="enum StunMethod"><span class="returnvalue">StunMethod</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunMessage.html#stun-message-get-method" title="stun_message_get_method ()">stun_message_get_method</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">bool</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunMessage.html#stun-message-has-attribute" title="stun_message_has_attribute ()">stun_message_has_attribute</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">bool</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunMessage.html#stun-message-has-cookie" title="stun_message_has_cookie ()">stun_message_has_cookie</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">bool</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunMessage.html#stun-optional" title="stun_optional ()">stun_optional</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">const <span class="returnvalue">char</span> *
+</td>
+<td class="function_name">
+<a class="link" href="libnice-StunMessage.html#stun-strerror" title="stun_strerror ()">stun_strerror</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect1">
+<a name="libnice-StunMessage.other"></a><h2>Types and Values</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="name">
+<col class="description">
+</colgroup>
+<tbody>
+<tr>
+<td class="datatype_keyword">struct</td>
+<td class="function_name"><a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage">StunMessage</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="libnice-StunMessage.html#StunClass" title="enum StunClass">StunClass</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="libnice-StunMessage.html#StunMethod" title="enum StunMethod">StunMethod</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute">StunAttribute</a></td>
+</tr>
+<tr>
+<td class="typedef_keyword">typedef</td>
+<td class="function_name"><a class="link" href="libnice-StunMessage.html#StunTransactionId" title="StunTransactionId">StunTransactionId</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="libnice-StunMessage.html#StunError" title="enum StunError">StunError</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn">StunMessageReturn</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="libnice-StunMessage.html#STUN-MESSAGE-BUFFER-INCOMPLETE:CAPS" title="STUN_MESSAGE_BUFFER_INCOMPLETE">STUN_MESSAGE_BUFFER_INCOMPLETE</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="libnice-StunMessage.html#STUN-MESSAGE-BUFFER-INVALID:CAPS" title="STUN_MESSAGE_BUFFER_INVALID">STUN_MESSAGE_BUFFER_INVALID</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword"> </td>
+<td class="function_name"><a class="link" href="libnice-StunMessage.html#StunInputVector" title="StunInputVector">StunInputVector</a></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect1">
+<a name="libnice-StunMessage.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include <stun/stunmessage.h>
+</pre>
+</div>
+<div class="refsect1">
+<a name="libnice-StunMessage.description"></a><h2>Description</h2>
+<p>The STUN Messages API allows you to create STUN messages easily as well as to
+parse existing messages.</p>
+</div>
+<div class="refsect1">
+<a name="libnice-StunMessage.functions_details"></a><h2>Functions</h2>
+<div class="refsect2">
+<a name="stun-message-init"></a><h3>stun_message_init ()</h3>
+<pre class="programlisting"><span class="returnvalue">bool</span>
+stun_message_init (<em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunClass" title="enum StunClass"><span class="type">StunClass</span></a> c</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMethod" title="enum StunMethod"><span class="type">StunMethod</span></a> m</code></em>,
+ <em class="parameter"><code>const <a class="link" href="libnice-StunMessage.html#StunTransactionId" title="StunTransactionId"><span class="type">StunTransactionId</span></a> id</code></em>);</pre>
+<p>Initializes a STUN message buffer, with no attributes.</p>
+<div class="refsect3">
+<a name="stun-message-init.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> to initialize</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>c</p></td>
+<td class="parameter_description"><p>STUN message class (host byte order)</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>m</p></td>
+<td class="parameter_description"><p>STUN message method (host byte order)</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>id</p></td>
+<td class="parameter_description"><p>16-bytes transaction ID</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-message-init.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> if the initialization was successful</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-message-length"></a><h3>stun_message_length ()</h3>
+<pre class="programlisting"><span class="returnvalue">uint16_t</span>
+stun_message_length (<em class="parameter"><code>const <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>);</pre>
+<p>Get the length of the message (including the header)</p>
+<div class="refsect3">
+<a name="stun-message-length.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-message-length.returns"></a><h4>Returns</h4>
+<p> The length of the message</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-message-find"></a><h3>stun_message_find ()</h3>
+<pre class="programlisting">const <span class="returnvalue">void</span> *
+stun_message_find (<em class="parameter"><code>const <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute"><span class="type">StunAttribute</span></a> type</code></em>,
+ <em class="parameter"><code><span class="type">uint16_t</span> *palen</code></em>);</pre>
+<p>Finds an attribute in a STUN message and fetches its content</p>
+<div class="refsect3">
+<a name="stun-message-find.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>type</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute"><span class="type">StunAttribute</span></a> to find</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>palen</p></td>
+<td class="parameter_description"><p>A pointer to store the length of the attribute</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-message-find.returns"></a><h4>Returns</h4>
+<p> A pointer to the start of the attribute payload if found,
+otherwise NULL.</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-message-find-flag"></a><h3>stun_message_find_flag ()</h3>
+<pre class="programlisting"><a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="returnvalue">StunMessageReturn</span></a>
+stun_message_find_flag (<em class="parameter"><code>const <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute"><span class="type">StunAttribute</span></a> type</code></em>);</pre>
+<p>Looks for a flag attribute within a valid STUN message.</p>
+<div class="refsect3">
+<a name="stun-message-find-flag.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>type</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute"><span class="type">StunAttribute</span></a> to find</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-message-find-flag.returns"></a><h4>Returns</h4>
+<p> A <a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="type">StunMessageReturn</span></a> value.
+<a class="link" href="libnice-StunMessage.html#STUN-MESSAGE-RETURN-INVALID:CAPS"><code class="literal">STUN_MESSAGE_RETURN_INVALID</code></a> is returned if the attribute's size is not zero.</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-message-find32"></a><h3>stun_message_find32 ()</h3>
+<pre class="programlisting"><a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="returnvalue">StunMessageReturn</span></a>
+stun_message_find32 (<em class="parameter"><code>const <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute"><span class="type">StunAttribute</span></a> type</code></em>,
+ <em class="parameter"><code><span class="type">uint32_t</span> *pval</code></em>);</pre>
+<p>Extracts a 32-bits attribute from a STUN message.</p>
+<div class="refsect3">
+<a name="stun-message-find32.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>type</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute"><span class="type">StunAttribute</span></a> to find</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>pval</p></td>
+<td class="parameter_description"><p>A pointer where to store the value (host byte order)</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-message-find32.returns"></a><h4>Returns</h4>
+<p> A <a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="type">StunMessageReturn</span></a> value.
+<a class="link" href="libnice-StunMessage.html#STUN-MESSAGE-RETURN-INVALID:CAPS"><code class="literal">STUN_MESSAGE_RETURN_INVALID</code></a> is returned if the attribute's size is not
+4 bytes.</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-message-find64"></a><h3>stun_message_find64 ()</h3>
+<pre class="programlisting"><a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="returnvalue">StunMessageReturn</span></a>
+stun_message_find64 (<em class="parameter"><code>const <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute"><span class="type">StunAttribute</span></a> type</code></em>,
+ <em class="parameter"><code><span class="type">uint64_t</span> *pval</code></em>);</pre>
+<p>Extracts a 64-bits attribute from a STUN message.</p>
+<div class="refsect3">
+<a name="stun-message-find64.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>type</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute"><span class="type">StunAttribute</span></a> to find</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>pval</p></td>
+<td class="parameter_description"><p>A pointer where to store the value (host byte order)</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-message-find64.returns"></a><h4>Returns</h4>
+<p> A <a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="type">StunMessageReturn</span></a> value.
+<a class="link" href="libnice-StunMessage.html#STUN-MESSAGE-RETURN-INVALID:CAPS"><code class="literal">STUN_MESSAGE_RETURN_INVALID</code></a> is returned if the attribute's size is not
+8 bytes.</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-message-find-string"></a><h3>stun_message_find_string ()</h3>
+<pre class="programlisting"><a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="returnvalue">StunMessageReturn</span></a>
+stun_message_find_string (<em class="parameter"><code>const <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute"><span class="type">StunAttribute</span></a> type</code></em>,
+ <em class="parameter"><code><span class="type">char</span> *buf</code></em>,
+ <em class="parameter"><code><span class="type">size_t</span> buflen</code></em>);</pre>
+<p>Extracts an UTF-8 string from a valid STUN message.</p>
+<div class="refsect3">
+<a name="stun-message-find-string.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>type</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute"><span class="type">StunAttribute</span></a> to find</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buf</p></td>
+<td class="parameter_description"><p>A pointer where to store the data</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buflen</p></td>
+<td class="parameter_description"><p>The length of the buffer</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-message-find-string.returns"></a><h4>Returns</h4>
+<p> A <a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="type">StunMessageReturn</span></a> value.
+<a class="link" href="libnice-StunMessage.html#STUN-MESSAGE-RETURN-INVALID:CAPS"><code class="literal">STUN_MESSAGE_RETURN_INVALID</code></a> is returned if the attribute is improperly
+encoded
+<a class="link" href="libnice-StunMessage.html#STUN-MESSAGE-RETURN-NOT-ENOUGH-SPACE:CAPS"><code class="literal">STUN_MESSAGE_RETURN_NOT_ENOUGH_SPACE</code></a> is return if the buffer size is too
+small to hold the string</p>
+<div class="note"><p>
+The string will be nul-terminated.
+</p></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-message-find-addr"></a><h3>stun_message_find_addr ()</h3>
+<pre class="programlisting"><a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="returnvalue">StunMessageReturn</span></a>
+stun_message_find_addr (<em class="parameter"><code>const <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute"><span class="type">StunAttribute</span></a> type</code></em>,
+ <em class="parameter"><code><span class="type">struct sockaddr_storage</span> *addr</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/camel/camel-camel-net-utils.html#socklen-t"><span class="type">socklen_t</span></a> *addrlen</code></em>);</pre>
+<p>Extracts a network address attribute from a STUN message.</p>
+<div class="refsect3">
+<a name="stun-message-find-addr.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>type</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute"><span class="type">StunAttribute</span></a> to find</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>addr</p></td>
+<td class="parameter_description"><p>The <a href="/usr/share/gtk-doc/html/camel/camel-camel-net-utils.html#sockaddr"><span class="type">sockaddr</span></a> to be filled</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>addrlen</p></td>
+<td class="parameter_description"><p>The size of the <em class="parameter"><code>addr</code></em>
+variable. Must be set to the size of the
+<em class="parameter"><code>addr</code></em>
+socket address and will be set to the size of the extracted socket
+address.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-message-find-addr.returns"></a><h4>Returns</h4>
+<p> A <a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="type">StunMessageReturn</span></a> value.
+<a class="link" href="libnice-StunMessage.html#STUN-MESSAGE-RETURN-INVALID:CAPS"><code class="literal">STUN_MESSAGE_RETURN_INVALID</code></a> is returned if the attribute payload size is
+wrong or if the <em class="parameter"><code>addrlen</code></em>
+is too small
+<a class="link" href="libnice-StunMessage.html#STUN-MESSAGE-RETURN-UNSUPPORTED-ADDRESS:CAPS"><code class="literal">STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS</code></a> if the address family is unknown.</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-message-find-xor-addr"></a><h3>stun_message_find_xor_addr ()</h3>
+<pre class="programlisting"><a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="returnvalue">StunMessageReturn</span></a>
+stun_message_find_xor_addr (<em class="parameter"><code>const <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute"><span class="type">StunAttribute</span></a> type</code></em>,
+ <em class="parameter"><code><span class="type">struct sockaddr_storage</span> *addr</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/camel/camel-camel-net-utils.html#socklen-t"><span class="type">socklen_t</span></a> *addrlen</code></em>);</pre>
+<p>Extracts an obfuscated network address attribute from a STUN message.</p>
+<div class="refsect3">
+<a name="stun-message-find-xor-addr.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>type</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute"><span class="type">StunAttribute</span></a> to find</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>addr</p></td>
+<td class="parameter_description"><p>The <a href="/usr/share/gtk-doc/html/camel/camel-camel-net-utils.html#sockaddr"><span class="type">sockaddr</span></a> to be filled</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>addrlen</p></td>
+<td class="parameter_description"><p>The size of the <em class="parameter"><code>addr</code></em>
+variable. Must be set to the size of the
+<em class="parameter"><code>addr</code></em>
+socket address and will be set to the size of the
+extracted socket address.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-message-find-xor-addr.returns"></a><h4>Returns</h4>
+<p> A <a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="type">StunMessageReturn</span></a> value.
+<a class="link" href="libnice-StunMessage.html#STUN-MESSAGE-RETURN-INVALID:CAPS"><code class="literal">STUN_MESSAGE_RETURN_INVALID</code></a> is returned if the attribute payload size is
+wrong or if the <em class="parameter"><code>addrlen</code></em>
+is too small
+<a class="link" href="libnice-StunMessage.html#STUN-MESSAGE-RETURN-UNSUPPORTED-ADDRESS:CAPS"><code class="literal">STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS</code></a> if the address family is unknown.</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-message-find-xor-addr-full"></a><h3>stun_message_find_xor_addr_full ()</h3>
+<pre class="programlisting"><a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="returnvalue">StunMessageReturn</span></a>
+stun_message_find_xor_addr_full (<em class="parameter"><code>const <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute"><span class="type">StunAttribute</span></a> type</code></em>,
+ <em class="parameter"><code><span class="type">struct sockaddr_storage</span> *addr</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/camel/camel-camel-net-utils.html#socklen-t"><span class="type">socklen_t</span></a> *addrlen</code></em>,
+ <em class="parameter"><code><span class="type">uint32_t</span> magic_cookie</code></em>);</pre>
+<p>Extracts an obfuscated network address attribute from a STUN message.</p>
+<div class="refsect3">
+<a name="stun-message-find-xor-addr-full.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>type</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute"><span class="type">StunAttribute</span></a> to find</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>addr</p></td>
+<td class="parameter_description"><p>The <a href="/usr/share/gtk-doc/html/camel/camel-camel-net-utils.html#sockaddr"><span class="type">sockaddr</span></a> to be filled</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>addrlen</p></td>
+<td class="parameter_description"><p>The size of the <em class="parameter"><code>addr</code></em>
+variable. Must be set to the size of the
+<em class="parameter"><code>addr</code></em>
+socket address and will be set to the size of the
+extracted socket address.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>magic_cookie</p></td>
+<td class="parameter_description"><p>The magic cookie to use to XOR the address.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-message-find-xor-addr-full.returns"></a><h4>Returns</h4>
+<p> A <a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="type">StunMessageReturn</span></a> value.
+<a class="link" href="libnice-StunMessage.html#STUN-MESSAGE-RETURN-INVALID:CAPS"><code class="literal">STUN_MESSAGE_RETURN_INVALID</code></a> is returned if the attribute payload size is
+wrong or if the <em class="parameter"><code>addrlen</code></em>
+is too small
+<a class="link" href="libnice-StunMessage.html#STUN-MESSAGE-RETURN-UNSUPPORTED-ADDRESS:CAPS"><code class="literal">STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS</code></a> if the address family is unknown.</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-message-find-error"></a><h3>stun_message_find_error ()</h3>
+<pre class="programlisting"><a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="returnvalue">StunMessageReturn</span></a>
+stun_message_find_error (<em class="parameter"><code>const <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><span class="type">int</span> *code</code></em>);</pre>
+<p>Extract the error response code from a STUN message</p>
+<div class="refsect3">
+<a name="stun-message-find-error.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>code</p></td>
+<td class="parameter_description"><p>A pointer where to store the value</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-message-find-error.returns"></a><h4>Returns</h4>
+<p> A <a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="type">StunMessageReturn</span></a> value.
+<a class="link" href="libnice-StunMessage.html#STUN-MESSAGE-RETURN-INVALID:CAPS"><code class="literal">STUN_MESSAGE_RETURN_INVALID</code></a> is returned if the value is invalid</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-message-append"></a><h3>stun_message_append ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span> *
+stun_message_append (<em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute"><span class="type">StunAttribute</span></a> type</code></em>,
+ <em class="parameter"><code><span class="type">size_t</span> length</code></em>);</pre>
+<p>Reserves room for appending an attribute to an unfinished STUN message.</p>
+<div class="refsect3">
+<a name="stun-message-append.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>type</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute"><span class="type">StunAttribute</span></a> to append</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>length</p></td>
+<td class="parameter_description"><p>The length of the attribute</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-message-append.returns"></a><h4>Returns</h4>
+<p> A pointer to an unitialized buffer of <em class="parameter"><code>length</code></em>
+bytes to
+where the attribute payload must be written, or NULL if there is not
+enough room in the STUN message buffer.</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-message-append-bytes"></a><h3>stun_message_append_bytes ()</h3>
+<pre class="programlisting"><a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="returnvalue">StunMessageReturn</span></a>
+stun_message_append_bytes (<em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute"><span class="type">StunAttribute</span></a> type</code></em>,
+ <em class="parameter"><code>const <span class="type">void</span> *data</code></em>,
+ <em class="parameter"><code><span class="type">size_t</span> len</code></em>);</pre>
+<p>Appends a binary value to a STUN message</p>
+<div class="refsect3">
+<a name="stun-message-append-bytes.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>type</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute"><span class="type">StunAttribute</span></a> to append</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>data</p></td>
+<td class="parameter_description"><p>The data to append</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>len</p></td>
+<td class="parameter_description"><p>The length of the attribute</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-message-append-bytes.returns"></a><h4>Returns</h4>
+<p> A <a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="type">StunMessageReturn</span></a> value.</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-message-append-flag"></a><h3>stun_message_append_flag ()</h3>
+<pre class="programlisting"><a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="returnvalue">StunMessageReturn</span></a>
+stun_message_append_flag (<em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute"><span class="type">StunAttribute</span></a> type</code></em>);</pre>
+<p>Appends an empty flag attribute to a STUN message</p>
+<div class="refsect3">
+<a name="stun-message-append-flag.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>type</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute"><span class="type">StunAttribute</span></a> to append</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-message-append-flag.returns"></a><h4>Returns</h4>
+<p> A <a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="type">StunMessageReturn</span></a> value.</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-message-append32"></a><h3>stun_message_append32 ()</h3>
+<pre class="programlisting"><a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="returnvalue">StunMessageReturn</span></a>
+stun_message_append32 (<em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute"><span class="type">StunAttribute</span></a> type</code></em>,
+ <em class="parameter"><code><span class="type">uint32_t</span> value</code></em>);</pre>
+<p>Appends a 32-bits value attribute to a STUN message</p>
+<div class="refsect3">
+<a name="stun-message-append32.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>type</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute"><span class="type">StunAttribute</span></a> to append</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>value</p></td>
+<td class="parameter_description"><p>The value to append (host byte order)</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-message-append32.returns"></a><h4>Returns</h4>
+<p> A <a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="type">StunMessageReturn</span></a> value.</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-message-append64"></a><h3>stun_message_append64 ()</h3>
+<pre class="programlisting"><a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="returnvalue">StunMessageReturn</span></a>
+stun_message_append64 (<em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute"><span class="type">StunAttribute</span></a> type</code></em>,
+ <em class="parameter"><code><span class="type">uint64_t</span> value</code></em>);</pre>
+<p>Appends a 64-bits value attribute to a STUN message</p>
+<div class="refsect3">
+<a name="stun-message-append64.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>type</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute"><span class="type">StunAttribute</span></a> to append</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>value</p></td>
+<td class="parameter_description"><p>The value to append (host byte order)</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-message-append64.returns"></a><h4>Returns</h4>
+<p> A <a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="type">StunMessageReturn</span></a> value.</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-message-append-string"></a><h3>stun_message_append_string ()</h3>
+<pre class="programlisting"><a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="returnvalue">StunMessageReturn</span></a>
+stun_message_append_string (<em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute"><span class="type">StunAttribute</span></a> type</code></em>,
+ <em class="parameter"><code>const <span class="type">char</span> *str</code></em>);</pre>
+<p>Adds an attribute from a nul-terminated string to a STUN message</p>
+<div class="refsect3">
+<a name="stun-message-append-string.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>type</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute"><span class="type">StunAttribute</span></a> to append</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>str</p></td>
+<td class="parameter_description"><p>The string to append</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-message-append-string.returns"></a><h4>Returns</h4>
+<p> A <a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="type">StunMessageReturn</span></a> value.</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-message-append-addr"></a><h3>stun_message_append_addr ()</h3>
+<pre class="programlisting"><a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="returnvalue">StunMessageReturn</span></a>
+stun_message_append_addr (<em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute"><span class="type">StunAttribute</span></a> type</code></em>,
+ <em class="parameter"><code>const <span class="type">struct sockaddr</span> *addr</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/camel/camel-camel-net-utils.html#socklen-t"><span class="type">socklen_t</span></a> addrlen</code></em>);</pre>
+<p>Append a network address attribute to a STUN message</p>
+<div class="refsect3">
+<a name="stun-message-append-addr.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>type</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute"><span class="type">StunAttribute</span></a> to append</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>addr</p></td>
+<td class="parameter_description"><p>The <a href="/usr/share/gtk-doc/html/camel/camel-camel-net-utils.html#sockaddr"><span class="type">sockaddr</span></a> to be append</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>addrlen</p></td>
+<td class="parameter_description"><p>The size of the <em class="parameter"><code>addr</code></em>
+variable.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-message-append-addr.returns"></a><h4>Returns</h4>
+<p> A <a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="type">StunMessageReturn</span></a> value.
+<a class="link" href="libnice-StunMessage.html#STUN-MESSAGE-RETURN-INVALID:CAPS"><code class="literal">STUN_MESSAGE_RETURN_INVALID</code></a> is returned if the <em class="parameter"><code>addrlen</code></em>
+is too small
+<a class="link" href="libnice-StunMessage.html#STUN-MESSAGE-RETURN-UNSUPPORTED-ADDRESS:CAPS"><code class="literal">STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS</code></a> if the address family is unknown.</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-message-append-xor-addr"></a><h3>stun_message_append_xor_addr ()</h3>
+<pre class="programlisting"><a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="returnvalue">StunMessageReturn</span></a>
+stun_message_append_xor_addr (<em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute"><span class="type">StunAttribute</span></a> type</code></em>,
+ <em class="parameter"><code>const <span class="type">struct sockaddr_storage</span> *addr</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/camel/camel-camel-net-utils.html#socklen-t"><span class="type">socklen_t</span></a> addrlen</code></em>);</pre>
+<p>Append an obfuscated network address attribute to a STUN message</p>
+<div class="refsect3">
+<a name="stun-message-append-xor-addr.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>type</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute"><span class="type">StunAttribute</span></a> to append</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>addr</p></td>
+<td class="parameter_description"><p>The <a href="/usr/share/gtk-doc/html/camel/camel-camel-net-utils.html#sockaddr"><span class="type">sockaddr</span></a> to be append</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>addrlen</p></td>
+<td class="parameter_description"><p>The size of the <em class="parameter"><code>addr</code></em>
+variable.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-message-append-xor-addr.returns"></a><h4>Returns</h4>
+<p> A <a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="type">StunMessageReturn</span></a> value.
+<a class="link" href="libnice-StunMessage.html#STUN-MESSAGE-RETURN-INVALID:CAPS"><code class="literal">STUN_MESSAGE_RETURN_INVALID</code></a> is returned if the <em class="parameter"><code>addrlen</code></em>
+is too small
+<a class="link" href="libnice-StunMessage.html#STUN-MESSAGE-RETURN-UNSUPPORTED-ADDRESS:CAPS"><code class="literal">STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS</code></a> if the address family is unknown.</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-message-append-xor-addr-full"></a><h3>stun_message_append_xor_addr_full ()</h3>
+<pre class="programlisting"><a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="returnvalue">StunMessageReturn</span></a>
+stun_message_append_xor_addr_full (<em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute"><span class="type">StunAttribute</span></a> type</code></em>,
+ <em class="parameter"><code>const <span class="type">struct sockaddr_storage</span> *addr</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/camel/camel-camel-net-utils.html#socklen-t"><span class="type">socklen_t</span></a> addrlen</code></em>,
+ <em class="parameter"><code><span class="type">uint32_t</span> magic_cookie</code></em>);</pre>
+<p>Append an obfuscated network address attribute from a STUN message.</p>
+<div class="refsect3">
+<a name="stun-message-append-xor-addr-full.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>type</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute"><span class="type">StunAttribute</span></a> to append</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>addr</p></td>
+<td class="parameter_description"><p>The <a href="/usr/share/gtk-doc/html/camel/camel-camel-net-utils.html#sockaddr"><span class="type">sockaddr</span></a> to be append</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>addrlen</p></td>
+<td class="parameter_description"><p>The size of the <em class="parameter"><code>addr</code></em>
+variable.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>magic_cookie</p></td>
+<td class="parameter_description"><p>The magic cookie to use to XOR the address.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-message-append-xor-addr-full.returns"></a><h4>Returns</h4>
+<p> A <a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="type">StunMessageReturn</span></a> value.
+<a class="link" href="libnice-StunMessage.html#STUN-MESSAGE-RETURN-INVALID:CAPS"><code class="literal">STUN_MESSAGE_RETURN_INVALID</code></a> is returned if the <em class="parameter"><code>addrlen</code></em>
+is too small
+<a class="link" href="libnice-StunMessage.html#STUN-MESSAGE-RETURN-UNSUPPORTED-ADDRESS:CAPS"><code class="literal">STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS</code></a> if the address family is unknown.</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-message-append-error"></a><h3>stun_message_append_error ()</h3>
+<pre class="programlisting"><a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="returnvalue">StunMessageReturn</span></a>
+stun_message_append_error (<em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunError" title="enum StunError"><span class="type">StunError</span></a> code</code></em>);</pre>
+<p>Appends the ERROR-CODE attribute to the STUN message and fills it according
+to <span class="type">code</span></p>
+<div class="refsect3">
+<a name="stun-message-append-error.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>code</p></td>
+<td class="parameter_description"><p>The error code value</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-message-append-error.returns"></a><h4>Returns</h4>
+<p> A <a class="link" href="libnice-StunMessage.html#StunMessageReturn" title="enum StunMessageReturn"><span class="type">StunMessageReturn</span></a> value.</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-message-validate-buffer-length"></a><h3>stun_message_validate_buffer_length ()</h3>
+<pre class="programlisting"><span class="returnvalue">int</span>
+stun_message_validate_buffer_length (<em class="parameter"><code>const <span class="type">uint8_t</span> *msg</code></em>,
+ <em class="parameter"><code><span class="type">size_t</span> length</code></em>,
+ <em class="parameter"><code><span class="type">bool</span> has_padding</code></em>);</pre>
+<p>This function will take a data buffer and will try to validate whether it is
+a STUN message or if it's not or if it's an incomplete STUN message and will
+provide us with the length of the STUN message.</p>
+<div class="refsect3">
+<a name="stun-message-validate-buffer-length.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The buffer to validate</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>length</p></td>
+<td class="parameter_description"><p>The length of the buffer</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>has_padding</p></td>
+<td class="parameter_description"><p>Set TRUE if attributes should be padded to multiple of 4 bytes</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-message-validate-buffer-length.returns"></a><h4>Returns</h4>
+<p> The length of the valid STUN message in the buffer.</p>
+<p> See also: <a class="link" href="libnice-StunMessage.html#STUN-MESSAGE-BUFFER-INCOMPLETE:CAPS" title="STUN_MESSAGE_BUFFER_INCOMPLETE"><span class="type">STUN_MESSAGE_BUFFER_INCOMPLETE</span></a> </p>
+<p> See also: <a class="link" href="libnice-StunMessage.html#STUN-MESSAGE-BUFFER-INVALID:CAPS" title="STUN_MESSAGE_BUFFER_INVALID"><span class="type">STUN_MESSAGE_BUFFER_INVALID</span></a> </p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-message-validate-buffer-length-fast"></a><h3>stun_message_validate_buffer_length_fast ()</h3>
+<pre class="programlisting"><span class="returnvalue">ssize_t</span>
+stun_message_validate_buffer_length_fast
+ (<em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunInputVector" title="StunInputVector"><span class="type">StunInputVector</span></a> *buffers</code></em>,
+ <em class="parameter"><code><span class="type">int</span> n_buffers</code></em>,
+ <em class="parameter"><code><span class="type">size_t</span> total_length</code></em>,
+ <em class="parameter"><code><span class="type">bool</span> has_padding</code></em>);</pre>
+<p>Quickly validate whether the message in the given <em class="parameter"><code>buffers</code></em>
+ is potentially a
+valid STUN message, an incomplete STUN message, or if it’s definitely not one
+at all.</p>
+<p>This is designed as a first-pass validation only, and does not check the
+message’s attributes for validity. If this function returns success, the
+buffers can be compacted and a more thorough validation can be performed
+using <a class="link" href="libnice-StunMessage.html#stun-message-validate-buffer-length" title="stun_message_validate_buffer_length ()"><code class="function">stun_message_validate_buffer_length()</code></a>. If it fails, the buffers
+definitely do not contain a complete, valid STUN message.</p>
+<div class="refsect3">
+<a name="stun-message-validate-buffer-length-fast.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>buffers</p></td>
+<td class="parameter_description"><p>array of contiguous
+<a href="libnice-StunMessage.html#StunInputVector"><span class="type">StunInputVectors</span></a> containing already-received message data. </p></td>
+<td class="parameter_annotations"><span class="annotation">[<acronym title="Parameter points to an array of items."><span class="acronym">array</span></acronym> length=n_buffers][<acronym title="Parameter for input. Default is transfer none."><span class="acronym">in</span></acronym> caller-allocated]</span></td>
+</tr>
+<tr>
+<td class="parameter_name"><p>n_buffers</p></td>
+<td class="parameter_description"><p>number of entries in <em class="parameter"><code>buffers</code></em>
+or if -1 , then buffers is
+terminated by a <a class="link" href="libnice-StunMessage.html#StunInputVector" title="StunInputVector"><span class="type">StunInputVector</span></a> with the buffer pointer being <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#NULL:CAPS"><code class="literal">NULL</code></a>.</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>total_length</p></td>
+<td class="parameter_description"><p>total number of valid bytes stored consecutively in <em class="parameter"><code>buffers</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>has_padding</p></td>
+<td class="parameter_description"><p><a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> if attributes should be padded to 4-byte boundaries</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-message-validate-buffer-length-fast.returns"></a><h4>Returns</h4>
+<p> The length of the valid STUN message in the buffer, or zero or -1 on
+failure</p>
+<p> See also: <a class="link" href="libnice-StunMessage.html#STUN-MESSAGE-BUFFER-INCOMPLETE:CAPS" title="STUN_MESSAGE_BUFFER_INCOMPLETE"><span class="type">STUN_MESSAGE_BUFFER_INCOMPLETE</span></a> </p>
+<p> See also: <a class="link" href="libnice-StunMessage.html#STUN-MESSAGE-BUFFER-INVALID:CAPS" title="STUN_MESSAGE_BUFFER_INVALID"><span class="type">STUN_MESSAGE_BUFFER_INVALID</span></a> </p>
+</div>
+<p class="since">Since: <a class="link" href="ix10.html#api-index-0.1.5">0.1.5</a></p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-message-id"></a><h3>stun_message_id ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+stun_message_id (<em class="parameter"><code>const <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunTransactionId" title="StunTransactionId"><span class="type">StunTransactionId</span></a> id</code></em>);</pre>
+<p>Retreive the STUN transaction id from a STUN message</p>
+<div class="refsect3">
+<a name="stun-message-id.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>id</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunTransactionId" title="StunTransactionId"><span class="type">StunTransactionId</span></a> to fill</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-message-get-class"></a><h3>stun_message_get_class ()</h3>
+<pre class="programlisting"><a class="link" href="libnice-StunMessage.html#StunClass" title="enum StunClass"><span class="returnvalue">StunClass</span></a>
+stun_message_get_class (<em class="parameter"><code>const <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>);</pre>
+<p>Retreive the STUN class from a STUN message</p>
+<div class="refsect3">
+<a name="stun-message-get-class.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-message-get-class.returns"></a><h4>Returns</h4>
+<p> The <a class="link" href="libnice-StunMessage.html#StunClass" title="enum StunClass"><span class="type">StunClass</span></a></p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-message-get-method"></a><h3>stun_message_get_method ()</h3>
+<pre class="programlisting"><a class="link" href="libnice-StunMessage.html#StunMethod" title="enum StunMethod"><span class="returnvalue">StunMethod</span></a>
+stun_message_get_method (<em class="parameter"><code>const <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>);</pre>
+<p>Retreive the STUN method from a STUN message</p>
+<div class="refsect3">
+<a name="stun-message-get-method.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-message-get-method.returns"></a><h4>Returns</h4>
+<p> The <a class="link" href="libnice-StunMessage.html#StunMethod" title="enum StunMethod"><span class="type">StunMethod</span></a></p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-message-has-attribute"></a><h3>stun_message_has_attribute ()</h3>
+<pre class="programlisting"><span class="returnvalue">bool</span>
+stun_message_has_attribute (<em class="parameter"><code>const <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute"><span class="type">StunAttribute</span></a> type</code></em>);</pre>
+<p>Checks if an attribute is present within a STUN message.</p>
+<div class="refsect3">
+<a name="stun-message-has-attribute.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>type</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunAttribute" title="enum StunAttribute"><span class="type">StunAttribute</span></a> to look for</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-message-has-attribute.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> if the attribute is found, <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> otherwise</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-message-has-cookie"></a><h3>stun_message_has_cookie ()</h3>
+<pre class="programlisting"><span class="returnvalue">bool</span>
+stun_message_has_cookie (<em class="parameter"><code>const <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>);</pre>
+<p>Checks if the STUN message has a RFC5389 compatible cookie</p>
+<div class="refsect3">
+<a name="stun-message-has-cookie.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-message-has-cookie.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> if the cookie is present, <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#FALSE:CAPS"><code class="literal">FALSE</code></a> otherwise</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-optional"></a><h3>stun_optional ()</h3>
+<pre class="programlisting"><span class="returnvalue">bool</span>
+stun_optional (<em class="parameter"><code><span class="type">uint16_t</span> t</code></em>);</pre>
+<p>Helper function that checks whether a STUN attribute is a mandatory
+or an optional attribute</p>
+<div class="refsect3">
+<a name="stun-optional.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>t</p></td>
+<td class="parameter_description"><p>An attribute type</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-optional.returns"></a><h4>Returns</h4>
+<p> <a href="/usr/share/gtk-doc/html/glib/glib-Standard-Macros.html#TRUE:CAPS"><code class="literal">TRUE</code></a> if the attribute is an optional one</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-strerror"></a><h3>stun_strerror ()</h3>
+<pre class="programlisting">const <span class="returnvalue">char</span> *
+stun_strerror (<em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunError" title="enum StunError"><span class="type">StunError</span></a> code</code></em>);</pre>
+<p>Transforms a STUN error-code into a human readable string</p>
+<div class="refsect3">
+<a name="stun-strerror.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>code</p></td>
+<td class="parameter_description"><p>host-byte order error code</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-strerror.returns"></a><h4>Returns</h4>
+<p> A static pointer to a nul-terminated error message string.</p>
+</div>
+</div>
+</div>
+<div class="refsect1">
+<a name="libnice-StunMessage.other_details"></a><h2>Types and Values</h2>
+<div class="refsect2">
+<a name="StunMessage"></a><h3>struct StunMessage</h3>
+<pre class="programlisting">struct StunMessage {
+ StunAgent *agent;
+ uint8_t *buffer;
+ size_t buffer_len;
+ uint8_t *key;
+ size_t key_len;
+ uint8_t long_term_key[16];
+ bool long_term_valid;
+};
+</pre>
+<p>This structure represents a STUN message</p>
+<div class="refsect3">
+<a name="StunMessage.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="struct_members_name">
+<col class="struct_members_description">
+<col width="200px" class="struct_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="struct_member_name"><p><a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a> *<em class="structfield"><code><a name="StunMessage.agent"></a>agent</code></em>;</p></td>
+<td class="struct_member_description"><p>The agent that created or validated this message</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><span class="type">uint8_t</span> *<em class="structfield"><code><a name="StunMessage.buffer"></a>buffer</code></em>;</p></td>
+<td class="struct_member_description"><p>The buffer containing the STUN message</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><span class="type">size_t</span> <em class="structfield"><code><a name="StunMessage.buffer-len"></a>buffer_len</code></em>;</p></td>
+<td class="struct_member_description"><p>The length of the buffer (not the size of the message)</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><span class="type">uint8_t</span> *<em class="structfield"><code><a name="StunMessage.key"></a>key</code></em>;</p></td>
+<td class="struct_member_description"><p>The short term credentials key to use for authentication validation
+or that was used to finalize this message</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><span class="type">size_t</span> <em class="structfield"><code><a name="StunMessage.key-len"></a>key_len</code></em>;</p></td>
+<td class="struct_member_description"><p>The length of the associated key</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><span class="type">uint8_t</span> <em class="structfield"><code><a name="StunMessage.long-term-key"></a>long_term_key</code></em>[16];</p></td>
+<td class="struct_member_description"><p>The long term credential key to use for authentication
+validation or that was used to finalize this message</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><span class="type">bool</span> <em class="structfield"><code><a name="StunMessage.long-term-valid"></a>long_term_valid</code></em>;</p></td>
+<td class="struct_member_description"><p>Whether or not the <span class="type">long_term_key</span> variable contains valid
+data</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="StunClass"></a><h3>enum StunClass</h3>
+<p>This enum is used to represent the class of
+a STUN message, as defined in RFC5389</p>
+<div class="refsect3">
+<a name="StunClass.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-REQUEST:CAPS"></a>STUN_REQUEST</p></td>
+<td class="enum_member_description">
+<p>A STUN Request message</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-INDICATION:CAPS"></a>STUN_INDICATION</p></td>
+<td class="enum_member_description">
+<p>A STUN indication message</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-RESPONSE:CAPS"></a>STUN_RESPONSE</p></td>
+<td class="enum_member_description">
+<p>A STUN Response message</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ERROR:CAPS"></a>STUN_ERROR</p></td>
+<td class="enum_member_description">
+<p>A STUN Error message</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="StunMethod"></a><h3>enum StunMethod</h3>
+<p>This enum is used to represent the method of
+a STUN message, as defined by various RFCs</p>
+<div class="refsect3">
+<a name="StunMethod.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-BINDING:CAPS"></a>STUN_BINDING</p></td>
+<td class="enum_member_description">
+<p>The Binding method as defined by the RFC5389</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-SHARED-SECRET:CAPS"></a>STUN_SHARED_SECRET</p></td>
+<td class="enum_member_description">
+<p>The Shared-Secret method as defined by the RFC3489</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ALLOCATE:CAPS"></a>STUN_ALLOCATE</p></td>
+<td class="enum_member_description">
+<p>The Allocate method as defined by the TURN draft 12</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-SET-ACTIVE-DST:CAPS"></a>STUN_SET_ACTIVE_DST</p></td>
+<td class="enum_member_description">
+<p>The Set-Active-Destination method as defined by
+the TURN draft 4</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-REFRESH:CAPS"></a>STUN_REFRESH</p></td>
+<td class="enum_member_description">
+<p>The Refresh method as defined by the TURN draft 12</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-SEND:CAPS"></a>STUN_SEND</p></td>
+<td class="enum_member_description">
+<p>The Send method as defined by the TURN draft 00</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-CONNECT:CAPS"></a>STUN_CONNECT</p></td>
+<td class="enum_member_description">
+<p>The Connect method as defined by the TURN draft 4</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-OLD-SET-ACTIVE-DST:CAPS"></a>STUN_OLD_SET_ACTIVE_DST</p></td>
+<td class="enum_member_description">
+<p>The older Set-Active-Destination method as
+defined by the TURN draft 0</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-IND-SEND:CAPS"></a>STUN_IND_SEND</p></td>
+<td class="enum_member_description">
+<p>The Send method used in indication messages as defined
+by the TURN draft 12</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-IND-DATA:CAPS"></a>STUN_IND_DATA</p></td>
+<td class="enum_member_description">
+<p>The Data method used in indication messages as defined
+by the TURN draft 12</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-IND-CONNECT-STATUS:CAPS"></a>STUN_IND_CONNECT_STATUS</p></td>
+<td class="enum_member_description">
+<p>The Connect-Status method used in indication
+messages as defined by the TURN draft 4</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-CREATEPERMISSION:CAPS"></a>STUN_CREATEPERMISSION</p></td>
+<td class="enum_member_description">
+<p>The CreatePermission method as defined by
+the TURN draft 12</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-CHANNELBIND:CAPS"></a>STUN_CHANNELBIND</p></td>
+<td class="enum_member_description">
+<p>The ChannelBind method as defined by the TURN draft 12</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="StunAttribute"></a><h3>enum StunAttribute</h3>
+<p>Known STUN attribute types as defined by various RFCs and drafts</p>
+<div class="refsect3">
+<a name="StunAttribute.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-MAPPED-ADDRESS:CAPS"></a>STUN_ATTRIBUTE_MAPPED_ADDRESS</p></td>
+<td class="enum_member_description">
+<p>The MAPPED-ADDRESS attribute as defined
+by RFC5389</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-RESPONSE-ADDRESS:CAPS"></a>STUN_ATTRIBUTE_RESPONSE_ADDRESS</p></td>
+<td class="enum_member_description">
+<p>The RESPONSE-ADDRESS attribute as defined
+by RFC3489</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-CHANGE-REQUEST:CAPS"></a>STUN_ATTRIBUTE_CHANGE_REQUEST</p></td>
+<td class="enum_member_description">
+<p>The CHANGE-REQUEST attribute as defined by
+RFC3489</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-SOURCE-ADDRESS:CAPS"></a>STUN_ATTRIBUTE_SOURCE_ADDRESS</p></td>
+<td class="enum_member_description">
+<p>The SOURCE-ADDRESS attribute as defined by
+RFC3489</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-CHANGED-ADDRESS:CAPS"></a>STUN_ATTRIBUTE_CHANGED_ADDRESS</p></td>
+<td class="enum_member_description">
+<p>The CHANGED-ADDRESS attribute as defined
+by RFC3489</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-USERNAME:CAPS"></a>STUN_ATTRIBUTE_USERNAME</p></td>
+<td class="enum_member_description">
+<p>The USERNAME attribute as defined by RFC5389</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-PASSWORD:CAPS"></a>STUN_ATTRIBUTE_PASSWORD</p></td>
+<td class="enum_member_description">
+<p>The PASSWORD attribute as defined by RFC3489</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-MESSAGE-INTEGRITY:CAPS"></a>STUN_ATTRIBUTE_MESSAGE_INTEGRITY</p></td>
+<td class="enum_member_description">
+<p>The MESSAGE-INTEGRITY attribute as defined
+by RFC5389</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-ERROR-CODE:CAPS"></a>STUN_ATTRIBUTE_ERROR_CODE</p></td>
+<td class="enum_member_description">
+<p>The ERROR-CODE attribute as defined by RFC5389</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-UNKNOWN-ATTRIBUTES:CAPS"></a>STUN_ATTRIBUTE_UNKNOWN_ATTRIBUTES</p></td>
+<td class="enum_member_description">
+<p>The UNKNOWN-ATTRIBUTES attribute as
+defined by RFC5389</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-REFLECTED-FROM:CAPS"></a>STUN_ATTRIBUTE_REFLECTED_FROM</p></td>
+<td class="enum_member_description">
+<p>The REFLECTED-FROM attribute as defined
+by RFC3489</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-CHANNEL-NUMBER:CAPS"></a>STUN_ATTRIBUTE_CHANNEL_NUMBER</p></td>
+<td class="enum_member_description">
+<p>The CHANNEL-NUMBER attribute as defined by
+TURN draft 09 and 12</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-LIFETIME:CAPS"></a>STUN_ATTRIBUTE_LIFETIME</p></td>
+<td class="enum_member_description">
+<p>The LIFETIME attribute as defined by TURN
+draft 04, 09 and 12</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-MS-ALTERNATE-SERVER:CAPS"></a>STUN_ATTRIBUTE_MS_ALTERNATE_SERVER</p></td>
+<td class="enum_member_description">
+<p>The ALTERNATE-SERVER attribute as
+defined by [MS-TURN]</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-MAGIC-COOKIE:CAPS"></a>STUN_ATTRIBUTE_MAGIC_COOKIE</p></td>
+<td class="enum_member_description">
+<p>The MAGIC-COOKIE attribute as defined by
+the rosenberg-midcom TURN draft 08</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-BANDWIDTH:CAPS"></a>STUN_ATTRIBUTE_BANDWIDTH</p></td>
+<td class="enum_member_description">
+<p>The BANDWIDTH attribute as defined by TURN draft 04</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-DESTINATION-ADDRESS:CAPS"></a>STUN_ATTRIBUTE_DESTINATION_ADDRESS</p></td>
+<td class="enum_member_description">
+<p>The DESTINATION-ADDRESS attribute as
+defined by the rosenberg-midcom TURN draft 08</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-REMOTE-ADDRESS:CAPS"></a>STUN_ATTRIBUTE_REMOTE_ADDRESS</p></td>
+<td class="enum_member_description">
+<p>The REMOTE-ADDRESS attribute as defined by
+TURN draft 04</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-PEER-ADDRESS:CAPS"></a>STUN_ATTRIBUTE_PEER_ADDRESS</p></td>
+<td class="enum_member_description">
+<p>The PEER-ADDRESS attribute as defined by
+TURN draft 09</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-XOR-PEER-ADDRESS:CAPS"></a>STUN_ATTRIBUTE_XOR_PEER_ADDRESS</p></td>
+<td class="enum_member_description">
+<p>The XOR-PEER-ADDRESS attribute as defined
+by TURN draft 12</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-DATA:CAPS"></a>STUN_ATTRIBUTE_DATA</p></td>
+<td class="enum_member_description">
+<p>The DATA attribute as defined by TURN draft 04,
+09 and 12</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-REALM:CAPS"></a>STUN_ATTRIBUTE_REALM</p></td>
+<td class="enum_member_description">
+<p>The REALM attribute as defined by RFC5389</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-NONCE:CAPS"></a>STUN_ATTRIBUTE_NONCE</p></td>
+<td class="enum_member_description">
+<p>The NONCE attribute as defined by RFC5389</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-RELAY-ADDRESS:CAPS"></a>STUN_ATTRIBUTE_RELAY_ADDRESS</p></td>
+<td class="enum_member_description">
+<p>The RELAY-ADDRESS attribute as defined by
+TURN draft 04</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-RELAYED-ADDRESS:CAPS"></a>STUN_ATTRIBUTE_RELAYED_ADDRESS</p></td>
+<td class="enum_member_description">
+<p>The RELAYED-ADDRESS attribute as defined by
+TURN draft 09</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-XOR-RELAYED-ADDRESS:CAPS"></a>STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS</p></td>
+<td class="enum_member_description">
+<p>The XOR-RELAYED-ADDRESS attribute as
+defined by TURN draft 12</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-REQUESTED-ADDRESS-TYPE:CAPS"></a>STUN_ATTRIBUTE_REQUESTED_ADDRESS_TYPE</p></td>
+<td class="enum_member_description">
+<p>The REQUESTED-ADDRESS-TYPE attribute
+as defined by TURN-IPV6 draft 05</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-REQUESTED-PORT-PROPS:CAPS"></a>STUN_ATTRIBUTE_REQUESTED_PORT_PROPS</p></td>
+<td class="enum_member_description">
+<p>The REQUESTED-PORT-PROPS attribute
+as defined by TURN draft 04</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-REQUESTED-PROPS:CAPS"></a>STUN_ATTRIBUTE_REQUESTED_PROPS</p></td>
+<td class="enum_member_description">
+<p>The REQUESTED-PROPS attribute as defined
+by TURN draft 09</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-EVEN-PORT:CAPS"></a>STUN_ATTRIBUTE_EVEN_PORT</p></td>
+<td class="enum_member_description">
+<p>The EVEN-PORT attribute as defined by TURN draft 12</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-REQUESTED-TRANSPORT:CAPS"></a>STUN_ATTRIBUTE_REQUESTED_TRANSPORT</p></td>
+<td class="enum_member_description">
+<p>The REQUESTED-TRANSPORT attribute as
+defined by TURN draft 12</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-DONT-FRAGMENT:CAPS"></a>STUN_ATTRIBUTE_DONT_FRAGMENT</p></td>
+<td class="enum_member_description">
+<p>The DONT-FRAGMENT attribute as defined
+by TURN draft 12</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-XOR-MAPPED-ADDRESS:CAPS"></a>STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS</p></td>
+<td class="enum_member_description">
+<p>The XOR-MAPPED-ADDRESS attribute as
+defined by RFC5389</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-TIMER-VAL:CAPS"></a>STUN_ATTRIBUTE_TIMER_VAL</p></td>
+<td class="enum_member_description">
+<p>The TIMER-VAL attribute as defined by TURN draft 04</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-REQUESTED-IP:CAPS"></a>STUN_ATTRIBUTE_REQUESTED_IP</p></td>
+<td class="enum_member_description">
+<p>The REQUESTED-IP attribute as defined by
+TURN draft 04</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-RESERVATION-TOKEN:CAPS"></a>STUN_ATTRIBUTE_RESERVATION_TOKEN</p></td>
+<td class="enum_member_description">
+<p>The RESERVATION-TOKEN attribute as defined
+by TURN draft 09 and 12</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-CONNECT-STAT:CAPS"></a>STUN_ATTRIBUTE_CONNECT_STAT</p></td>
+<td class="enum_member_description">
+<p>The CONNECT-STAT attribute as defined by TURN
+draft 04</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-PRIORITY:CAPS"></a>STUN_ATTRIBUTE_PRIORITY</p></td>
+<td class="enum_member_description">
+<p>The PRIORITY attribute as defined by ICE draft 19</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-USE-CANDIDATE:CAPS"></a>STUN_ATTRIBUTE_USE_CANDIDATE</p></td>
+<td class="enum_member_description">
+<p>The USE-CANDIDATE attribute as defined by
+ICE draft 19</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-OPTIONS:CAPS"></a>STUN_ATTRIBUTE_OPTIONS</p></td>
+<td class="enum_member_description">
+<p>The OPTIONS optional attribute as defined by
+libjingle</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-MS-VERSION:CAPS"></a>STUN_ATTRIBUTE_MS_VERSION</p></td>
+<td class="enum_member_description">
+<p>The MS-VERSION optional attribute as defined
+by [MS-TURN]</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-MS-XOR-MAPPED-ADDRESS:CAPS"></a>STUN_ATTRIBUTE_MS_XOR_MAPPED_ADDRESS</p></td>
+<td class="enum_member_description">
+<p>The XOR-MAPPED-ADDRESS optional
+attribute as defined by [MS-TURN]</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-SOFTWARE:CAPS"></a>STUN_ATTRIBUTE_SOFTWARE</p></td>
+<td class="enum_member_description">
+<p>The SOFTWARE optional attribute as defined by RFC5389</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-ALTERNATE-SERVER:CAPS"></a>STUN_ATTRIBUTE_ALTERNATE_SERVER</p></td>
+<td class="enum_member_description">
+<p>The ALTERNATE-SERVER optional attribute as
+defined by RFC5389</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-FINGERPRINT:CAPS"></a>STUN_ATTRIBUTE_FINGERPRINT</p></td>
+<td class="enum_member_description">
+<p>The FINGERPRINT optional attribute as defined
+by RFC5389</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-ICE-CONTROLLED:CAPS"></a>STUN_ATTRIBUTE_ICE_CONTROLLED</p></td>
+<td class="enum_member_description">
+<p>The ICE-CONTROLLED optional attribute as
+defined by ICE draft 19</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-ICE-CONTROLLING:CAPS"></a>STUN_ATTRIBUTE_ICE_CONTROLLING</p></td>
+<td class="enum_member_description">
+<p>The ICE-CONTROLLING optional attribute as
+defined by ICE draft 19</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-MS-SEQUENCE-NUMBER:CAPS"></a>STUN_ATTRIBUTE_MS_SEQUENCE_NUMBER</p></td>
+<td class="enum_member_description">
+<p>The MS-SEQUENCE NUMBER optional attribute
+as defined by [MS-TURN]</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-CANDIDATE-IDENTIFIER:CAPS"></a>STUN_ATTRIBUTE_CANDIDATE_IDENTIFIER</p></td>
+<td class="enum_member_description">
+<p>The CANDIDATE-IDENTIFIER optional
+attribute as defined by [MS-ICE2]</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-MS-IMPLEMENTATION-VERSION:CAPS"></a>STUN_ATTRIBUTE_MS_IMPLEMENTATION_VERSION</p></td>
+<td class="enum_member_description">
+<p>The IMPLEMENTATION-VERSION
+optional attribute as defined by [MS-ICE2]</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ATTRIBUTE-NOMINATION:CAPS"></a>STUN_ATTRIBUTE_NOMINATION</p></td>
+<td class="enum_member_description">
+<p>The NOMINATION attribute as defined by
+draft-thatcher-ice-renomination-00 and deployed in Google Chrome</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="StunTransactionId"></a><h3>StunTransactionId</h3>
+<pre class="programlisting">typedef uint8_t StunTransactionId[STUN_MESSAGE_TRANS_ID_LEN];
+</pre>
+<p>A type that holds a STUN transaction id.</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="StunError"></a><h3>enum StunError</h3>
+<p>STUN error codes as defined by various RFCs and drafts</p>
+<div class="refsect3">
+<a name="StunError.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ERROR-TRY-ALTERNATE:CAPS"></a>STUN_ERROR_TRY_ALTERNATE</p></td>
+<td class="enum_member_description">
+<p>The ERROR-CODE value for the
+"Try Alternate" error as defined in RFC5389</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ERROR-BAD-REQUEST:CAPS"></a>STUN_ERROR_BAD_REQUEST</p></td>
+<td class="enum_member_description">
+<p>The ERROR-CODE value for the
+"Bad Request" error as defined in RFC5389</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ERROR-UNAUTHORIZED:CAPS"></a>STUN_ERROR_UNAUTHORIZED</p></td>
+<td class="enum_member_description">
+<p>The ERROR-CODE value for the
+"Unauthorized" error as defined in RFC5389</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ERROR-UNKNOWN-ATTRIBUTE:CAPS"></a>STUN_ERROR_UNKNOWN_ATTRIBUTE</p></td>
+<td class="enum_member_description">
+<p>The ERROR-CODE value for the
+"Unknown Attribute" error as defined in RFC5389</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ERROR-ALLOCATION-MISMATCH:CAPS"></a>STUN_ERROR_ALLOCATION_MISMATCH</p></td>
+<td class="enum_member_description">
+<p>The ERROR-CODE value for the
+"Allocation Mismatch" error as defined in TURN draft 12.
+Equivalent to the "No Binding" error defined in TURN draft 04.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ERROR-STALE-NONCE:CAPS"></a>STUN_ERROR_STALE_NONCE</p></td>
+<td class="enum_member_description">
+<p>The ERROR-CODE value for the
+"Stale Nonce" error as defined in RFC5389</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ERROR-ACT-DST-ALREADY:CAPS"></a>STUN_ERROR_ACT_DST_ALREADY</p></td>
+<td class="enum_member_description">
+<p>The ERROR-CODE value for the
+"Active Destination Already Set" error as defined in TURN draft 04.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ERROR-UNSUPPORTED-FAMILY:CAPS"></a>STUN_ERROR_UNSUPPORTED_FAMILY</p></td>
+<td class="enum_member_description">
+<p>The ERROR-CODE value for the
+"Address Family not Supported" error as defined in TURN IPV6 Draft 05.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ERROR-WRONG-CREDENTIALS:CAPS"></a>STUN_ERROR_WRONG_CREDENTIALS</p></td>
+<td class="enum_member_description">
+<p>The ERROR-CODE value for the
+"Wrong Credentials" error as defined in TURN Draft 12.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ERROR-UNSUPPORTED-TRANSPORT:CAPS"></a>STUN_ERROR_UNSUPPORTED_TRANSPORT</p></td>
+<td class="enum_member_description">
+<p>he ERROR-CODE value for the
+"Unsupported Transport Protocol" error as defined in TURN Draft 12.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ERROR-INVALID-IP:CAPS"></a>STUN_ERROR_INVALID_IP</p></td>
+<td class="enum_member_description">
+<p>The ERROR-CODE value for the
+"Invalid IP Address" error as defined in TURN draft 04.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ERROR-INVALID-PORT:CAPS"></a>STUN_ERROR_INVALID_PORT</p></td>
+<td class="enum_member_description">
+<p>The ERROR-CODE value for the
+"Invalid Port" error as defined in TURN draft 04.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ERROR-OP-TCP-ONLY:CAPS"></a>STUN_ERROR_OP_TCP_ONLY</p></td>
+<td class="enum_member_description">
+<p>The ERROR-CODE value for the
+"Operation for TCP Only" error as defined in TURN draft 04.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ERROR-CONN-ALREADY:CAPS"></a>STUN_ERROR_CONN_ALREADY</p></td>
+<td class="enum_member_description">
+<p>The ERROR-CODE value for the
+"Connection Already Exists" error as defined in TURN draft 04.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ERROR-ALLOCATION-QUOTA-REACHED:CAPS"></a>STUN_ERROR_ALLOCATION_QUOTA_REACHED</p></td>
+<td class="enum_member_description">
+<p>The ERROR-CODE value for the
+"Allocation Quota Reached" error as defined in TURN draft 12.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ERROR-ROLE-CONFLICT:CAPS"></a>STUN_ERROR_ROLE_CONFLICT</p></td>
+<td class="enum_member_description">
+<p>The ERROR-CODE value for the
+"Role Conflict" error as defined in ICE draft 19.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ERROR-SERVER-ERROR:CAPS"></a>STUN_ERROR_SERVER_ERROR</p></td>
+<td class="enum_member_description">
+<p>The ERROR-CODE value for the
+"Server Error" error as defined in RFC5389</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ERROR-SERVER-CAPACITY:CAPS"></a>STUN_ERROR_SERVER_CAPACITY</p></td>
+<td class="enum_member_description">
+<p>The ERROR-CODE value for the
+"Insufficient Capacity" error as defined in TURN draft 04.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ERROR-INSUFFICIENT-CAPACITY:CAPS"></a>STUN_ERROR_INSUFFICIENT_CAPACITY</p></td>
+<td class="enum_member_description">
+<p>The ERROR-CODE value for the
+"Insufficient Capacity" error as defined in TURN draft 12.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-ERROR-MAX:CAPS"></a>STUN_ERROR_MAX</p></td>
+<td class="enum_member_description">
+<p>The maximum possible ERROR-CODE value as defined by RFC 5389.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="StunMessageReturn"></a><h3>enum StunMessageReturn</h3>
+<p>The return value of most stun_message_* functions.
+This enum will report on whether an operation was successful or not
+and what error occured if any.</p>
+<div class="refsect3">
+<a name="StunMessageReturn.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-MESSAGE-RETURN-SUCCESS:CAPS"></a>STUN_MESSAGE_RETURN_SUCCESS</p></td>
+<td class="enum_member_description">
+<p>The operation was successful</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-MESSAGE-RETURN-NOT-FOUND:CAPS"></a>STUN_MESSAGE_RETURN_NOT_FOUND</p></td>
+<td class="enum_member_description">
+<p>The attribute was not found</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-MESSAGE-RETURN-INVALID:CAPS"></a>STUN_MESSAGE_RETURN_INVALID</p></td>
+<td class="enum_member_description">
+<p>The argument or data is invalid</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-MESSAGE-RETURN-NOT-ENOUGH-SPACE:CAPS"></a>STUN_MESSAGE_RETURN_NOT_ENOUGH_SPACE</p></td>
+<td class="enum_member_description">
+<p>There is not enough space in the
+message to append data to it, or not enough in an argument to fill it with
+the data requested.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-MESSAGE-RETURN-UNSUPPORTED-ADDRESS:CAPS"></a>STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS</p></td>
+<td class="enum_member_description">
+<p>The address in the arguments or in
+the STUN message is not supported.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="STUN-MESSAGE-BUFFER-INCOMPLETE:CAPS"></a><h3>STUN_MESSAGE_BUFFER_INCOMPLETE</h3>
+<pre class="programlisting">#define STUN_MESSAGE_BUFFER_INCOMPLETE 0
+</pre>
+<p>Convenience macro for <a class="link" href="libnice-StunMessage.html#stun-message-validate-buffer-length" title="stun_message_validate_buffer_length ()"><code class="function">stun_message_validate_buffer_length()</code></a> meaning that the
+data to validate does not hold a complete STUN message</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="STUN-MESSAGE-BUFFER-INVALID:CAPS"></a><h3>STUN_MESSAGE_BUFFER_INVALID</h3>
+<pre class="programlisting">#define STUN_MESSAGE_BUFFER_INVALID -1
+</pre>
+<p>Convenience macro for <a class="link" href="libnice-StunMessage.html#stun-message-validate-buffer-length" title="stun_message_validate_buffer_length ()"><code class="function">stun_message_validate_buffer_length()</code></a> meaning that the
+data to validate is not a valid STUN message</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="StunInputVector"></a><h3>StunInputVector</h3>
+<pre class="programlisting">typedef struct {
+ const uint8_t *buffer;
+ size_t size;
+} StunInputVector;
+</pre>
+<p>Container for a single buffer which also stores its length. This is designed
+for vectored I/O: typically an array of <a href="libnice-StunMessage.html#StunInputVector"><span class="type">StunInputVectors</span></a> is passed to
+functions, providing multiple buffers which store logically contiguous
+received data.</p>
+<p>This is guaranteed to be layed out identically in memory to <a href="/usr/share/gtk-doc/html/gio/GSocket.html#GInputVector"><span class="type">GInputVector</span></a>.</p>
+<div class="refsect3">
+<a name="StunInputVector.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="struct_members_name">
+<col class="struct_members_description">
+<col width="200px" class="struct_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="struct_member_name"><p>const <span class="type">uint8_t</span> *<em class="structfield"><code><a name="StunInputVector.buffer"></a>buffer</code></em>;</p></td>
+<td class="struct_member_description"><p>a buffer containing already-received binary data</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+<tr>
+<td class="struct_member_name"><p><span class="type">size_t</span> <em class="structfield"><code><a name="StunInputVector.size"></a>size</code></em>;</p></td>
+<td class="struct_member_description"><p>length of <em class="parameter"><code>buffer</code></em>
+, in bytes</p></td>
+<td class="struct_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<p class="since">Since: <a class="link" href="ix10.html#api-index-0.1.5">0.1.5</a></p>
+</div>
+</div>
+<div class="refsect1">
+<a name="libnice-StunMessage.see-also"></a><h2>See Also</h2>
+<p><a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a></p>
+</div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.29</div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>TURN: libnice Reference Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets Vsnapshot">
+<link rel="home" href="index.html" title="libnice Reference Manual">
+<link rel="up" href="ch04.html" title="STUN usages">
+<link rel="prev" href="libnice-ICE.html" title="ICE">
+<link rel="next" href="libnice-Timer.html" title="Timer">
+<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts">
+<a href="#" class="shortcut">Top</a><span id="nav_description"> <span class="dim">|</span>
+ <a href="#libnice-TURN.description" class="shortcut">Description</a></span>
+</td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="ch04.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="libnice-ICE.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="libnice-Timer.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="refentry">
+<a name="libnice-TURN"></a><div class="titlepage"></div>
+<div class="refnamediv"><table width="100%"><tr>
+<td valign="top">
+<h2><span class="refentrytitle"><a name="libnice-TURN.top_of_page"></a>TURN</span></h2>
+<p>TURN — TURN Allocation Usage</p>
+</td>
+<td class="gallery_image" valign="top" align="right"></td>
+</tr></table></div>
+<div class="refsect1">
+<a name="libnice-TURN.stability-level"></a><h2>Stability Level</h2>
+<acronym title="The intention of a Stable interface is to enable arbitrary third parties to
+develop applications to these interfaces, release them, and have confidence that
+they will run on all minor releases of the product (after the one in which the
+interface was introduced, and within the same major release). Even at a major
+release, incompatible changes are expected to be rare, and to have strong
+justifications.
+"><span class="acronym">Stable</span></acronym>, unless otherwise indicated
+</div>
+<div class="refsect1">
+<a name="libnice-TURN.functions"></a><h2>Functions</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="functions_return">
+<col class="functions_name">
+</colgroup>
+<tbody>
+<tr>
+<td class="function_type">
+<span class="returnvalue">size_t</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-TURN.html#stun-usage-turn-create" title="stun_usage_turn_create ()">stun_usage_turn_create</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">size_t</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-TURN.html#stun-usage-turn-create-refresh" title="stun_usage_turn_create_refresh ()">stun_usage_turn_create_refresh</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="libnice-TURN.html#StunUsageTurnReturn" title="enum StunUsageTurnReturn"><span class="returnvalue">StunUsageTurnReturn</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-TURN.html#stun-usage-turn-process" title="stun_usage_turn_process ()">stun_usage_turn_process</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="libnice-TURN.html#StunUsageTurnReturn" title="enum StunUsageTurnReturn"><span class="returnvalue">StunUsageTurnReturn</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-TURN.html#stun-usage-turn-refresh-process" title="stun_usage_turn_refresh_process ()">stun_usage_turn_refresh_process</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">size_t</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-TURN.html#stun-usage-turn-create-permission" title="stun_usage_turn_create_permission ()">stun_usage_turn_create_permission</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect1">
+<a name="libnice-TURN.other"></a><h2>Types and Values</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="name">
+<col class="description">
+</colgroup>
+<tbody>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="libnice-TURN.html#StunUsageTurnCompatibility" title="enum StunUsageTurnCompatibility">StunUsageTurnCompatibility</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="libnice-TURN.html#StunUsageTurnRequestPorts" title="enum StunUsageTurnRequestPorts">StunUsageTurnRequestPorts</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="libnice-TURN.html#StunUsageTurnReturn" title="enum StunUsageTurnReturn">StunUsageTurnReturn</a></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect1">
+<a name="libnice-TURN.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include <stun/usages/turn.h>
+</pre>
+</div>
+<div class="refsect1">
+<a name="libnice-TURN.description"></a><h2>Description</h2>
+<p>The STUN TURN usage allows for easily creating and parsing STUN Allocate
+requests and responses used for TURN. The API allows you to create a new
+allocation or refresh an existing one as well as to parse a response to
+an allocate or refresh request.</p>
+</div>
+<div class="refsect1">
+<a name="libnice-TURN.functions_details"></a><h2>Functions</h2>
+<div class="refsect2">
+<a name="stun-usage-turn-create"></a><h3>stun_usage_turn_create ()</h3>
+<pre class="programlisting"><span class="returnvalue">size_t</span>
+stun_usage_turn_create (<em class="parameter"><code><a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><span class="type">uint8_t</span> *buffer</code></em>,
+ <em class="parameter"><code><span class="type">size_t</span> buffer_len</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *previous_response</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-TURN.html#StunUsageTurnRequestPorts" title="enum StunUsageTurnRequestPorts"><span class="type">StunUsageTurnRequestPorts</span></a> request_ports</code></em>,
+ <em class="parameter"><code><span class="type">int32_t</span> bandwidth</code></em>,
+ <em class="parameter"><code><span class="type">int32_t</span> lifetime</code></em>,
+ <em class="parameter"><code><span class="type">uint8_t</span> *username</code></em>,
+ <em class="parameter"><code><span class="type">size_t</span> username_len</code></em>,
+ <em class="parameter"><code><span class="type">uint8_t</span> *password</code></em>,
+ <em class="parameter"><code><span class="type">size_t</span> password_len</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-TURN.html#StunUsageTurnCompatibility" title="enum StunUsageTurnCompatibility"><span class="type">StunUsageTurnCompatibility</span></a> compatibility</code></em>);</pre>
+<p>Create a new TURN Allocation request</p>
+<div class="refsect3">
+<a name="stun-usage-turn-create.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a> to use to build the request</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> to build</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>The buffer to use for creating the <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buffer_len</p></td>
+<td class="parameter_description"><p>The size of the <em class="parameter"><code>buffer</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>previous_response</p></td>
+<td class="parameter_description"><p>If this is the first request you are sending, set this
+argument to NULL, if it's a subsequent request you are building, then set this
+argument to the response you have received. This argument is used for building
+long term credentials (using the REALM and NONCE attributes) as well as for
+getting the RESERVATION-TOKEN attribute when you previously requested an
+allocation which reserved two ports</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>request_ports</p></td>
+<td class="parameter_description">
+<p>Specify how you want to request the allocated port(s).
+This is only used if the compatibility is set to
+<a class="link" href="libnice-TURN.html#STUN-USAGE-TURN-COMPATIBILITY-DRAFT9:CAPS"><span class="type">STUN_USAGE_TURN_COMPATIBILITY_DRAFT9</span></a></p>
+<p>See <a class="link" href="libnice-TURN.html#StunUsageTurnRequestPorts" title="enum StunUsageTurnRequestPorts"><span class="type">StunUsageTurnRequestPorts</span></a> </p>
+</td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>bandwidth</p></td>
+<td class="parameter_description"><p>The bandwidth to request from the server for the allocation. If
+this value is negative, then no BANDWIDTH attribute is added to the request.
+This is only used if the compatibility is set to
+<a class="link" href="libnice-TURN.html#STUN-USAGE-TURN-COMPATIBILITY-DRAFT9:CAPS"><span class="type">STUN_USAGE_TURN_COMPATIBILITY_DRAFT9</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>lifetime</p></td>
+<td class="parameter_description"><p>The lifetime of the allocation to request from the server. If
+this value is negative, then no LIFETIME attribute is added to the request.
+This is only used if the compatibility is set to
+<a class="link" href="libnice-TURN.html#STUN-USAGE-TURN-COMPATIBILITY-DRAFT9:CAPS"><span class="type">STUN_USAGE_TURN_COMPATIBILITY_DRAFT9</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>username</p></td>
+<td class="parameter_description"><p>The username to use in the request</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>username_len</p></td>
+<td class="parameter_description"><p>The length of <em class="parameter"><code>username</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>password</p></td>
+<td class="parameter_description"><p>The key to use for building the MESSAGE-INTEGRITY</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>password_len</p></td>
+<td class="parameter_description"><p>The length of <em class="parameter"><code>password</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>compatibility</p></td>
+<td class="parameter_description"><p>The compatibility mode to use for building the Allocation
+request</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-usage-turn-create.returns"></a><h4>Returns</h4>
+<p> The length of the message to send</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-usage-turn-create-refresh"></a><h3>stun_usage_turn_create_refresh ()</h3>
+<pre class="programlisting"><span class="returnvalue">size_t</span>
+stun_usage_turn_create_refresh (<em class="parameter"><code><a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><span class="type">uint8_t</span> *buffer</code></em>,
+ <em class="parameter"><code><span class="type">size_t</span> buffer_len</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *previous_response</code></em>,
+ <em class="parameter"><code><span class="type">int32_t</span> lifetime</code></em>,
+ <em class="parameter"><code><span class="type">uint8_t</span> *username</code></em>,
+ <em class="parameter"><code><span class="type">size_t</span> username_len</code></em>,
+ <em class="parameter"><code><span class="type">uint8_t</span> *password</code></em>,
+ <em class="parameter"><code><span class="type">size_t</span> password_len</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-TURN.html#StunUsageTurnCompatibility" title="enum StunUsageTurnCompatibility"><span class="type">StunUsageTurnCompatibility</span></a> compatibility</code></em>);</pre>
+<p>Create a new TURN Refresh request</p>
+<div class="refsect3">
+<a name="stun-usage-turn-create-refresh.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a> to use to build the request</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> to build</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>The buffer to use for creating the <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buffer_len</p></td>
+<td class="parameter_description"><p>The size of the <em class="parameter"><code>buffer</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>previous_response</p></td>
+<td class="parameter_description"><p>If this is the first request you are sending, set this
+argument to NULL, if it's a subsequent request you are building, then set this
+argument to the response you have received. This argument is used for building
+long term credentials (using the REALM and NONCE attributes)</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>lifetime</p></td>
+<td class="parameter_description"><p>The lifetime of the allocation to request from the server. If
+this value is negative, then no LIFETIME attribute is added to the request.
+This is only used if the compatibility is set to
+<a class="link" href="libnice-TURN.html#STUN-USAGE-TURN-COMPATIBILITY-DRAFT9:CAPS"><span class="type">STUN_USAGE_TURN_COMPATIBILITY_DRAFT9</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>username</p></td>
+<td class="parameter_description"><p>The username to use in the request</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>username_len</p></td>
+<td class="parameter_description"><p>The length of <em class="parameter"><code>username</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>password</p></td>
+<td class="parameter_description"><p>The key to use for building the MESSAGE-INTEGRITY</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>password_len</p></td>
+<td class="parameter_description"><p>The length of <em class="parameter"><code>password</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>compatibility</p></td>
+<td class="parameter_description"><p>The compatibility mode to use for building the Allocation
+request</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-usage-turn-create-refresh.returns"></a><h4>Returns</h4>
+<p> The length of the message to send</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-usage-turn-process"></a><h3>stun_usage_turn_process ()</h3>
+<pre class="programlisting"><a class="link" href="libnice-TURN.html#StunUsageTurnReturn" title="enum StunUsageTurnReturn"><span class="returnvalue">StunUsageTurnReturn</span></a>
+stun_usage_turn_process (<em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><span class="type">struct sockaddr_storage</span> *relay_addr</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/camel/camel-camel-net-utils.html#socklen-t"><span class="type">socklen_t</span></a> *relay_addrlen</code></em>,
+ <em class="parameter"><code><span class="type">struct sockaddr_storage</span> *addr</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/camel/camel-camel-net-utils.html#socklen-t"><span class="type">socklen_t</span></a> *addrlen</code></em>,
+ <em class="parameter"><code><span class="type">struct sockaddr_storage</span> *alternate_server</code></em>,
+ <em class="parameter"><code><a href="/usr/share/gtk-doc/html/camel/camel-camel-net-utils.html#socklen-t"><span class="type">socklen_t</span></a> *alternate_server_len</code></em>,
+ <em class="parameter"><code><span class="type">uint32_t</span> *bandwidth</code></em>,
+ <em class="parameter"><code><span class="type">uint32_t</span> *lifetime</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-TURN.html#StunUsageTurnCompatibility" title="enum StunUsageTurnCompatibility"><span class="type">StunUsageTurnCompatibility</span></a> compatibility</code></em>);</pre>
+<p>Process a TURN Allocate response and extract the necessary information from
+the message</p>
+<div class="refsect3">
+<a name="stun-usage-turn-process.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The message containing the response</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>relay_addr</p></td>
+<td class="parameter_description"><p>A pointer to a <a href="/usr/share/gtk-doc/html/camel/camel-camel-net-utils.html#sockaddr"><span class="type">sockaddr</span></a> structure to fill with the relay address
+that the TURN server allocated for us</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>relay_addrlen</p></td>
+<td class="parameter_description"><p>The length of <em class="parameter"><code>relay_addr</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>addr</p></td>
+<td class="parameter_description"><p>A pointer to a <a href="/usr/share/gtk-doc/html/camel/camel-camel-net-utils.html#sockaddr"><span class="type">sockaddr</span></a> structure to fill with the mapped address
+that the STUN response contains.
+This argument will only be filled if the return value
+of the function is <a class="link" href="libnice-TURN.html#STUN-USAGE-TURN-RETURN-MAPPED-SUCCESS:CAPS"><span class="type">STUN_USAGE_TURN_RETURN_MAPPED_SUCCESS</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>addrlen</p></td>
+<td class="parameter_description"><p>The length of <em class="parameter"><code>addr</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>alternate_server</p></td>
+<td class="parameter_description"><p>A pointer to a <a href="/usr/share/gtk-doc/html/camel/camel-camel-net-utils.html#sockaddr"><span class="type">sockaddr</span></a> structure to fill with the
+address of an alternate server to which we should send our new STUN
+Allocate request, in case the currently used TURN server is requesting the use
+of an alternate server. This argument will only be filled if the return value
+of the function is <a class="link" href="libnice-TURN.html#STUN-USAGE-TURN-RETURN-ALTERNATE-SERVER:CAPS"><span class="type">STUN_USAGE_TURN_RETURN_ALTERNATE_SERVER</span></a>
+In the case of <em class="parameter"><code>STUN_USAGE_TURN_COMPATIBILITY_OC2007</code></em>
+compatibility, the
+<em class="parameter"><code>alternate_server</code></em>
+could be filled at any time, and should only be considered
+if the request was sent to a different server than the address returned
+in the <em class="parameter"><code>alternate_server</code></em>
+field</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>alternate_server_len</p></td>
+<td class="parameter_description"><p>The length of <em class="parameter"><code>alternate_server</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>bandwidth</p></td>
+<td class="parameter_description"><p>A pointer to fill with the bandwidth the TURN server allocated us</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>lifetime</p></td>
+<td class="parameter_description"><p>A pointer to fill with the lifetime of the allocation</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>compatibility</p></td>
+<td class="parameter_description"><p>The compatibility mode to use for processing the Allocation
+response</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-usage-turn-process.returns"></a><h4>Returns</h4>
+<p> A <a class="link" href="libnice-TURN.html#StunUsageTurnReturn" title="enum StunUsageTurnReturn"><span class="type">StunUsageTurnReturn</span></a> value</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-usage-turn-refresh-process"></a><h3>stun_usage_turn_refresh_process ()</h3>
+<pre class="programlisting"><a class="link" href="libnice-TURN.html#StunUsageTurnReturn" title="enum StunUsageTurnReturn"><span class="returnvalue">StunUsageTurnReturn</span></a>
+stun_usage_turn_refresh_process (<em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><span class="type">uint32_t</span> *lifetime</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-TURN.html#StunUsageTurnCompatibility" title="enum StunUsageTurnCompatibility"><span class="type">StunUsageTurnCompatibility</span></a> compatibility</code></em>);</pre>
+<p>Process a TURN Refresh response and extract the necessary information from
+the message</p>
+<div class="refsect3">
+<a name="stun-usage-turn-refresh-process.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The message containing the response</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>lifetime</p></td>
+<td class="parameter_description"><p>A pointer to fill with the lifetime of the allocation</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>compatibility</p></td>
+<td class="parameter_description"><p>The compatibility mode to use for processing the Refresh
+response</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-usage-turn-refresh-process.returns"></a><h4>Returns</h4>
+<p> A <a class="link" href="libnice-TURN.html#StunUsageTurnReturn" title="enum StunUsageTurnReturn"><span class="type">StunUsageTurnReturn</span></a> value. A <a class="link" href="libnice-TURN.html#STUN-USAGE-TURN-RETURN-RELAY-SUCCESS:CAPS"><span class="type">STUN_USAGE_TURN_RETURN_RELAY_SUCCESS</span></a>
+means the Refresh was successful, but no relay address is given (kept the same
+as for the original allocation)</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-usage-turn-create-permission"></a><h3>stun_usage_turn_create_permission ()</h3>
+<pre class="programlisting"><span class="returnvalue">size_t</span>
+stun_usage_turn_create_permission (<em class="parameter"><code><a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a> *agent</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> *msg</code></em>,
+ <em class="parameter"><code><span class="type">uint8_t</span> *buffer</code></em>,
+ <em class="parameter"><code><span class="type">size_t</span> buffer_len</code></em>,
+ <em class="parameter"><code><span class="type">uint8_t</span> *username</code></em>,
+ <em class="parameter"><code><span class="type">size_t</span> username_len</code></em>,
+ <em class="parameter"><code><span class="type">uint8_t</span> *password</code></em>,
+ <em class="parameter"><code><span class="type">size_t</span> password_len</code></em>,
+ <em class="parameter"><code><span class="type">uint8_t</span> *realm</code></em>,
+ <em class="parameter"><code><span class="type">size_t</span> realm_len</code></em>,
+ <em class="parameter"><code><span class="type">uint8_t</span> *nonce</code></em>,
+ <em class="parameter"><code><span class="type">size_t</span> nonce_len</code></em>,
+ <em class="parameter"><code><span class="type">struct sockaddr_storage</span> *peer</code></em>,
+ <em class="parameter"><code><a class="link" href="libnice-TURN.html#StunUsageTurnCompatibility" title="enum StunUsageTurnCompatibility"><span class="type">StunUsageTurnCompatibility</span></a> compatibility</code></em>);</pre>
+<p>Create a new TURN CreatePermission request</p>
+<div class="refsect3">
+<a name="stun-usage-turn-create-permission.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>agent</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunAgent.html#StunAgent" title="StunAgent"><span class="type">StunAgent</span></a> to use to build the request</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>msg</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a> to build</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buffer</p></td>
+<td class="parameter_description"><p>The buffer to use for creating the <a class="link" href="libnice-StunMessage.html#StunMessage" title="struct StunMessage"><span class="type">StunMessage</span></a></p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>buffer_len</p></td>
+<td class="parameter_description"><p>The size of the <em class="parameter"><code>buffer</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>username</p></td>
+<td class="parameter_description"><p>The username to use in the request</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>username_len</p></td>
+<td class="parameter_description"><p>The length of <em class="parameter"><code>username</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>password</p></td>
+<td class="parameter_description"><p>The key to use for building the MESSAGE-INTEGRITY</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>password_len</p></td>
+<td class="parameter_description"><p>The length of <em class="parameter"><code>password</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>realm</p></td>
+<td class="parameter_description"><p>The realm identifier to use in the request</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>realm_len</p></td>
+<td class="parameter_description"><p>The length of <em class="parameter"><code>realm</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>nonce</p></td>
+<td class="parameter_description"><p>Unique and securely random nonce to use in the request</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>nonce_len</p></td>
+<td class="parameter_description"><p>The length of <em class="parameter"><code>nonce</code></em>
+</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>peer</p></td>
+<td class="parameter_description"><p>Server-reflexive host address to request permission for</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>compatibility</p></td>
+<td class="parameter_description"><p>The compatibility mode to use for building the
+CreatePermission request</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-usage-turn-create-permission.returns"></a><h4>Returns</h4>
+<p> The length of the message to send</p>
+</div>
+</div>
+</div>
+<div class="refsect1">
+<a name="libnice-TURN.other_details"></a><h2>Types and Values</h2>
+<div class="refsect2">
+<a name="StunUsageTurnCompatibility"></a><h3>enum StunUsageTurnCompatibility</h3>
+<p>Specifies which TURN specification compatibility to use</p>
+<div class="refsect3">
+<a name="StunUsageTurnCompatibility.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-USAGE-TURN-COMPATIBILITY-DRAFT9:CAPS"></a>STUN_USAGE_TURN_COMPATIBILITY_DRAFT9</p></td>
+<td class="enum_member_description">
+<p>Use the specification compatible with
+TURN Draft 09</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-USAGE-TURN-COMPATIBILITY-GOOGLE:CAPS"></a>STUN_USAGE_TURN_COMPATIBILITY_GOOGLE</p></td>
+<td class="enum_member_description">
+<p>Use the specification compatible with
+Google Talk's relay server</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-USAGE-TURN-COMPATIBILITY-MSN:CAPS"></a>STUN_USAGE_TURN_COMPATIBILITY_MSN</p></td>
+<td class="enum_member_description">
+<p>Use the specification compatible with
+MSN TURN servers</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-USAGE-TURN-COMPATIBILITY-OC2007:CAPS"></a>STUN_USAGE_TURN_COMPATIBILITY_OC2007</p></td>
+<td class="enum_member_description">
+<p>Use the specification compatible with
+Microsoft Office Communicator 2007</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-USAGE-TURN-COMPATIBILITY-RFC5766:CAPS"></a>STUN_USAGE_TURN_COMPATIBILITY_RFC5766</p></td>
+<td class="enum_member_description">
+<p>Use the specification compatible with
+RFC 5766 (the final, canonical TURN standard)</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="StunUsageTurnRequestPorts"></a><h3>enum StunUsageTurnRequestPorts</h3>
+<p>This enum is used to specify which port configuration you want when creating
+a new Allocation</p>
+<div class="refsect3">
+<a name="StunUsageTurnRequestPorts.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-USAGE-TURN-REQUEST-PORT-NORMAL:CAPS"></a>STUN_USAGE_TURN_REQUEST_PORT_NORMAL</p></td>
+<td class="enum_member_description">
+<p>Request a normal port</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-USAGE-TURN-REQUEST-PORT-EVEN:CAPS"></a>STUN_USAGE_TURN_REQUEST_PORT_EVEN</p></td>
+<td class="enum_member_description">
+<p>Request an even port</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-USAGE-TURN-REQUEST-PORT-EVEN-AND-RESERVE:CAPS"></a>STUN_USAGE_TURN_REQUEST_PORT_EVEN_AND_RESERVE</p></td>
+<td class="enum_member_description">
+<p>Request an even port and
+reserve the next higher port</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="StunUsageTurnReturn"></a><h3>enum StunUsageTurnReturn</h3>
+<p>Return value of <a class="link" href="libnice-TURN.html#stun-usage-turn-process" title="stun_usage_turn_process ()"><code class="function">stun_usage_turn_process()</code></a> and
+<a class="link" href="libnice-TURN.html#stun-usage-turn-refresh-process" title="stun_usage_turn_refresh_process ()"><code class="function">stun_usage_turn_refresh_process()</code></a> which allows you to see what status the
+function call returned.</p>
+<div class="refsect3">
+<a name="StunUsageTurnReturn.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-USAGE-TURN-RETURN-RELAY-SUCCESS:CAPS"></a>STUN_USAGE_TURN_RETURN_RELAY_SUCCESS</p></td>
+<td class="enum_member_description">
+<p>The response was successful and a relay
+address is provided</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-USAGE-TURN-RETURN-MAPPED-SUCCESS:CAPS"></a>STUN_USAGE_TURN_RETURN_MAPPED_SUCCESS</p></td>
+<td class="enum_member_description">
+<p>The response was successful and a
+relay address as well as a mapped address are provided</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-USAGE-TURN-RETURN-ERROR:CAPS"></a>STUN_USAGE_TURN_RETURN_ERROR</p></td>
+<td class="enum_member_description">
+<p>The response resulted in an error</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-USAGE-TURN-RETURN-INVALID:CAPS"></a>STUN_USAGE_TURN_RETURN_INVALID</p></td>
+<td class="enum_member_description">
+<p>The response is not a valid response</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-USAGE-TURN-RETURN-ALTERNATE-SERVER:CAPS"></a>STUN_USAGE_TURN_RETURN_ALTERNATE_SERVER</p></td>
+<td class="enum_member_description">
+<p>The server requests the message
+to be sent to an alternate server</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+</div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.29</div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Timer: libnice Reference Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets Vsnapshot">
+<link rel="home" href="index.html" title="libnice Reference Manual">
+<link rel="up" href="ch04.html" title="STUN usages">
+<link rel="prev" href="libnice-TURN.html" title="TURN">
+<link rel="next" href="pt03.html" title="Part III. Pseudo TCP Socket implementation">
+<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts">
+<a href="#" class="shortcut">Top</a><span id="nav_description"> <span class="dim">|</span>
+ <a href="#libnice-Timer.description" class="shortcut">Description</a></span>
+</td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><a accesskey="u" href="ch04.html"><img src="up.png" width="16" height="16" border="0" alt="Up"></a></td>
+<td><a accesskey="p" href="libnice-TURN.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="pt03.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="refentry">
+<a name="libnice-Timer"></a><div class="titlepage"></div>
+<div class="refnamediv"><table width="100%"><tr>
+<td valign="top">
+<h2><span class="refentrytitle"><a name="libnice-Timer.top_of_page"></a>Timer</span></h2>
+<p>Timer — STUN timer Usage</p>
+</td>
+<td class="gallery_image" valign="top" align="right"></td>
+</tr></table></div>
+<div class="refsect1">
+<a name="libnice-Timer.stability-level"></a><h2>Stability Level</h2>
+<acronym title="The intention of a Stable interface is to enable arbitrary third parties to
+develop applications to these interfaces, release them, and have confidence that
+they will run on all minor releases of the product (after the one in which the
+interface was introduced, and within the same major release). Even at a major
+release, incompatible changes are expected to be rare, and to have strong
+justifications.
+"><span class="acronym">Stable</span></acronym>, unless otherwise indicated
+</div>
+<div class="refsect1">
+<a name="libnice-Timer.functions"></a><h2>Functions</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="functions_return">
+<col class="functions_name">
+</colgroup>
+<tbody>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-Timer.html#stun-timer-start" title="stun_timer_start ()">stun_timer_start</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">void</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-Timer.html#stun-timer-start-reliable" title="stun_timer_start_reliable ()">stun_timer_start_reliable</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<a class="link" href="libnice-Timer.html#StunUsageTimerReturn" title="enum StunUsageTimerReturn"><span class="returnvalue">StunUsageTimerReturn</span></a>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-Timer.html#stun-timer-refresh" title="stun_timer_refresh ()">stun_timer_refresh</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+<tr>
+<td class="function_type">
+<span class="returnvalue">unsigned</span>
+</td>
+<td class="function_name">
+<a class="link" href="libnice-Timer.html#stun-timer-remainder" title="stun_timer_remainder ()">stun_timer_remainder</a> <span class="c_punctuation">()</span>
+</td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect1">
+<a name="libnice-Timer.other"></a><h2>Types and Values</h2>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="name">
+<col class="description">
+</colgroup>
+<tbody>
+<tr>
+<td class="typedef_keyword">typedef</td>
+<td class="function_name"><a class="link" href="libnice-Timer.html#StunTimer" title="StunTimer">StunTimer</a></td>
+</tr>
+<tr>
+<td class="datatype_keyword">enum</td>
+<td class="function_name"><a class="link" href="libnice-Timer.html#StunUsageTimerReturn" title="enum StunUsageTimerReturn">StunUsageTimerReturn</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="libnice-Timer.html#STUN-TIMER-DEFAULT-MAX-RETRANSMISSIONS:CAPS" title="STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS">STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="libnice-Timer.html#STUN-TIMER-DEFAULT-RELIABLE-TIMEOUT:CAPS" title="STUN_TIMER_DEFAULT_RELIABLE_TIMEOUT">STUN_TIMER_DEFAULT_RELIABLE_TIMEOUT</a></td>
+</tr>
+<tr>
+<td class="define_keyword">#define</td>
+<td class="function_name"><a class="link" href="libnice-Timer.html#STUN-TIMER-DEFAULT-TIMEOUT:CAPS" title="STUN_TIMER_DEFAULT_TIMEOUT">STUN_TIMER_DEFAULT_TIMEOUT</a></td>
+</tr>
+</tbody>
+</table></div>
+</div>
+<div class="refsect1">
+<a name="libnice-Timer.includes"></a><h2>Includes</h2>
+<pre class="synopsis">#include <stun/usages/timer.h>
+</pre>
+</div>
+<div class="refsect1">
+<a name="libnice-Timer.description"></a><h2>Description</h2>
+<p>The STUN timer usage is a set of helpful utility functions that allows you
+to easily track when a STUN message should be retransmitted or considered
+as timed out.</p>
+<div class="example">
+<a name="id-1.3.3.5.7.3"></a><p class="title"><b>Example 3. Simple example on how to use the timer usage</b></p>
+<div class="example-contents">
+ <table class="listing_frame" border="0" cellpadding="0" cellspacing="0">
+ <tbody>
+ <tr>
+ <td class="listing_lines" align="right"><pre>1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44</pre></td>
+ <td class="listing_code"><pre class="programlisting"><span class="usertype">StunTimer</span><span class="normal"> timer</span><span class="symbol">;</span>
+<span class="type">unsigned</span><span class="normal"> remainder</span><span class="symbol">;</span>
+<span class="usertype">StunUsageTimerReturn</span><span class="normal"> ret</span><span class="symbol">;</span>
+
+<span class="comment">// Build the message, etc..</span>
+<span class="symbol">...</span>
+
+<span class="comment">// Send the message and start the timer</span>
+<span class="function">send</span><span class="symbol">(</span><span class="normal">socket</span><span class="symbol">,</span><span class="normal"> request</span><span class="symbol">,</span><span class="normal"> </span><span class="keyword">sizeof</span><span class="symbol">(</span><span class="normal">request</span><span class="symbol">));</span>
+<span class="function"><a href="libnice-Timer.html#stun-timer-start">stun_timer_start</a></span><span class="symbol">(&</span><span class="normal">timer</span><span class="symbol">,</span><span class="normal"> <a href="libnice-Timer.html#STUN-TIMER-DEFAULT-TIMEOUT:CAPS">STUN_TIMER_DEFAULT_TIMEOUT</a></span><span class="symbol">,</span>
+<span class="normal"> <a href="libnice-Timer.html#STUN-TIMER-DEFAULT-MAX-RETRANSMISSIONS:CAPS">STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS</a></span><span class="symbol">);</span>
+
+<span class="comment">// Loop until we get the response</span>
+<span class="keyword">for</span><span class="normal"> </span><span class="symbol">(;;)</span><span class="normal"> </span><span class="cbracket">{</span>
+<span class="normal"> remainder </span><span class="symbol">=</span><span class="normal"> </span><span class="function"><a href="libnice-Timer.html#stun-timer-remainder">stun_timer_remainder</a></span><span class="symbol">(&</span><span class="normal">timer</span><span class="symbol">);</span>
+
+<span class="normal"> </span><span class="comment">// Poll the socket until data is received or the timer expires</span>
+<span class="normal"> </span><span class="keyword">if</span><span class="normal"> </span><span class="symbol">(</span><span class="function">poll</span><span class="normal"> </span><span class="symbol">(&</span><span class="normal">pollfd</span><span class="symbol">,</span><span class="normal"> </span><span class="number">1</span><span class="symbol">,</span><span class="normal"> delay</span><span class="symbol">)</span><span class="normal"> </span><span class="symbol"><=</span><span class="normal"> </span><span class="number">0</span><span class="symbol">)</span><span class="normal"> </span><span class="cbracket">{</span>
+<span class="normal"> </span><span class="comment">// Time out and no response was received</span>
+<span class="normal"> ret </span><span class="symbol">=</span><span class="normal"> </span><span class="function"><a href="libnice-Timer.html#stun-timer-refresh">stun_timer_refresh</a></span><span class="normal"> </span><span class="symbol">(&</span><span class="normal">timer</span><span class="symbol">);</span>
+<span class="normal"> </span><span class="keyword">if</span><span class="normal"> </span><span class="symbol">(</span><span class="normal">ret </span><span class="symbol">==</span><span class="normal"> <a href="libnice-Timer.html#STUN-USAGE-TIMER-RETURN-TIMEOUT:CAPS">STUN_USAGE_TIMER_RETURN_TIMEOUT</a></span><span class="symbol">)</span><span class="normal"> </span><span class="cbracket">{</span>
+<span class="normal"> </span><span class="comment">// Transaction timed out</span>
+<span class="normal"> </span><span class="keyword">break</span><span class="symbol">;</span>
+<span class="normal"> </span><span class="cbracket">}</span><span class="normal"> </span><span class="keyword">else</span><span class="normal"> </span><span class="keyword">if</span><span class="normal"> </span><span class="symbol">(</span><span class="normal">ret </span><span class="symbol">==</span><span class="normal"> <a href="libnice-Timer.html#STUN-USAGE-TIMER-RETURN-RETRANSMIT:CAPS">STUN_USAGE_TIMER_RETURN_RETRANSMIT</a></span><span class="symbol">)</span><span class="normal"> </span><span class="cbracket">{</span>
+<span class="normal"> </span><span class="comment">// A retransmission is necessary</span>
+<span class="normal"> </span><span class="function">send</span><span class="symbol">(</span><span class="normal">socket</span><span class="symbol">,</span><span class="normal"> request</span><span class="symbol">,</span><span class="normal"> </span><span class="keyword">sizeof</span><span class="symbol">(</span><span class="normal">request</span><span class="symbol">));</span>
+<span class="normal"> </span><span class="keyword">continue</span><span class="symbol">;</span>
+<span class="normal"> </span><span class="cbracket">}</span><span class="normal"> </span><span class="keyword">else</span><span class="normal"> </span><span class="keyword">if</span><span class="normal"> </span><span class="symbol">(</span><span class="normal">ret </span><span class="symbol">==</span><span class="normal"> <a href="libnice-Timer.html#STUN-USAGE-TIMER-RETURN-SUCCESS:CAPS">STUN_USAGE_TIMER_RETURN_SUCCESS</a></span><span class="symbol">)</span><span class="normal"> </span><span class="cbracket">{</span>
+<span class="normal"> </span><span class="comment">// The refresh succeeded and nothing has to be done, continue polling</span>
+<span class="normal"> </span><span class="keyword">continue</span><span class="symbol">;</span>
+<span class="normal"> </span><span class="cbracket">}</span>
+<span class="normal"> </span><span class="cbracket">}</span><span class="normal"> </span><span class="keyword">else</span><span class="normal"> </span><span class="cbracket">{</span>
+<span class="normal"> </span><span class="comment">// We received a response, read it</span>
+<span class="normal"> </span><span class="function">recv</span><span class="symbol">(</span><span class="normal">socket</span><span class="symbol">,</span><span class="normal"> response</span><span class="symbol">,</span><span class="normal"> </span><span class="keyword">sizeof</span><span class="symbol">(</span><span class="normal">response</span><span class="symbol">));</span>
+<span class="normal"> </span><span class="keyword">break</span><span class="symbol">;</span>
+<span class="normal"> </span><span class="cbracket">}</span>
+<span class="cbracket">}</span>
+
+<span class="comment">// Check if the transaction timed out or not</span>
+<span class="keyword">if</span><span class="normal"> </span><span class="symbol">(</span><span class="normal">ret </span><span class="symbol">==</span><span class="normal"> <a href="libnice-Timer.html#STUN-USAGE-TIMER-RETURN-TIMEOUT:CAPS">STUN_USAGE_TIMER_RETURN_TIMEOUT</a></span><span class="symbol">)</span><span class="normal"> </span><span class="cbracket">{</span>
+<span class="normal"> </span><span class="comment">// do whatever needs to be done in that case</span>
+<span class="cbracket">}</span><span class="normal"> </span><span class="keyword">else</span><span class="normal"> </span><span class="cbracket">{</span>
+<span class="normal"> </span><span class="comment">// Parse the response</span>
+<span class="cbracket">}</span></pre></td>
+ </tr>
+ </tbody>
+ </table>
+</div>
+
+</div>
+<br class="example-break">
+</div>
+<div class="refsect1">
+<a name="libnice-Timer.functions_details"></a><h2>Functions</h2>
+<div class="refsect2">
+<a name="stun-timer-start"></a><h3>stun_timer_start ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+stun_timer_start (<em class="parameter"><code><a class="link" href="libnice-Timer.html#StunTimer" title="StunTimer"><span class="type">StunTimer</span></a> *timer</code></em>,
+ <em class="parameter"><code>unsigned <span class="type">int</span> initial_timeout</code></em>,
+ <em class="parameter"><code>unsigned <span class="type">int</span> max_retransmissions</code></em>);</pre>
+<p>Starts a STUN transaction retransmission timer.
+This should be called as soon as you send the message for the first time on
+a UDP socket.
+The timeout before the next retransmission is set to <em class="parameter"><code>initial_timeout</code></em>
+, then
+each time a packet is retransmited, that timeout will be doubled, until the
+<em class="parameter"><code>max_retransmissions</code></em>
+ retransmissions limit is reached.</p>
+<p>
+To determine the total timeout value, one can use the following equation :
+ </p>
+<pre class="programlisting">
+ total_timeout = initial_timeout * (2^(max_retransmissions + 1) - 1);
+ </pre>
+<p>
+</p>
+<p>See also: <a class="link" href="libnice-Timer.html#STUN-TIMER-DEFAULT-TIMEOUT:CAPS" title="STUN_TIMER_DEFAULT_TIMEOUT"><span class="type">STUN_TIMER_DEFAULT_TIMEOUT</span></a></p>
+<p>See also: <a class="link" href="libnice-Timer.html#STUN-TIMER-DEFAULT-MAX-RETRANSMISSIONS:CAPS" title="STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS"><span class="type">STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS</span></a></p>
+<div class="refsect3">
+<a name="stun-timer-start.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>timer</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-Timer.html#StunTimer" title="StunTimer"><span class="type">StunTimer</span></a> to start</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>initial_timeout</p></td>
+<td class="parameter_description"><p>The initial timeout to use before the first retransmission</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>max_retransmissions</p></td>
+<td class="parameter_description"><p>The maximum number of transmissions before the
+<a class="link" href="libnice-Timer.html#StunTimer" title="StunTimer"><span class="type">StunTimer</span></a> times out</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-timer-start-reliable"></a><h3>stun_timer_start_reliable ()</h3>
+<pre class="programlisting"><span class="returnvalue">void</span>
+stun_timer_start_reliable (<em class="parameter"><code><a class="link" href="libnice-Timer.html#StunTimer" title="StunTimer"><span class="type">StunTimer</span></a> *timer</code></em>,
+ <em class="parameter"><code>unsigned <span class="type">int</span> initial_timeout</code></em>);</pre>
+<p>Starts a STUN transaction retransmission timer for a reliable transport.
+This should be called as soon as you send the message for the first time on
+a TCP socket</p>
+<div class="refsect3">
+<a name="stun-timer-start-reliable.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="parameter_name"><p>timer</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-Timer.html#StunTimer" title="StunTimer"><span class="type">StunTimer</span></a> to start</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+<tr>
+<td class="parameter_name"><p>initial_timeout</p></td>
+<td class="parameter_description"><p>The initial timeout to use before the first retransmission</p></td>
+<td class="parameter_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-timer-refresh"></a><h3>stun_timer_refresh ()</h3>
+<pre class="programlisting"><a class="link" href="libnice-Timer.html#StunUsageTimerReturn" title="enum StunUsageTimerReturn"><span class="returnvalue">StunUsageTimerReturn</span></a>
+stun_timer_refresh (<em class="parameter"><code><a class="link" href="libnice-Timer.html#StunTimer" title="StunTimer"><span class="type">StunTimer</span></a> *timer</code></em>);</pre>
+<p>Updates a STUN transaction retransmission timer.</p>
+<div class="refsect3">
+<a name="stun-timer-refresh.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>timer</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-Timer.html#StunTimer" title="StunTimer"><span class="type">StunTimer</span></a> to refresh</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-timer-refresh.returns"></a><h4>Returns</h4>
+<p> A <a class="link" href="libnice-Timer.html#StunUsageTimerReturn" title="enum StunUsageTimerReturn"><span class="type">StunUsageTimerReturn</span></a> telling you what to do next</p>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="stun-timer-remainder"></a><h3>stun_timer_remainder ()</h3>
+<pre class="programlisting"><span class="returnvalue">unsigned</span>
+stun_timer_remainder (<em class="parameter"><code>const <a class="link" href="libnice-Timer.html#StunTimer" title="StunTimer"><span class="type">StunTimer</span></a> *timer</code></em>);</pre>
+<p>Query the timer on the time left before the next refresh should be done</p>
+<div class="refsect3">
+<a name="stun-timer-remainder.parameters"></a><h4>Parameters</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="150px" class="parameters_name">
+<col class="parameters_description">
+<col width="200px" class="parameters_annotations">
+</colgroup>
+<tbody><tr>
+<td class="parameter_name"><p>timer</p></td>
+<td class="parameter_description"><p>The <a class="link" href="libnice-Timer.html#StunTimer" title="StunTimer"><span class="type">StunTimer</span></a> to query</p></td>
+<td class="parameter_annotations"> </td>
+</tr></tbody>
+</table></div>
+</div>
+<div class="refsect3">
+<a name="stun-timer-remainder.returns"></a><h4>Returns</h4>
+<p> The time remaining for the timer to expire in milliseconds</p>
+</div>
+</div>
+</div>
+<div class="refsect1">
+<a name="libnice-Timer.other_details"></a><h2>Types and Values</h2>
+<div class="refsect2">
+<a name="StunTimer"></a><h3>StunTimer</h3>
+<pre class="programlisting">typedef struct stun_timer_s StunTimer;
+</pre>
+<p>An opaque structure representing a STUN transaction retransmission timer</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="StunUsageTimerReturn"></a><h3>enum StunUsageTimerReturn</h3>
+<p>Return value of <code class="function">stun_usage_timer_refresh()</code> which provides you with status
+information on the timer.</p>
+<div class="refsect3">
+<a name="StunUsageTimerReturn.members"></a><h4>Members</h4>
+<div class="informaltable"><table class="informaltable" width="100%" border="0">
+<colgroup>
+<col width="300px" class="enum_members_name">
+<col class="enum_members_description">
+<col width="200px" class="enum_members_annotations">
+</colgroup>
+<tbody>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-USAGE-TIMER-RETURN-SUCCESS:CAPS"></a>STUN_USAGE_TIMER_RETURN_SUCCESS</p></td>
+<td class="enum_member_description">
+<p>The timer was refreshed successfully
+and there is nothing to be done</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-USAGE-TIMER-RETURN-RETRANSMIT:CAPS"></a>STUN_USAGE_TIMER_RETURN_RETRANSMIT</p></td>
+<td class="enum_member_description">
+<p>The timer expired and the message
+should be retransmitted now.</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+<tr>
+<td class="enum_member_name"><p><a name="STUN-USAGE-TIMER-RETURN-TIMEOUT:CAPS"></a>STUN_USAGE_TIMER_RETURN_TIMEOUT</p></td>
+<td class="enum_member_description">
+<p>The timer expired as well as all the
+retransmissions, the transaction timed out</p>
+</td>
+<td class="enum_member_annotations"> </td>
+</tr>
+</tbody>
+</table></div>
+</div>
+</div>
+<hr>
+<div class="refsect2">
+<a name="STUN-TIMER-DEFAULT-MAX-RETRANSMISSIONS:CAPS"></a><h3>STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS</h3>
+<pre class="programlisting">#define STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS 7
+</pre>
+<p>The default maximum retransmissions allowed before a timer decides to timeout</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="STUN-TIMER-DEFAULT-RELIABLE-TIMEOUT:CAPS"></a><h3>STUN_TIMER_DEFAULT_RELIABLE_TIMEOUT</h3>
+<pre class="programlisting">#define STUN_TIMER_DEFAULT_RELIABLE_TIMEOUT 7900
+</pre>
+<p>The default intial timeout to use for a reliable timer</p>
+</div>
+<hr>
+<div class="refsect2">
+<a name="STUN-TIMER-DEFAULT-TIMEOUT:CAPS"></a><h3>STUN_TIMER_DEFAULT_TIMEOUT</h3>
+<pre class="programlisting">#define STUN_TIMER_DEFAULT_TIMEOUT 200
+</pre>
+<p>The default intial timeout to use for the timer
+RFC recommendds 500, but it's ridiculous, 50ms is known to work in most
+cases as it is also what is used by SIP style VoIP when sending A-Law and
+mu-Law audio, so 200ms should be hyper safe. With an initial timeout
+of 200ms, a default of 7 transmissions, the last timeout will be
+16 * 200ms, and we expect to receive a response from the stun server
+before (1 + 2 + 4 + 8 + 16 + 32 + 16) * 200ms = 15200 ms after the initial
+stun request has been sent.</p>
+</div>
+</div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.29</div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8" standalone="no"?>
+<book xmlns="http://www.devhelp.net/book" title="libnice Reference Manual" link="index.html" author="" name="libnice" version="2" language="c" online="http://nice.freedesktop.org/libnice/index.html">
+ <chapters>
+ <sub name="ICE Library" link="pt01.html">
+ <sub name="" link="ch01.html">
+ <sub name="NiceAgent" link="NiceAgent.html"/>
+ <sub name="NiceAddress" link="libnice-NiceAddress.html"/>
+ <sub name="NiceCandidate" link="NiceCandidate.html"/>
+ </sub>
+ <sub name="Libnice helper functions" link="ch02.html">
+ <sub name="Debug messages" link="libnice-Debug-messages.html"/>
+ <sub name="Network interfaces discovery" link="libnice-Network-interfaces-discovery.html"/>
+ </sub>
+ </sub>
+ <sub name="STUN Library" link="pt02.html">
+ <sub name="" link="ch03.html">
+ <sub name="StunAgent" link="libnice-StunAgent.html"/>
+ <sub name="StunMessage" link="libnice-StunMessage.html"/>
+ <sub name="STUN Constants" link="libnice-STUN-Constants.html"/>
+ </sub>
+ <sub name="STUN usages" link="ch04.html">
+ <sub name="Bind" link="libnice-Bind.html"/>
+ <sub name="ICE" link="libnice-ICE.html"/>
+ <sub name="TURN" link="libnice-TURN.html"/>
+ <sub name="Timer" link="libnice-Timer.html"/>
+ </sub>
+ </sub>
+ <sub name="Pseudo TCP Socket implementation" link="pt03.html">
+ <sub name="" link="ch05.html">
+ <sub name="Pseudo TCP Socket" link="libnice-Pseudo-TCP-Socket.html"/>
+ </sub>
+ </sub>
+ <sub name="Appendices" link="pt04.html">
+ <sub name="API Index" link="api-index-full.html"/>
+ <sub name="Index of deprecated symbols" link="api-index-deprecated.html"/>
+ <sub name="Index of new symbols in 0.0.4" link="ix03.html"/>
+ <sub name="Index of new symbols in 0.0.6" link="ix04.html"/>
+ <sub name="Index of new symbols in 0.0.7" link="ix05.html"/>
+ <sub name="Index of new symbols in 0.0.9" link="ix06.html"/>
+ <sub name="Index of new symbols in 0.0.10" link="ix07.html"/>
+ <sub name="Index of new symbols in 0.0.11" link="ix08.html"/>
+ <sub name="Index of new symbols in 0.1.4" link="ix09.html"/>
+ <sub name="Index of new symbols in 0.1.5" link="ix10.html"/>
+ <sub name="Index of new symbols in 0.1.6" link="ix11.html"/>
+ <sub name="Index of new symbols in 0.1.8" link="ix12.html"/>
+ <sub name="Index of new symbols in 0.1.14" link="ix13.html"/>
+ <sub name="Index of new symbols in 0.1.15" link="ix14.html"/>
+ <sub name="Index of new symbols in 0.1.16" link="ix15.html"/>
+ <sub name="Annotation Glossary" link="annotation-glossary.html"/>
+ </sub>
+ </chapters>
+ <functions>
+ <keyword type="function" name="NiceAgentRecvFunc ()" link="NiceAgent.html#NiceAgentRecvFunc"/>
+ <keyword type="function" name="nice_agent_new ()" link="NiceAgent.html#nice-agent-new"/>
+ <keyword type="function" name="nice_agent_new_reliable ()" link="NiceAgent.html#nice-agent-new-reliable" since="0.0.11"/>
+ <keyword type="function" name="nice_agent_new_full ()" link="NiceAgent.html#nice-agent-new-full" since="0.1.15"/>
+ <keyword type="function" name="nice_agent_add_local_address ()" link="NiceAgent.html#nice-agent-add-local-address"/>
+ <keyword type="function" name="nice_agent_set_port_range ()" link="NiceAgent.html#nice-agent-set-port-range"/>
+ <keyword type="function" name="nice_agent_add_stream ()" link="NiceAgent.html#nice-agent-add-stream"/>
+ <keyword type="function" name="nice_agent_remove_stream ()" link="NiceAgent.html#nice-agent-remove-stream"/>
+ <keyword type="function" name="nice_agent_set_relay_info ()" link="NiceAgent.html#nice-agent-set-relay-info"/>
+ <keyword type="function" name="nice_agent_forget_relays ()" link="NiceAgent.html#nice-agent-forget-relays" since="0.1.6"/>
+ <keyword type="function" name="nice_agent_gather_candidates ()" link="NiceAgent.html#nice-agent-gather-candidates"/>
+ <keyword type="function" name="nice_agent_set_remote_credentials ()" link="NiceAgent.html#nice-agent-set-remote-credentials"/>
+ <keyword type="function" name="nice_agent_get_local_credentials ()" link="NiceAgent.html#nice-agent-get-local-credentials"/>
+ <keyword type="function" name="nice_agent_set_local_credentials ()" link="NiceAgent.html#nice-agent-set-local-credentials"/>
+ <keyword type="function" name="nice_agent_set_remote_candidates ()" link="NiceAgent.html#nice-agent-set-remote-candidates"/>
+ <keyword type="function" name="nice_agent_get_remote_candidates ()" link="NiceAgent.html#nice-agent-get-remote-candidates"/>
+ <keyword type="function" name="nice_agent_get_local_candidates ()" link="NiceAgent.html#nice-agent-get-local-candidates"/>
+ <keyword type="function" name="nice_agent_get_selected_pair ()" link="NiceAgent.html#nice-agent-get-selected-pair"/>
+ <keyword type="function" name="nice_agent_peer_candidate_gathering_done ()" link="NiceAgent.html#nice-agent-peer-candidate-gathering-done" since="0.1.16"/>
+ <keyword type="function" name="nice_agent_send ()" link="NiceAgent.html#nice-agent-send"/>
+ <keyword type="function" name="nice_agent_send_messages_nonblocking ()" link="NiceAgent.html#nice-agent-send-messages-nonblocking" since="0.1.5"/>
+ <keyword type="function" name="nice_agent_recv ()" link="NiceAgent.html#nice-agent-recv" since="0.1.5"/>
+ <keyword type="function" name="nice_agent_recv_messages ()" link="NiceAgent.html#nice-agent-recv-messages" since="0.1.5"/>
+ <keyword type="function" name="nice_agent_recv_nonblocking ()" link="NiceAgent.html#nice-agent-recv-nonblocking" since="0.1.5"/>
+ <keyword type="function" name="nice_agent_recv_messages_nonblocking ()" link="NiceAgent.html#nice-agent-recv-messages-nonblocking" since="0.1.5"/>
+ <keyword type="function" name="nice_agent_attach_recv ()" link="NiceAgent.html#nice-agent-attach-recv"/>
+ <keyword type="function" name="nice_agent_set_selected_pair ()" link="NiceAgent.html#nice-agent-set-selected-pair"/>
+ <keyword type="function" name="nice_agent_set_selected_remote_candidate ()" link="NiceAgent.html#nice-agent-set-selected-remote-candidate"/>
+ <keyword type="function" name="nice_agent_set_stream_tos ()" link="NiceAgent.html#nice-agent-set-stream-tos" since="0.0.9"/>
+ <keyword type="function" name="nice_agent_set_software ()" link="NiceAgent.html#nice-agent-set-software" since="0.0.10"/>
+ <keyword type="function" name="nice_agent_restart ()" link="NiceAgent.html#nice-agent-restart"/>
+ <keyword type="function" name="nice_agent_restart_stream ()" link="NiceAgent.html#nice-agent-restart-stream" since="0.1.6"/>
+ <keyword type="function" name="nice_agent_set_stream_name ()" link="NiceAgent.html#nice-agent-set-stream-name" since="0.1.4"/>
+ <keyword type="function" name="nice_agent_get_stream_name ()" link="NiceAgent.html#nice-agent-get-stream-name" since="0.1.4"/>
+ <keyword type="function" name="nice_agent_get_default_local_candidate ()" link="NiceAgent.html#nice-agent-get-default-local-candidate"/>
+ <keyword type="function" name="nice_agent_generate_local_sdp ()" link="NiceAgent.html#nice-agent-generate-local-sdp" since="0.1.4"/>
+ <keyword type="function" name="nice_agent_generate_local_stream_sdp ()" link="NiceAgent.html#nice-agent-generate-local-stream-sdp" since="0.1.4"/>
+ <keyword type="function" name="nice_agent_generate_local_candidate_sdp ()" link="NiceAgent.html#nice-agent-generate-local-candidate-sdp" since="0.1.4"/>
+ <keyword type="function" name="nice_agent_parse_remote_sdp ()" link="NiceAgent.html#nice-agent-parse-remote-sdp" since="0.1.4"/>
+ <keyword type="function" name="nice_agent_parse_remote_stream_sdp ()" link="NiceAgent.html#nice-agent-parse-remote-stream-sdp" since="0.1.4"/>
+ <keyword type="function" name="nice_agent_parse_remote_candidate_sdp ()" link="NiceAgent.html#nice-agent-parse-remote-candidate-sdp" since="0.1.4"/>
+ <keyword type="function" name="nice_agent_get_io_stream ()" link="NiceAgent.html#nice-agent-get-io-stream" since="0.1.5"/>
+ <keyword type="function" name="nice_agent_get_selected_socket ()" link="NiceAgent.html#nice-agent-get-selected-socket" since="0.1.5"/>
+ <keyword type="function" name="nice_agent_get_component_state ()" link="NiceAgent.html#nice-agent-get-component-state" since="0.1.8"/>
+ <keyword type="function" name="nice_agent_close_async ()" link="NiceAgent.html#nice-agent-close-async" since="0.1.16"/>
+ <keyword type="function" name="nice_component_state_to_string ()" link="NiceAgent.html#nice-component-state-to-string" since="0.1.6"/>
+ <keyword type="struct" name="NiceAgent" link="NiceAgent.html#NiceAgent-struct"/>
+ <keyword type="enum" name="enum NiceComponentState" link="NiceAgent.html#NiceComponentState"/>
+ <keyword type="enum" name="enum NiceComponentType" link="NiceAgent.html#NiceComponentType"/>
+ <keyword type="enum" name="enum NiceProxyType" link="NiceAgent.html#NiceProxyType" since="0.0.4"/>
+ <keyword type="enum" name="enum NiceNominationMode" link="NiceAgent.html#NiceNominationMode" since="0.1.15"/>
+ <keyword type="enum" name="enum NiceCompatibility" link="NiceAgent.html#NiceCompatibility"/>
+ <keyword type="struct" name="NiceInputMessage" link="NiceAgent.html#NiceInputMessage" since="0.1.5"/>
+ <keyword type="struct" name="NiceOutputMessage" link="NiceAgent.html#NiceOutputMessage" since="0.1.5"/>
+ <keyword type="macro" name="NICE_AGENT_MAX_REMOTE_CANDIDATES" link="NiceAgent.html#NICE-AGENT-MAX-REMOTE-CANDIDATES:CAPS"/>
+ <keyword type="enum" name="enum NiceAgentOption" link="NiceAgent.html#NiceAgentOption" since="0.1.15"/>
+ <keyword type="property" name="The “bytestream-tcp” property" link="NiceAgent.html#NiceAgent--bytestream-tcp"/>
+ <keyword type="property" name="The “compatibility” property" link="NiceAgent.html#NiceAgent--compatibility"/>
+ <keyword type="property" name="The “controlling-mode” property" link="NiceAgent.html#NiceAgent--controlling-mode"/>
+ <keyword type="property" name="The “force-relay” property" link="NiceAgent.html#NiceAgent--force-relay"/>
+ <keyword type="property" name="The “full-mode” property" link="NiceAgent.html#NiceAgent--full-mode"/>
+ <keyword type="property" name="The “ice-tcp” property" link="NiceAgent.html#NiceAgent--ice-tcp"/>
+ <keyword type="property" name="The “ice-trickle” property" link="NiceAgent.html#NiceAgent--ice-trickle"/>
+ <keyword type="property" name="The “ice-udp” property" link="NiceAgent.html#NiceAgent--ice-udp"/>
+ <keyword type="property" name="The “keepalive-conncheck” property" link="NiceAgent.html#NiceAgent--keepalive-conncheck"/>
+ <keyword type="property" name="The “main-context” property" link="NiceAgent.html#NiceAgent--main-context"/>
+ <keyword type="property" name="The “max-connectivity-checks” property" link="NiceAgent.html#NiceAgent--max-connectivity-checks"/>
+ <keyword type="property" name="The “nomination-mode” property" link="NiceAgent.html#NiceAgent--nomination-mode"/>
+ <keyword type="property" name="The “proxy-ip” property" link="NiceAgent.html#NiceAgent--proxy-ip"/>
+ <keyword type="property" name="The “proxy-password” property" link="NiceAgent.html#NiceAgent--proxy-password"/>
+ <keyword type="property" name="The “proxy-port” property" link="NiceAgent.html#NiceAgent--proxy-port"/>
+ <keyword type="property" name="The “proxy-type” property" link="NiceAgent.html#NiceAgent--proxy-type"/>
+ <keyword type="property" name="The “proxy-username” property" link="NiceAgent.html#NiceAgent--proxy-username"/>
+ <keyword type="property" name="The “reliable” property" link="NiceAgent.html#NiceAgent--reliable"/>
+ <keyword type="property" name="The “stun-initial-timeout” property" link="NiceAgent.html#NiceAgent--stun-initial-timeout"/>
+ <keyword type="property" name="The “stun-max-retransmissions” property" link="NiceAgent.html#NiceAgent--stun-max-retransmissions"/>
+ <keyword type="property" name="The “stun-pacing-timer” property" link="NiceAgent.html#NiceAgent--stun-pacing-timer"/>
+ <keyword type="property" name="The “stun-reliable-timeout” property" link="NiceAgent.html#NiceAgent--stun-reliable-timeout"/>
+ <keyword type="property" name="The “stun-server” property" link="NiceAgent.html#NiceAgent--stun-server"/>
+ <keyword type="property" name="The “stun-server-port” property" link="NiceAgent.html#NiceAgent--stun-server-port"/>
+ <keyword type="property" name="The “support-renomination” property" link="NiceAgent.html#NiceAgent--support-renomination"/>
+ <keyword type="property" name="The “upnp” property" link="NiceAgent.html#NiceAgent--upnp"/>
+ <keyword type="property" name="The “upnp-timeout” property" link="NiceAgent.html#NiceAgent--upnp-timeout"/>
+ <keyword type="signal" name="The “candidate-gathering-done” signal" link="NiceAgent.html#NiceAgent-candidate-gathering-done"/>
+ <keyword type="signal" name="The “component-state-changed” signal" link="NiceAgent.html#NiceAgent-component-state-changed"/>
+ <keyword type="signal" name="The “initial-binding-request-received” signal" link="NiceAgent.html#NiceAgent-initial-binding-request-received"/>
+ <keyword type="signal" name="The “new-candidate” signal" link="NiceAgent.html#NiceAgent-new-candidate"/>
+ <keyword type="signal" name="The “new-candidate-full” signal" link="NiceAgent.html#NiceAgent-new-candidate-full"/>
+ <keyword type="signal" name="The “new-remote-candidate” signal" link="NiceAgent.html#NiceAgent-new-remote-candidate"/>
+ <keyword type="signal" name="The “new-remote-candidate-full” signal" link="NiceAgent.html#NiceAgent-new-remote-candidate-full"/>
+ <keyword type="signal" name="The “new-selected-pair” signal" link="NiceAgent.html#NiceAgent-new-selected-pair"/>
+ <keyword type="signal" name="The “new-selected-pair-full” signal" link="NiceAgent.html#NiceAgent-new-selected-pair-full"/>
+ <keyword type="signal" name="The “reliable-transport-writable” signal" link="NiceAgent.html#NiceAgent-reliable-transport-writable"/>
+ <keyword type="signal" name="The “streams-removed” signal" link="NiceAgent.html#NiceAgent-streams-removed"/>
+ <keyword type="function" name="nice_address_init ()" link="libnice-NiceAddress.html#nice-address-init"/>
+ <keyword type="function" name="nice_address_new ()" link="libnice-NiceAddress.html#nice-address-new"/>
+ <keyword type="function" name="nice_address_free ()" link="libnice-NiceAddress.html#nice-address-free"/>
+ <keyword type="function" name="nice_address_dup ()" link="libnice-NiceAddress.html#nice-address-dup"/>
+ <keyword type="function" name="nice_address_set_ipv4 ()" link="libnice-NiceAddress.html#nice-address-set-ipv4"/>
+ <keyword type="function" name="nice_address_set_ipv6 ()" link="libnice-NiceAddress.html#nice-address-set-ipv6"/>
+ <keyword type="function" name="nice_address_set_port ()" link="libnice-NiceAddress.html#nice-address-set-port"/>
+ <keyword type="function" name="nice_address_get_port ()" link="libnice-NiceAddress.html#nice-address-get-port"/>
+ <keyword type="function" name="nice_address_set_from_string ()" link="libnice-NiceAddress.html#nice-address-set-from-string"/>
+ <keyword type="function" name="nice_address_set_from_sockaddr ()" link="libnice-NiceAddress.html#nice-address-set-from-sockaddr"/>
+ <keyword type="function" name="nice_address_copy_to_sockaddr ()" link="libnice-NiceAddress.html#nice-address-copy-to-sockaddr"/>
+ <keyword type="function" name="nice_address_equal ()" link="libnice-NiceAddress.html#nice-address-equal"/>
+ <keyword type="function" name="nice_address_equal_no_port ()" link="libnice-NiceAddress.html#nice-address-equal-no-port" since="0.1.8"/>
+ <keyword type="function" name="nice_address_to_string ()" link="libnice-NiceAddress.html#nice-address-to-string"/>
+ <keyword type="function" name="nice_address_is_private ()" link="libnice-NiceAddress.html#nice-address-is-private"/>
+ <keyword type="function" name="nice_address_is_valid ()" link="libnice-NiceAddress.html#nice-address-is-valid"/>
+ <keyword type="function" name="nice_address_ip_version ()" link="libnice-NiceAddress.html#nice-address-ip-version"/>
+ <keyword type="struct" name="NiceAddress" link="libnice-NiceAddress.html#NiceAddress"/>
+ <keyword type="macro" name="NICE_ADDRESS_STRING_LEN" link="libnice-NiceAddress.html#NICE-ADDRESS-STRING-LEN:CAPS"/>
+ <keyword type="function" name="nice_candidate_new ()" link="NiceCandidate.html#nice-candidate-new"/>
+ <keyword type="function" name="nice_candidate_free ()" link="NiceCandidate.html#nice-candidate-free"/>
+ <keyword type="function" name="nice_candidate_copy ()" link="NiceCandidate.html#nice-candidate-copy"/>
+ <keyword type="function" name="nice_candidate_equal_target ()" link="NiceCandidate.html#nice-candidate-equal-target" since="0.1.15"/>
+ <keyword type="struct" name="struct NiceCandidate" link="NiceCandidate.html#NiceCandidate-struct"/>
+ <keyword type="enum" name="enum NiceCandidateType" link="NiceCandidate.html#NiceCandidateType"/>
+ <keyword type="enum" name="enum NiceCandidateTransport" link="NiceCandidate.html#NiceCandidateTransport"/>
+ <keyword type="struct" name="struct TurnServer" link="NiceCandidate.html#TurnServer"/>
+ <keyword type="enum" name="enum NiceRelayType" link="NiceCandidate.html#NiceRelayType"/>
+ <keyword type="macro" name="NICE_CANDIDATE_MAX_FOUNDATION" link="NiceCandidate.html#NICE-CANDIDATE-MAX-FOUNDATION:CAPS"/>
+ <keyword type="function" name="nice_debug_enable ()" link="libnice-Debug-messages.html#nice-debug-enable"/>
+ <keyword type="function" name="nice_debug_disable ()" link="libnice-Debug-messages.html#nice-debug-disable"/>
+ <keyword type="function" name="nice_interfaces_get_ip_for_interface ()" link="libnice-Network-interfaces-discovery.html#nice-interfaces-get-ip-for-interface"/>
+ <keyword type="function" name="nice_interfaces_get_local_interfaces ()" link="libnice-Network-interfaces-discovery.html#nice-interfaces-get-local-interfaces"/>
+ <keyword type="function" name="nice_interfaces_get_local_ips ()" link="libnice-Network-interfaces-discovery.html#nice-interfaces-get-local-ips"/>
+ <keyword type="function" name="StunMessageIntegrityValidate ()" link="libnice-StunAgent.html#StunMessageIntegrityValidate"/>
+ <keyword type="function" name="StunDebugHandler ()" link="libnice-StunAgent.html#StunDebugHandler"/>
+ <keyword type="function" name="stun_agent_init ()" link="libnice-StunAgent.html#stun-agent-init"/>
+ <keyword type="function" name="stun_agent_validate ()" link="libnice-StunAgent.html#stun-agent-validate"/>
+ <keyword type="function" name="stun_agent_default_validater ()" link="libnice-StunAgent.html#stun-agent-default-validater"/>
+ <keyword type="function" name="stun_agent_init_request ()" link="libnice-StunAgent.html#stun-agent-init-request"/>
+ <keyword type="function" name="stun_agent_init_indication ()" link="libnice-StunAgent.html#stun-agent-init-indication"/>
+ <keyword type="function" name="stun_agent_init_response ()" link="libnice-StunAgent.html#stun-agent-init-response"/>
+ <keyword type="function" name="stun_agent_init_error ()" link="libnice-StunAgent.html#stun-agent-init-error"/>
+ <keyword type="function" name="stun_agent_build_unknown_attributes_error ()" link="libnice-StunAgent.html#stun-agent-build-unknown-attributes-error"/>
+ <keyword type="function" name="stun_agent_finish_message ()" link="libnice-StunAgent.html#stun-agent-finish-message"/>
+ <keyword type="function" name="stun_agent_forget_transaction ()" link="libnice-StunAgent.html#stun-agent-forget-transaction" since="0.0.6"/>
+ <keyword type="function" name="stun_agent_set_software ()" link="libnice-StunAgent.html#stun-agent-set-software" since="0.0.10"/>
+ <keyword type="function" name="stun_debug_enable ()" link="libnice-StunAgent.html#stun-debug-enable"/>
+ <keyword type="function" name="stun_debug_disable ()" link="libnice-StunAgent.html#stun-debug-disable"/>
+ <keyword type="function" name="stun_set_debug_handler ()" link="libnice-StunAgent.html#stun-set-debug-handler"/>
+ <keyword type="typedef" name="StunAgent" link="libnice-StunAgent.html#StunAgent"/>
+ <keyword type="enum" name="enum StunCompatibility" link="libnice-StunAgent.html#StunCompatibility"/>
+ <keyword type="enum" name="enum StunAgentUsageFlags" link="libnice-StunAgent.html#StunAgentUsageFlags"/>
+ <keyword type="enum" name="enum StunValidationStatus" link="libnice-StunAgent.html#StunValidationStatus"/>
+ <keyword type="struct" name="StunDefaultValidaterData" link="libnice-StunAgent.html#StunDefaultValidaterData"/>
+ <keyword type="function" name="stun_message_init ()" link="libnice-StunMessage.html#stun-message-init"/>
+ <keyword type="function" name="stun_message_length ()" link="libnice-StunMessage.html#stun-message-length"/>
+ <keyword type="function" name="stun_message_find ()" link="libnice-StunMessage.html#stun-message-find"/>
+ <keyword type="function" name="stun_message_find_flag ()" link="libnice-StunMessage.html#stun-message-find-flag"/>
+ <keyword type="function" name="stun_message_find32 ()" link="libnice-StunMessage.html#stun-message-find32"/>
+ <keyword type="function" name="stun_message_find64 ()" link="libnice-StunMessage.html#stun-message-find64"/>
+ <keyword type="function" name="stun_message_find_string ()" link="libnice-StunMessage.html#stun-message-find-string"/>
+ <keyword type="function" name="stun_message_find_addr ()" link="libnice-StunMessage.html#stun-message-find-addr"/>
+ <keyword type="function" name="stun_message_find_xor_addr ()" link="libnice-StunMessage.html#stun-message-find-xor-addr"/>
+ <keyword type="function" name="stun_message_find_xor_addr_full ()" link="libnice-StunMessage.html#stun-message-find-xor-addr-full"/>
+ <keyword type="function" name="stun_message_find_error ()" link="libnice-StunMessage.html#stun-message-find-error"/>
+ <keyword type="function" name="stun_message_append ()" link="libnice-StunMessage.html#stun-message-append"/>
+ <keyword type="function" name="stun_message_append_bytes ()" link="libnice-StunMessage.html#stun-message-append-bytes"/>
+ <keyword type="function" name="stun_message_append_flag ()" link="libnice-StunMessage.html#stun-message-append-flag"/>
+ <keyword type="function" name="stun_message_append32 ()" link="libnice-StunMessage.html#stun-message-append32"/>
+ <keyword type="function" name="stun_message_append64 ()" link="libnice-StunMessage.html#stun-message-append64"/>
+ <keyword type="function" name="stun_message_append_string ()" link="libnice-StunMessage.html#stun-message-append-string"/>
+ <keyword type="function" name="stun_message_append_addr ()" link="libnice-StunMessage.html#stun-message-append-addr"/>
+ <keyword type="function" name="stun_message_append_xor_addr ()" link="libnice-StunMessage.html#stun-message-append-xor-addr"/>
+ <keyword type="function" name="stun_message_append_xor_addr_full ()" link="libnice-StunMessage.html#stun-message-append-xor-addr-full"/>
+ <keyword type="function" name="stun_message_append_error ()" link="libnice-StunMessage.html#stun-message-append-error"/>
+ <keyword type="function" name="stun_message_validate_buffer_length ()" link="libnice-StunMessage.html#stun-message-validate-buffer-length"/>
+ <keyword type="function" name="stun_message_validate_buffer_length_fast ()" link="libnice-StunMessage.html#stun-message-validate-buffer-length-fast" since="0.1.5"/>
+ <keyword type="function" name="stun_message_id ()" link="libnice-StunMessage.html#stun-message-id"/>
+ <keyword type="function" name="stun_message_get_class ()" link="libnice-StunMessage.html#stun-message-get-class"/>
+ <keyword type="function" name="stun_message_get_method ()" link="libnice-StunMessage.html#stun-message-get-method"/>
+ <keyword type="function" name="stun_message_has_attribute ()" link="libnice-StunMessage.html#stun-message-has-attribute"/>
+ <keyword type="function" name="stun_message_has_cookie ()" link="libnice-StunMessage.html#stun-message-has-cookie"/>
+ <keyword type="function" name="stun_optional ()" link="libnice-StunMessage.html#stun-optional"/>
+ <keyword type="function" name="stun_strerror ()" link="libnice-StunMessage.html#stun-strerror"/>
+ <keyword type="struct" name="struct StunMessage" link="libnice-StunMessage.html#StunMessage"/>
+ <keyword type="enum" name="enum StunClass" link="libnice-StunMessage.html#StunClass"/>
+ <keyword type="enum" name="enum StunMethod" link="libnice-StunMessage.html#StunMethod"/>
+ <keyword type="enum" name="enum StunAttribute" link="libnice-StunMessage.html#StunAttribute"/>
+ <keyword type="typedef" name="StunTransactionId" link="libnice-StunMessage.html#StunTransactionId"/>
+ <keyword type="enum" name="enum StunError" link="libnice-StunMessage.html#StunError"/>
+ <keyword type="enum" name="enum StunMessageReturn" link="libnice-StunMessage.html#StunMessageReturn"/>
+ <keyword type="macro" name="STUN_MESSAGE_BUFFER_INCOMPLETE" link="libnice-StunMessage.html#STUN-MESSAGE-BUFFER-INCOMPLETE:CAPS"/>
+ <keyword type="macro" name="STUN_MESSAGE_BUFFER_INVALID" link="libnice-StunMessage.html#STUN-MESSAGE-BUFFER-INVALID:CAPS"/>
+ <keyword type="struct" name="StunInputVector" link="libnice-StunMessage.html#StunInputVector" since="0.1.5"/>
+ <keyword type="macro" name="STUN_AGENT_MAX_SAVED_IDS" link="libnice-STUN-Constants.html#STUN-AGENT-MAX-SAVED-IDS:CAPS"/>
+ <keyword type="macro" name="STUN_AGENT_MAX_UNKNOWN_ATTRIBUTES" link="libnice-STUN-Constants.html#STUN-AGENT-MAX-UNKNOWN-ATTRIBUTES:CAPS"/>
+ <keyword type="macro" name="STUN_ATTRIBUTE_HEADER_LENGTH" link="libnice-STUN-Constants.html#STUN-ATTRIBUTE-HEADER-LENGTH:CAPS"/>
+ <keyword type="macro" name="STUN_ATTRIBUTE_LENGTH_LEN" link="libnice-STUN-Constants.html#STUN-ATTRIBUTE-LENGTH-LEN:CAPS"/>
+ <keyword type="macro" name="STUN_ATTRIBUTE_LENGTH_POS" link="libnice-STUN-Constants.html#STUN-ATTRIBUTE-LENGTH-POS:CAPS"/>
+ <keyword type="macro" name="STUN_ATTRIBUTE_TYPE_LEN" link="libnice-STUN-Constants.html#STUN-ATTRIBUTE-TYPE-LEN:CAPS"/>
+ <keyword type="macro" name="STUN_ATTRIBUTE_TYPE_POS" link="libnice-STUN-Constants.html#STUN-ATTRIBUTE-TYPE-POS:CAPS"/>
+ <keyword type="macro" name="STUN_ATTRIBUTE_VALUE_POS" link="libnice-STUN-Constants.html#STUN-ATTRIBUTE-VALUE-POS:CAPS"/>
+ <keyword type="macro" name="STUN_ID_LEN" link="libnice-STUN-Constants.html#STUN-ID-LEN:CAPS"/>
+ <keyword type="macro" name="STUN_MAGIC_COOKIE" link="libnice-STUN-Constants.html#STUN-MAGIC-COOKIE:CAPS"/>
+ <keyword type="macro" name="STUN_MAX_MESSAGE_SIZE" link="libnice-STUN-Constants.html#STUN-MAX-MESSAGE-SIZE:CAPS"/>
+ <keyword type="macro" name="STUN_MAX_MESSAGE_SIZE_IPV4" link="libnice-STUN-Constants.html#STUN-MAX-MESSAGE-SIZE-IPV4:CAPS"/>
+ <keyword type="macro" name="STUN_MAX_MESSAGE_SIZE_IPV6" link="libnice-STUN-Constants.html#STUN-MAX-MESSAGE-SIZE-IPV6:CAPS"/>
+ <keyword type="macro" name="STUN_MESSAGE_ATTRIBUTES_POS" link="libnice-STUN-Constants.html#STUN-MESSAGE-ATTRIBUTES-POS:CAPS"/>
+ <keyword type="macro" name="STUN_MESSAGE_HEADER_LENGTH" link="libnice-STUN-Constants.html#STUN-MESSAGE-HEADER-LENGTH:CAPS"/>
+ <keyword type="macro" name="STUN_MESSAGE_LENGTH_LEN" link="libnice-STUN-Constants.html#STUN-MESSAGE-LENGTH-LEN:CAPS"/>
+ <keyword type="macro" name="STUN_MESSAGE_LENGTH_POS" link="libnice-STUN-Constants.html#STUN-MESSAGE-LENGTH-POS:CAPS"/>
+ <keyword type="macro" name="STUN_MESSAGE_TRANS_ID_LEN" link="libnice-STUN-Constants.html#STUN-MESSAGE-TRANS-ID-LEN:CAPS"/>
+ <keyword type="macro" name="STUN_MESSAGE_TRANS_ID_POS" link="libnice-STUN-Constants.html#STUN-MESSAGE-TRANS-ID-POS:CAPS"/>
+ <keyword type="macro" name="STUN_MESSAGE_TYPE_LEN" link="libnice-STUN-Constants.html#STUN-MESSAGE-TYPE-LEN:CAPS"/>
+ <keyword type="macro" name="STUN_MESSAGE_TYPE_POS" link="libnice-STUN-Constants.html#STUN-MESSAGE-TYPE-POS:CAPS"/>
+ <keyword type="macro" name="TURN_MAGIC_COOKIE" link="libnice-STUN-Constants.html#TURN-MAGIC-COOKIE:CAPS"/>
+ <keyword type="function" name="stun_usage_bind_create ()" link="libnice-Bind.html#stun-usage-bind-create"/>
+ <keyword type="function" name="stun_usage_bind_process ()" link="libnice-Bind.html#stun-usage-bind-process"/>
+ <keyword type="function" name="stun_usage_bind_keepalive ()" link="libnice-Bind.html#stun-usage-bind-keepalive"/>
+ <keyword type="function" name="stun_usage_bind_run ()" link="libnice-Bind.html#stun-usage-bind-run"/>
+ <keyword type="enum" name="enum StunUsageBindReturn" link="libnice-Bind.html#StunUsageBindReturn"/>
+ <keyword type="function" name="stun_usage_ice_conncheck_create ()" link="libnice-ICE.html#stun-usage-ice-conncheck-create"/>
+ <keyword type="function" name="stun_usage_ice_conncheck_process ()" link="libnice-ICE.html#stun-usage-ice-conncheck-process"/>
+ <keyword type="function" name="stun_usage_ice_conncheck_create_reply ()" link="libnice-ICE.html#stun-usage-ice-conncheck-create-reply"/>
+ <keyword type="function" name="stun_usage_ice_conncheck_priority ()" link="libnice-ICE.html#stun-usage-ice-conncheck-priority"/>
+ <keyword type="function" name="stun_usage_ice_conncheck_use_candidate ()" link="libnice-ICE.html#stun-usage-ice-conncheck-use-candidate"/>
+ <keyword type="enum" name="enum StunUsageIceCompatibility" link="libnice-ICE.html#StunUsageIceCompatibility"/>
+ <keyword type="enum" name="enum StunUsageIceReturn" link="libnice-ICE.html#StunUsageIceReturn"/>
+ <keyword type="function" name="stun_usage_turn_create ()" link="libnice-TURN.html#stun-usage-turn-create"/>
+ <keyword type="function" name="stun_usage_turn_create_refresh ()" link="libnice-TURN.html#stun-usage-turn-create-refresh"/>
+ <keyword type="function" name="stun_usage_turn_process ()" link="libnice-TURN.html#stun-usage-turn-process"/>
+ <keyword type="function" name="stun_usage_turn_refresh_process ()" link="libnice-TURN.html#stun-usage-turn-refresh-process"/>
+ <keyword type="function" name="stun_usage_turn_create_permission ()" link="libnice-TURN.html#stun-usage-turn-create-permission"/>
+ <keyword type="enum" name="enum StunUsageTurnCompatibility" link="libnice-TURN.html#StunUsageTurnCompatibility"/>
+ <keyword type="enum" name="enum StunUsageTurnRequestPorts" link="libnice-TURN.html#StunUsageTurnRequestPorts"/>
+ <keyword type="enum" name="enum StunUsageTurnReturn" link="libnice-TURN.html#StunUsageTurnReturn"/>
+ <keyword type="function" name="stun_timer_start ()" link="libnice-Timer.html#stun-timer-start"/>
+ <keyword type="function" name="stun_timer_start_reliable ()" link="libnice-Timer.html#stun-timer-start-reliable"/>
+ <keyword type="function" name="stun_timer_refresh ()" link="libnice-Timer.html#stun-timer-refresh"/>
+ <keyword type="function" name="stun_timer_remainder ()" link="libnice-Timer.html#stun-timer-remainder"/>
+ <keyword type="typedef" name="StunTimer" link="libnice-Timer.html#StunTimer"/>
+ <keyword type="enum" name="enum StunUsageTimerReturn" link="libnice-Timer.html#StunUsageTimerReturn"/>
+ <keyword type="macro" name="STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS" link="libnice-Timer.html#STUN-TIMER-DEFAULT-MAX-RETRANSMISSIONS:CAPS"/>
+ <keyword type="macro" name="STUN_TIMER_DEFAULT_RELIABLE_TIMEOUT" link="libnice-Timer.html#STUN-TIMER-DEFAULT-RELIABLE-TIMEOUT:CAPS"/>
+ <keyword type="macro" name="STUN_TIMER_DEFAULT_TIMEOUT" link="libnice-Timer.html#STUN-TIMER-DEFAULT-TIMEOUT:CAPS"/>
+ <keyword type="function" name="pseudo_tcp_socket_new ()" link="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-new" since="0.0.11"/>
+ <keyword type="function" name="pseudo_tcp_socket_connect ()" link="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-connect" since="0.0.11"/>
+ <keyword type="function" name="pseudo_tcp_socket_recv ()" link="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-recv" since="0.0.11"/>
+ <keyword type="function" name="pseudo_tcp_socket_send ()" link="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-send" since="0.0.11"/>
+ <keyword type="function" name="pseudo_tcp_socket_close ()" link="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-close" since="0.0.11"/>
+ <keyword type="function" name="pseudo_tcp_socket_shutdown ()" link="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-shutdown" since="0.1.8"/>
+ <keyword type="function" name="pseudo_tcp_socket_is_closed ()" link="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-is-closed" since="0.1.8"/>
+ <keyword type="function" name="pseudo_tcp_socket_is_closed_remotely ()" link="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-is-closed-remotely" since="0.1.8"/>
+ <keyword type="function" name="pseudo_tcp_socket_get_error ()" link="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-get-error" since="0.0.11"/>
+ <keyword type="function" name="pseudo_tcp_socket_get_next_clock ()" link="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-get-next-clock" since="0.0.11"/>
+ <keyword type="function" name="pseudo_tcp_socket_notify_clock ()" link="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-notify-clock" since="0.0.11"/>
+ <keyword type="function" name="pseudo_tcp_socket_notify_mtu ()" link="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-notify-mtu" since="0.0.11"/>
+ <keyword type="function" name="pseudo_tcp_socket_notify_packet ()" link="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-notify-packet" since="0.0.11"/>
+ <keyword type="function" name="pseudo_tcp_set_debug_level ()" link="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-set-debug-level" since="0.0.11"/>
+ <keyword type="function" name="pseudo_tcp_socket_get_available_bytes ()" link="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-get-available-bytes" since="0.1.5"/>
+ <keyword type="function" name="pseudo_tcp_socket_can_send ()" link="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-can-send" since="0.1.5"/>
+ <keyword type="function" name="pseudo_tcp_socket_get_available_send_space ()" link="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-get-available-send-space" since="0.1.5"/>
+ <keyword type="function" name="pseudo_tcp_socket_notify_message ()" link="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-notify-message" since="0.1.5"/>
+ <keyword type="function" name="pseudo_tcp_socket_set_time ()" link="libnice-Pseudo-TCP-Socket.html#pseudo-tcp-socket-set-time" since="0.1.8"/>
+ <keyword type="struct" name="PseudoTcpSocket" link="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket-struct"/>
+ <keyword type="enum" name="enum PseudoTcpState" link="libnice-Pseudo-TCP-Socket.html#PseudoTcpState" since="0.0.11"/>
+ <keyword type="enum" name="enum PseudoTcpWriteResult" link="libnice-Pseudo-TCP-Socket.html#PseudoTcpWriteResult" since="0.0.11"/>
+ <keyword type="struct" name="PseudoTcpCallbacks" link="libnice-Pseudo-TCP-Socket.html#PseudoTcpCallbacks" since="0.0.11"/>
+ <keyword type="enum" name="enum PseudoTcpDebugLevel" link="libnice-Pseudo-TCP-Socket.html#PseudoTcpDebugLevel" since="0.0.11"/>
+ <keyword type="enum" name="enum PseudoTcpShutdown" link="libnice-Pseudo-TCP-Socket.html#PseudoTcpShutdown" since="0.1.8"/>
+ <keyword type="property" name="The “ack-delay” property" link="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket--ack-delay"/>
+ <keyword type="property" name="The “callbacks” property" link="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket--callbacks"/>
+ <keyword type="property" name="The “conversation” property" link="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket--conversation"/>
+ <keyword type="property" name="The “no-delay” property" link="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket--no-delay"/>
+ <keyword type="property" name="The “rcv-buf” property" link="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket--rcv-buf"/>
+ <keyword type="property" name="The “snd-buf” property" link="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket--snd-buf"/>
+ <keyword type="property" name="The “state” property" link="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket--state"/>
+ <keyword type="property" name="The “support-fin-ack” property" link="libnice-Pseudo-TCP-Socket.html#PseudoTcpSocket--support-fin-ack"/>
+ <keyword type="constant" name="NICE_COMPONENT_STATE_DISCONNECTED" link="NiceAgent.html#NICE-COMPONENT-STATE-DISCONNECTED:CAPS"/>
+ <keyword type="constant" name="NICE_COMPONENT_STATE_GATHERING" link="NiceAgent.html#NICE-COMPONENT-STATE-GATHERING:CAPS"/>
+ <keyword type="constant" name="NICE_COMPONENT_STATE_CONNECTING" link="NiceAgent.html#NICE-COMPONENT-STATE-CONNECTING:CAPS"/>
+ <keyword type="constant" name="NICE_COMPONENT_STATE_CONNECTED" link="NiceAgent.html#NICE-COMPONENT-STATE-CONNECTED:CAPS"/>
+ <keyword type="constant" name="NICE_COMPONENT_STATE_READY" link="NiceAgent.html#NICE-COMPONENT-STATE-READY:CAPS"/>
+ <keyword type="constant" name="NICE_COMPONENT_STATE_FAILED" link="NiceAgent.html#NICE-COMPONENT-STATE-FAILED:CAPS"/>
+ <keyword type="constant" name="NICE_COMPONENT_STATE_LAST" link="NiceAgent.html#NICE-COMPONENT-STATE-LAST:CAPS"/>
+ <keyword type="constant" name="NICE_COMPONENT_TYPE_RTP" link="NiceAgent.html#NICE-COMPONENT-TYPE-RTP:CAPS"/>
+ <keyword type="constant" name="NICE_COMPONENT_TYPE_RTCP" link="NiceAgent.html#NICE-COMPONENT-TYPE-RTCP:CAPS"/>
+ <keyword type="constant" name="NICE_PROXY_TYPE_NONE" link="NiceAgent.html#NICE-PROXY-TYPE-NONE:CAPS"/>
+ <keyword type="constant" name="NICE_PROXY_TYPE_SOCKS5" link="NiceAgent.html#NICE-PROXY-TYPE-SOCKS5:CAPS"/>
+ <keyword type="constant" name="NICE_PROXY_TYPE_HTTP" link="NiceAgent.html#NICE-PROXY-TYPE-HTTP:CAPS"/>
+ <keyword type="constant" name="NICE_PROXY_TYPE_LAST" link="NiceAgent.html#NICE-PROXY-TYPE-LAST:CAPS"/>
+ <keyword type="constant" name="NICE_NOMINATION_MODE_REGULAR" link="NiceAgent.html#NICE-NOMINATION-MODE-REGULAR:CAPS"/>
+ <keyword type="constant" name="NICE_NOMINATION_MODE_AGGRESSIVE" link="NiceAgent.html#NICE-NOMINATION-MODE-AGGRESSIVE:CAPS"/>
+ <keyword type="constant" name="NICE_COMPATIBILITY_RFC5245" link="NiceAgent.html#NICE-COMPATIBILITY-RFC5245:CAPS"/>
+ <keyword type="constant" name="NICE_COMPATIBILITY_DRAFT19" link="NiceAgent.html#NICE-COMPATIBILITY-DRAFT19:CAPS"/>
+ <keyword type="constant" name="NICE_COMPATIBILITY_GOOGLE" link="NiceAgent.html#NICE-COMPATIBILITY-GOOGLE:CAPS"/>
+ <keyword type="constant" name="NICE_COMPATIBILITY_MSN" link="NiceAgent.html#NICE-COMPATIBILITY-MSN:CAPS"/>
+ <keyword type="constant" name="NICE_COMPATIBILITY_WLM2009" link="NiceAgent.html#NICE-COMPATIBILITY-WLM2009:CAPS"/>
+ <keyword type="constant" name="NICE_COMPATIBILITY_OC2007" link="NiceAgent.html#NICE-COMPATIBILITY-OC2007:CAPS"/>
+ <keyword type="constant" name="NICE_COMPATIBILITY_OC2007R2" link="NiceAgent.html#NICE-COMPATIBILITY-OC2007R2:CAPS"/>
+ <keyword type="constant" name="NICE_COMPATIBILITY_LAST" link="NiceAgent.html#NICE-COMPATIBILITY-LAST:CAPS"/>
+ <keyword type="constant" name="NICE_AGENT_OPTION_REGULAR_NOMINATION" link="NiceAgent.html#NICE-AGENT-OPTION-REGULAR-NOMINATION:CAPS"/>
+ <keyword type="constant" name="NICE_AGENT_OPTION_RELIABLE" link="NiceAgent.html#NICE-AGENT-OPTION-RELIABLE:CAPS"/>
+ <keyword type="constant" name="NICE_AGENT_OPTION_LITE_MODE" link="NiceAgent.html#NICE-AGENT-OPTION-LITE-MODE:CAPS"/>
+ <keyword type="constant" name="NICE_AGENT_OPTION_ICE_TRICKLE" link="NiceAgent.html#NICE-AGENT-OPTION-ICE-TRICKLE:CAPS"/>
+ <keyword type="constant" name="NICE_AGENT_OPTION_SUPPORT_RENOMINATION" link="NiceAgent.html#NICE-AGENT-OPTION-SUPPORT-RENOMINATION:CAPS"/>
+ <keyword type="constant" name="NICE_CANDIDATE_TYPE_HOST" link="NiceCandidate.html#NICE-CANDIDATE-TYPE-HOST:CAPS"/>
+ <keyword type="constant" name="NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE" link="NiceCandidate.html#NICE-CANDIDATE-TYPE-SERVER-REFLEXIVE:CAPS"/>
+ <keyword type="constant" name="NICE_CANDIDATE_TYPE_PEER_REFLEXIVE" link="NiceCandidate.html#NICE-CANDIDATE-TYPE-PEER-REFLEXIVE:CAPS"/>
+ <keyword type="constant" name="NICE_CANDIDATE_TYPE_RELAYED" link="NiceCandidate.html#NICE-CANDIDATE-TYPE-RELAYED:CAPS"/>
+ <keyword type="constant" name="NICE_CANDIDATE_TRANSPORT_UDP" link="NiceCandidate.html#NICE-CANDIDATE-TRANSPORT-UDP:CAPS"/>
+ <keyword type="constant" name="NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE" link="NiceCandidate.html#NICE-CANDIDATE-TRANSPORT-TCP-ACTIVE:CAPS"/>
+ <keyword type="constant" name="NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE" link="NiceCandidate.html#NICE-CANDIDATE-TRANSPORT-TCP-PASSIVE:CAPS"/>
+ <keyword type="constant" name="NICE_CANDIDATE_TRANSPORT_TCP_SO" link="NiceCandidate.html#NICE-CANDIDATE-TRANSPORT-TCP-SO:CAPS"/>
+ <keyword type="constant" name="NICE_RELAY_TYPE_TURN_UDP" link="NiceCandidate.html#NICE-RELAY-TYPE-TURN-UDP:CAPS"/>
+ <keyword type="constant" name="NICE_RELAY_TYPE_TURN_TCP" link="NiceCandidate.html#NICE-RELAY-TYPE-TURN-TCP:CAPS"/>
+ <keyword type="constant" name="NICE_RELAY_TYPE_TURN_TLS" link="NiceCandidate.html#NICE-RELAY-TYPE-TURN-TLS:CAPS"/>
+ <keyword type="constant" name="STUN_COMPATIBILITY_RFC3489" link="libnice-StunAgent.html#STUN-COMPATIBILITY-RFC3489:CAPS"/>
+ <keyword type="constant" name="STUN_COMPATIBILITY_RFC5389" link="libnice-StunAgent.html#STUN-COMPATIBILITY-RFC5389:CAPS"/>
+ <keyword type="constant" name="STUN_COMPATIBILITY_MSICE2" link="libnice-StunAgent.html#STUN-COMPATIBILITY-MSICE2:CAPS"/>
+ <keyword type="constant" name="STUN_COMPATIBILITY_OC2007" link="libnice-StunAgent.html#STUN-COMPATIBILITY-OC2007:CAPS"/>
+ <keyword type="constant" name="STUN_COMPATIBILITY_WLM2009" link="libnice-StunAgent.html#STUN-COMPATIBILITY-WLM2009:CAPS"/>
+ <keyword type="constant" name="STUN_COMPATIBILITY_LAST" link="libnice-StunAgent.html#STUN-COMPATIBILITY-LAST:CAPS"/>
+ <keyword type="constant" name="STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS" link="libnice-StunAgent.html#STUN-AGENT-USAGE-SHORT-TERM-CREDENTIALS:CAPS"/>
+ <keyword type="constant" name="STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS" link="libnice-StunAgent.html#STUN-AGENT-USAGE-LONG-TERM-CREDENTIALS:CAPS"/>
+ <keyword type="constant" name="STUN_AGENT_USAGE_USE_FINGERPRINT" link="libnice-StunAgent.html#STUN-AGENT-USAGE-USE-FINGERPRINT:CAPS"/>
+ <keyword type="constant" name="STUN_AGENT_USAGE_ADD_SOFTWARE" link="libnice-StunAgent.html#STUN-AGENT-USAGE-ADD-SOFTWARE:CAPS"/>
+ <keyword type="constant" name="STUN_AGENT_USAGE_IGNORE_CREDENTIALS" link="libnice-StunAgent.html#STUN-AGENT-USAGE-IGNORE-CREDENTIALS:CAPS"/>
+ <keyword type="constant" name="STUN_AGENT_USAGE_NO_INDICATION_AUTH" link="libnice-StunAgent.html#STUN-AGENT-USAGE-NO-INDICATION-AUTH:CAPS"/>
+ <keyword type="constant" name="STUN_AGENT_USAGE_FORCE_VALIDATER" link="libnice-StunAgent.html#STUN-AGENT-USAGE-FORCE-VALIDATER:CAPS"/>
+ <keyword type="constant" name="STUN_AGENT_USAGE_NO_ALIGNED_ATTRIBUTES" link="libnice-StunAgent.html#STUN-AGENT-USAGE-NO-ALIGNED-ATTRIBUTES:CAPS"/>
+ <keyword type="constant" name="STUN_VALIDATION_SUCCESS" link="libnice-StunAgent.html#STUN-VALIDATION-SUCCESS:CAPS"/>
+ <keyword type="constant" name="STUN_VALIDATION_NOT_STUN" link="libnice-StunAgent.html#STUN-VALIDATION-NOT-STUN:CAPS"/>
+ <keyword type="constant" name="STUN_VALIDATION_INCOMPLETE_STUN" link="libnice-StunAgent.html#STUN-VALIDATION-INCOMPLETE-STUN:CAPS"/>
+ <keyword type="constant" name="STUN_VALIDATION_BAD_REQUEST" link="libnice-StunAgent.html#STUN-VALIDATION-BAD-REQUEST:CAPS"/>
+ <keyword type="constant" name="STUN_VALIDATION_UNAUTHORIZED_BAD_REQUEST" link="libnice-StunAgent.html#STUN-VALIDATION-UNAUTHORIZED-BAD-REQUEST:CAPS"/>
+ <keyword type="constant" name="STUN_VALIDATION_UNAUTHORIZED" link="libnice-StunAgent.html#STUN-VALIDATION-UNAUTHORIZED:CAPS"/>
+ <keyword type="constant" name="STUN_VALIDATION_UNMATCHED_RESPONSE" link="libnice-StunAgent.html#STUN-VALIDATION-UNMATCHED-RESPONSE:CAPS"/>
+ <keyword type="constant" name="STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE" link="libnice-StunAgent.html#STUN-VALIDATION-UNKNOWN-REQUEST-ATTRIBUTE:CAPS"/>
+ <keyword type="constant" name="STUN_VALIDATION_UNKNOWN_ATTRIBUTE" link="libnice-StunAgent.html#STUN-VALIDATION-UNKNOWN-ATTRIBUTE:CAPS"/>
+ <keyword type="constant" name="STUN_REQUEST" link="libnice-StunMessage.html#STUN-REQUEST:CAPS"/>
+ <keyword type="constant" name="STUN_INDICATION" link="libnice-StunMessage.html#STUN-INDICATION:CAPS"/>
+ <keyword type="constant" name="STUN_RESPONSE" link="libnice-StunMessage.html#STUN-RESPONSE:CAPS"/>
+ <keyword type="constant" name="STUN_ERROR" link="libnice-StunMessage.html#STUN-ERROR:CAPS"/>
+ <keyword type="constant" name="STUN_BINDING" link="libnice-StunMessage.html#STUN-BINDING:CAPS"/>
+ <keyword type="constant" name="STUN_SHARED_SECRET" link="libnice-StunMessage.html#STUN-SHARED-SECRET:CAPS"/>
+ <keyword type="constant" name="STUN_ALLOCATE" link="libnice-StunMessage.html#STUN-ALLOCATE:CAPS"/>
+ <keyword type="constant" name="STUN_SET_ACTIVE_DST" link="libnice-StunMessage.html#STUN-SET-ACTIVE-DST:CAPS"/>
+ <keyword type="constant" name="STUN_REFRESH" link="libnice-StunMessage.html#STUN-REFRESH:CAPS"/>
+ <keyword type="constant" name="STUN_SEND" link="libnice-StunMessage.html#STUN-SEND:CAPS"/>
+ <keyword type="constant" name="STUN_CONNECT" link="libnice-StunMessage.html#STUN-CONNECT:CAPS"/>
+ <keyword type="constant" name="STUN_OLD_SET_ACTIVE_DST" link="libnice-StunMessage.html#STUN-OLD-SET-ACTIVE-DST:CAPS"/>
+ <keyword type="constant" name="STUN_IND_SEND" link="libnice-StunMessage.html#STUN-IND-SEND:CAPS"/>
+ <keyword type="constant" name="STUN_IND_DATA" link="libnice-StunMessage.html#STUN-IND-DATA:CAPS"/>
+ <keyword type="constant" name="STUN_IND_CONNECT_STATUS" link="libnice-StunMessage.html#STUN-IND-CONNECT-STATUS:CAPS"/>
+ <keyword type="constant" name="STUN_CREATEPERMISSION" link="libnice-StunMessage.html#STUN-CREATEPERMISSION:CAPS"/>
+ <keyword type="constant" name="STUN_CHANNELBIND" link="libnice-StunMessage.html#STUN-CHANNELBIND:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_MAPPED_ADDRESS" link="libnice-StunMessage.html#STUN-ATTRIBUTE-MAPPED-ADDRESS:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_RESPONSE_ADDRESS" link="libnice-StunMessage.html#STUN-ATTRIBUTE-RESPONSE-ADDRESS:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_CHANGE_REQUEST" link="libnice-StunMessage.html#STUN-ATTRIBUTE-CHANGE-REQUEST:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_SOURCE_ADDRESS" link="libnice-StunMessage.html#STUN-ATTRIBUTE-SOURCE-ADDRESS:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_CHANGED_ADDRESS" link="libnice-StunMessage.html#STUN-ATTRIBUTE-CHANGED-ADDRESS:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_USERNAME" link="libnice-StunMessage.html#STUN-ATTRIBUTE-USERNAME:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_PASSWORD" link="libnice-StunMessage.html#STUN-ATTRIBUTE-PASSWORD:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_MESSAGE_INTEGRITY" link="libnice-StunMessage.html#STUN-ATTRIBUTE-MESSAGE-INTEGRITY:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_ERROR_CODE" link="libnice-StunMessage.html#STUN-ATTRIBUTE-ERROR-CODE:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_UNKNOWN_ATTRIBUTES" link="libnice-StunMessage.html#STUN-ATTRIBUTE-UNKNOWN-ATTRIBUTES:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_REFLECTED_FROM" link="libnice-StunMessage.html#STUN-ATTRIBUTE-REFLECTED-FROM:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_CHANNEL_NUMBER" link="libnice-StunMessage.html#STUN-ATTRIBUTE-CHANNEL-NUMBER:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_LIFETIME" link="libnice-StunMessage.html#STUN-ATTRIBUTE-LIFETIME:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_MS_ALTERNATE_SERVER" link="libnice-StunMessage.html#STUN-ATTRIBUTE-MS-ALTERNATE-SERVER:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_MAGIC_COOKIE" link="libnice-StunMessage.html#STUN-ATTRIBUTE-MAGIC-COOKIE:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_BANDWIDTH" link="libnice-StunMessage.html#STUN-ATTRIBUTE-BANDWIDTH:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_DESTINATION_ADDRESS" link="libnice-StunMessage.html#STUN-ATTRIBUTE-DESTINATION-ADDRESS:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_REMOTE_ADDRESS" link="libnice-StunMessage.html#STUN-ATTRIBUTE-REMOTE-ADDRESS:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_PEER_ADDRESS" link="libnice-StunMessage.html#STUN-ATTRIBUTE-PEER-ADDRESS:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_XOR_PEER_ADDRESS" link="libnice-StunMessage.html#STUN-ATTRIBUTE-XOR-PEER-ADDRESS:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_DATA" link="libnice-StunMessage.html#STUN-ATTRIBUTE-DATA:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_REALM" link="libnice-StunMessage.html#STUN-ATTRIBUTE-REALM:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_NONCE" link="libnice-StunMessage.html#STUN-ATTRIBUTE-NONCE:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_RELAY_ADDRESS" link="libnice-StunMessage.html#STUN-ATTRIBUTE-RELAY-ADDRESS:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_RELAYED_ADDRESS" link="libnice-StunMessage.html#STUN-ATTRIBUTE-RELAYED-ADDRESS:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS" link="libnice-StunMessage.html#STUN-ATTRIBUTE-XOR-RELAYED-ADDRESS:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_REQUESTED_ADDRESS_TYPE" link="libnice-StunMessage.html#STUN-ATTRIBUTE-REQUESTED-ADDRESS-TYPE:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_REQUESTED_PORT_PROPS" link="libnice-StunMessage.html#STUN-ATTRIBUTE-REQUESTED-PORT-PROPS:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_REQUESTED_PROPS" link="libnice-StunMessage.html#STUN-ATTRIBUTE-REQUESTED-PROPS:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_EVEN_PORT" link="libnice-StunMessage.html#STUN-ATTRIBUTE-EVEN-PORT:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_REQUESTED_TRANSPORT" link="libnice-StunMessage.html#STUN-ATTRIBUTE-REQUESTED-TRANSPORT:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_DONT_FRAGMENT" link="libnice-StunMessage.html#STUN-ATTRIBUTE-DONT-FRAGMENT:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS" link="libnice-StunMessage.html#STUN-ATTRIBUTE-XOR-MAPPED-ADDRESS:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_TIMER_VAL" link="libnice-StunMessage.html#STUN-ATTRIBUTE-TIMER-VAL:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_REQUESTED_IP" link="libnice-StunMessage.html#STUN-ATTRIBUTE-REQUESTED-IP:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_RESERVATION_TOKEN" link="libnice-StunMessage.html#STUN-ATTRIBUTE-RESERVATION-TOKEN:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_CONNECT_STAT" link="libnice-StunMessage.html#STUN-ATTRIBUTE-CONNECT-STAT:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_PRIORITY" link="libnice-StunMessage.html#STUN-ATTRIBUTE-PRIORITY:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_USE_CANDIDATE" link="libnice-StunMessage.html#STUN-ATTRIBUTE-USE-CANDIDATE:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_OPTIONS" link="libnice-StunMessage.html#STUN-ATTRIBUTE-OPTIONS:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_MS_VERSION" link="libnice-StunMessage.html#STUN-ATTRIBUTE-MS-VERSION:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_MS_XOR_MAPPED_ADDRESS" link="libnice-StunMessage.html#STUN-ATTRIBUTE-MS-XOR-MAPPED-ADDRESS:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_SOFTWARE" link="libnice-StunMessage.html#STUN-ATTRIBUTE-SOFTWARE:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_ALTERNATE_SERVER" link="libnice-StunMessage.html#STUN-ATTRIBUTE-ALTERNATE-SERVER:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_FINGERPRINT" link="libnice-StunMessage.html#STUN-ATTRIBUTE-FINGERPRINT:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_ICE_CONTROLLED" link="libnice-StunMessage.html#STUN-ATTRIBUTE-ICE-CONTROLLED:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_ICE_CONTROLLING" link="libnice-StunMessage.html#STUN-ATTRIBUTE-ICE-CONTROLLING:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_MS_SEQUENCE_NUMBER" link="libnice-StunMessage.html#STUN-ATTRIBUTE-MS-SEQUENCE-NUMBER:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_CANDIDATE_IDENTIFIER" link="libnice-StunMessage.html#STUN-ATTRIBUTE-CANDIDATE-IDENTIFIER:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_MS_IMPLEMENTATION_VERSION" link="libnice-StunMessage.html#STUN-ATTRIBUTE-MS-IMPLEMENTATION-VERSION:CAPS"/>
+ <keyword type="constant" name="STUN_ATTRIBUTE_NOMINATION" link="libnice-StunMessage.html#STUN-ATTRIBUTE-NOMINATION:CAPS"/>
+ <keyword type="constant" name="STUN_ERROR_TRY_ALTERNATE" link="libnice-StunMessage.html#STUN-ERROR-TRY-ALTERNATE:CAPS"/>
+ <keyword type="constant" name="STUN_ERROR_BAD_REQUEST" link="libnice-StunMessage.html#STUN-ERROR-BAD-REQUEST:CAPS"/>
+ <keyword type="constant" name="STUN_ERROR_UNAUTHORIZED" link="libnice-StunMessage.html#STUN-ERROR-UNAUTHORIZED:CAPS"/>
+ <keyword type="constant" name="STUN_ERROR_UNKNOWN_ATTRIBUTE" link="libnice-StunMessage.html#STUN-ERROR-UNKNOWN-ATTRIBUTE:CAPS"/>
+ <keyword type="constant" name="STUN_ERROR_ALLOCATION_MISMATCH" link="libnice-StunMessage.html#STUN-ERROR-ALLOCATION-MISMATCH:CAPS"/>
+ <keyword type="constant" name="STUN_ERROR_STALE_NONCE" link="libnice-StunMessage.html#STUN-ERROR-STALE-NONCE:CAPS"/>
+ <keyword type="constant" name="STUN_ERROR_ACT_DST_ALREADY" link="libnice-StunMessage.html#STUN-ERROR-ACT-DST-ALREADY:CAPS"/>
+ <keyword type="constant" name="STUN_ERROR_UNSUPPORTED_FAMILY" link="libnice-StunMessage.html#STUN-ERROR-UNSUPPORTED-FAMILY:CAPS"/>
+ <keyword type="constant" name="STUN_ERROR_WRONG_CREDENTIALS" link="libnice-StunMessage.html#STUN-ERROR-WRONG-CREDENTIALS:CAPS"/>
+ <keyword type="constant" name="STUN_ERROR_UNSUPPORTED_TRANSPORT" link="libnice-StunMessage.html#STUN-ERROR-UNSUPPORTED-TRANSPORT:CAPS"/>
+ <keyword type="constant" name="STUN_ERROR_INVALID_IP" link="libnice-StunMessage.html#STUN-ERROR-INVALID-IP:CAPS"/>
+ <keyword type="constant" name="STUN_ERROR_INVALID_PORT" link="libnice-StunMessage.html#STUN-ERROR-INVALID-PORT:CAPS"/>
+ <keyword type="constant" name="STUN_ERROR_OP_TCP_ONLY" link="libnice-StunMessage.html#STUN-ERROR-OP-TCP-ONLY:CAPS"/>
+ <keyword type="constant" name="STUN_ERROR_CONN_ALREADY" link="libnice-StunMessage.html#STUN-ERROR-CONN-ALREADY:CAPS"/>
+ <keyword type="constant" name="STUN_ERROR_ALLOCATION_QUOTA_REACHED" link="libnice-StunMessage.html#STUN-ERROR-ALLOCATION-QUOTA-REACHED:CAPS"/>
+ <keyword type="constant" name="STUN_ERROR_ROLE_CONFLICT" link="libnice-StunMessage.html#STUN-ERROR-ROLE-CONFLICT:CAPS"/>
+ <keyword type="constant" name="STUN_ERROR_SERVER_ERROR" link="libnice-StunMessage.html#STUN-ERROR-SERVER-ERROR:CAPS"/>
+ <keyword type="constant" name="STUN_ERROR_SERVER_CAPACITY" link="libnice-StunMessage.html#STUN-ERROR-SERVER-CAPACITY:CAPS"/>
+ <keyword type="constant" name="STUN_ERROR_INSUFFICIENT_CAPACITY" link="libnice-StunMessage.html#STUN-ERROR-INSUFFICIENT-CAPACITY:CAPS"/>
+ <keyword type="constant" name="STUN_ERROR_MAX" link="libnice-StunMessage.html#STUN-ERROR-MAX:CAPS"/>
+ <keyword type="constant" name="STUN_MESSAGE_RETURN_SUCCESS" link="libnice-StunMessage.html#STUN-MESSAGE-RETURN-SUCCESS:CAPS"/>
+ <keyword type="constant" name="STUN_MESSAGE_RETURN_NOT_FOUND" link="libnice-StunMessage.html#STUN-MESSAGE-RETURN-NOT-FOUND:CAPS"/>
+ <keyword type="constant" name="STUN_MESSAGE_RETURN_INVALID" link="libnice-StunMessage.html#STUN-MESSAGE-RETURN-INVALID:CAPS"/>
+ <keyword type="constant" name="STUN_MESSAGE_RETURN_NOT_ENOUGH_SPACE" link="libnice-StunMessage.html#STUN-MESSAGE-RETURN-NOT-ENOUGH-SPACE:CAPS"/>
+ <keyword type="constant" name="STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS" link="libnice-StunMessage.html#STUN-MESSAGE-RETURN-UNSUPPORTED-ADDRESS:CAPS"/>
+ <keyword type="constant" name="STUN_USAGE_BIND_RETURN_SUCCESS" link="libnice-Bind.html#STUN-USAGE-BIND-RETURN-SUCCESS:CAPS"/>
+ <keyword type="constant" name="STUN_USAGE_BIND_RETURN_ERROR" link="libnice-Bind.html#STUN-USAGE-BIND-RETURN-ERROR:CAPS"/>
+ <keyword type="constant" name="STUN_USAGE_BIND_RETURN_INVALID" link="libnice-Bind.html#STUN-USAGE-BIND-RETURN-INVALID:CAPS"/>
+ <keyword type="constant" name="STUN_USAGE_BIND_RETURN_ALTERNATE_SERVER" link="libnice-Bind.html#STUN-USAGE-BIND-RETURN-ALTERNATE-SERVER:CAPS"/>
+ <keyword type="constant" name="STUN_USAGE_BIND_RETURN_TIMEOUT" link="libnice-Bind.html#STUN-USAGE-BIND-RETURN-TIMEOUT:CAPS"/>
+ <keyword type="constant" name="STUN_USAGE_ICE_COMPATIBILITY_RFC5245" link="libnice-ICE.html#STUN-USAGE-ICE-COMPATIBILITY-RFC5245:CAPS"/>
+ <keyword type="constant" name="STUN_USAGE_ICE_COMPATIBILITY_GOOGLE" link="libnice-ICE.html#STUN-USAGE-ICE-COMPATIBILITY-GOOGLE:CAPS"/>
+ <keyword type="constant" name="STUN_USAGE_ICE_COMPATIBILITY_MSN" link="libnice-ICE.html#STUN-USAGE-ICE-COMPATIBILITY-MSN:CAPS"/>
+ <keyword type="constant" name="STUN_USAGE_ICE_COMPATIBILITY_MSICE2" link="libnice-ICE.html#STUN-USAGE-ICE-COMPATIBILITY-MSICE2:CAPS"/>
+ <keyword type="constant" name="STUN_USAGE_ICE_COMPATIBILITY_DRAFT19" link="libnice-ICE.html#STUN-USAGE-ICE-COMPATIBILITY-DRAFT19:CAPS"/>
+ <keyword type="constant" name="STUN_USAGE_ICE_COMPATIBILITY_WLM2009" link="libnice-ICE.html#STUN-USAGE-ICE-COMPATIBILITY-WLM2009:CAPS"/>
+ <keyword type="constant" name="STUN_USAGE_ICE_RETURN_SUCCESS" link="libnice-ICE.html#STUN-USAGE-ICE-RETURN-SUCCESS:CAPS"/>
+ <keyword type="constant" name="STUN_USAGE_ICE_RETURN_ERROR" link="libnice-ICE.html#STUN-USAGE-ICE-RETURN-ERROR:CAPS"/>
+ <keyword type="constant" name="STUN_USAGE_ICE_RETURN_INVALID" link="libnice-ICE.html#STUN-USAGE-ICE-RETURN-INVALID:CAPS"/>
+ <keyword type="constant" name="STUN_USAGE_ICE_RETURN_ROLE_CONFLICT" link="libnice-ICE.html#STUN-USAGE-ICE-RETURN-ROLE-CONFLICT:CAPS"/>
+ <keyword type="constant" name="STUN_USAGE_ICE_RETURN_INVALID_REQUEST" link="libnice-ICE.html#STUN-USAGE-ICE-RETURN-INVALID-REQUEST:CAPS"/>
+ <keyword type="constant" name="STUN_USAGE_ICE_RETURN_INVALID_METHOD" link="libnice-ICE.html#STUN-USAGE-ICE-RETURN-INVALID-METHOD:CAPS"/>
+ <keyword type="constant" name="STUN_USAGE_ICE_RETURN_MEMORY_ERROR" link="libnice-ICE.html#STUN-USAGE-ICE-RETURN-MEMORY-ERROR:CAPS"/>
+ <keyword type="constant" name="STUN_USAGE_ICE_RETURN_INVALID_ADDRESS" link="libnice-ICE.html#STUN-USAGE-ICE-RETURN-INVALID-ADDRESS:CAPS"/>
+ <keyword type="constant" name="STUN_USAGE_ICE_RETURN_NO_MAPPED_ADDRESS" link="libnice-ICE.html#STUN-USAGE-ICE-RETURN-NO-MAPPED-ADDRESS:CAPS"/>
+ <keyword type="constant" name="STUN_USAGE_TURN_COMPATIBILITY_DRAFT9" link="libnice-TURN.html#STUN-USAGE-TURN-COMPATIBILITY-DRAFT9:CAPS"/>
+ <keyword type="constant" name="STUN_USAGE_TURN_COMPATIBILITY_GOOGLE" link="libnice-TURN.html#STUN-USAGE-TURN-COMPATIBILITY-GOOGLE:CAPS"/>
+ <keyword type="constant" name="STUN_USAGE_TURN_COMPATIBILITY_MSN" link="libnice-TURN.html#STUN-USAGE-TURN-COMPATIBILITY-MSN:CAPS"/>
+ <keyword type="constant" name="STUN_USAGE_TURN_COMPATIBILITY_OC2007" link="libnice-TURN.html#STUN-USAGE-TURN-COMPATIBILITY-OC2007:CAPS"/>
+ <keyword type="constant" name="STUN_USAGE_TURN_COMPATIBILITY_RFC5766" link="libnice-TURN.html#STUN-USAGE-TURN-COMPATIBILITY-RFC5766:CAPS"/>
+ <keyword type="constant" name="STUN_USAGE_TURN_REQUEST_PORT_NORMAL" link="libnice-TURN.html#STUN-USAGE-TURN-REQUEST-PORT-NORMAL:CAPS"/>
+ <keyword type="constant" name="STUN_USAGE_TURN_REQUEST_PORT_EVEN" link="libnice-TURN.html#STUN-USAGE-TURN-REQUEST-PORT-EVEN:CAPS"/>
+ <keyword type="constant" name="STUN_USAGE_TURN_REQUEST_PORT_EVEN_AND_RESERVE" link="libnice-TURN.html#STUN-USAGE-TURN-REQUEST-PORT-EVEN-AND-RESERVE:CAPS"/>
+ <keyword type="constant" name="STUN_USAGE_TURN_RETURN_RELAY_SUCCESS" link="libnice-TURN.html#STUN-USAGE-TURN-RETURN-RELAY-SUCCESS:CAPS"/>
+ <keyword type="constant" name="STUN_USAGE_TURN_RETURN_MAPPED_SUCCESS" link="libnice-TURN.html#STUN-USAGE-TURN-RETURN-MAPPED-SUCCESS:CAPS"/>
+ <keyword type="constant" name="STUN_USAGE_TURN_RETURN_ERROR" link="libnice-TURN.html#STUN-USAGE-TURN-RETURN-ERROR:CAPS"/>
+ <keyword type="constant" name="STUN_USAGE_TURN_RETURN_INVALID" link="libnice-TURN.html#STUN-USAGE-TURN-RETURN-INVALID:CAPS"/>
+ <keyword type="constant" name="STUN_USAGE_TURN_RETURN_ALTERNATE_SERVER" link="libnice-TURN.html#STUN-USAGE-TURN-RETURN-ALTERNATE-SERVER:CAPS"/>
+ <keyword type="constant" name="STUN_USAGE_TIMER_RETURN_SUCCESS" link="libnice-Timer.html#STUN-USAGE-TIMER-RETURN-SUCCESS:CAPS"/>
+ <keyword type="constant" name="STUN_USAGE_TIMER_RETURN_RETRANSMIT" link="libnice-Timer.html#STUN-USAGE-TIMER-RETURN-RETRANSMIT:CAPS"/>
+ <keyword type="constant" name="STUN_USAGE_TIMER_RETURN_TIMEOUT" link="libnice-Timer.html#STUN-USAGE-TIMER-RETURN-TIMEOUT:CAPS"/>
+ <keyword type="constant" name="PSEUDO_TCP_LISTEN" link="libnice-Pseudo-TCP-Socket.html#PSEUDO-TCP-LISTEN:CAPS"/>
+ <keyword type="constant" name="PSEUDO_TCP_SYN_SENT" link="libnice-Pseudo-TCP-Socket.html#PSEUDO-TCP-SYN-SENT:CAPS"/>
+ <keyword type="constant" name="PSEUDO_TCP_SYN_RECEIVED" link="libnice-Pseudo-TCP-Socket.html#PSEUDO-TCP-SYN-RECEIVED:CAPS"/>
+ <keyword type="constant" name="PSEUDO_TCP_ESTABLISHED" link="libnice-Pseudo-TCP-Socket.html#PSEUDO-TCP-ESTABLISHED:CAPS"/>
+ <keyword type="constant" name="PSEUDO_TCP_CLOSED" link="libnice-Pseudo-TCP-Socket.html#PSEUDO-TCP-CLOSED:CAPS"/>
+ <keyword type="constant" name="PSEUDO_TCP_FIN_WAIT_1" link="libnice-Pseudo-TCP-Socket.html#PSEUDO-TCP-FIN-WAIT-1:CAPS"/>
+ <keyword type="constant" name="PSEUDO_TCP_FIN_WAIT_2" link="libnice-Pseudo-TCP-Socket.html#PSEUDO-TCP-FIN-WAIT-2:CAPS"/>
+ <keyword type="constant" name="PSEUDO_TCP_CLOSING" link="libnice-Pseudo-TCP-Socket.html#PSEUDO-TCP-CLOSING:CAPS"/>
+ <keyword type="constant" name="PSEUDO_TCP_TIME_WAIT" link="libnice-Pseudo-TCP-Socket.html#PSEUDO-TCP-TIME-WAIT:CAPS"/>
+ <keyword type="constant" name="PSEUDO_TCP_CLOSE_WAIT" link="libnice-Pseudo-TCP-Socket.html#PSEUDO-TCP-CLOSE-WAIT:CAPS"/>
+ <keyword type="constant" name="PSEUDO_TCP_LAST_ACK" link="libnice-Pseudo-TCP-Socket.html#PSEUDO-TCP-LAST-ACK:CAPS"/>
+ <keyword type="constant" name="WR_SUCCESS" link="libnice-Pseudo-TCP-Socket.html#WR-SUCCESS:CAPS"/>
+ <keyword type="constant" name="WR_TOO_LARGE" link="libnice-Pseudo-TCP-Socket.html#WR-TOO-LARGE:CAPS"/>
+ <keyword type="constant" name="WR_FAIL" link="libnice-Pseudo-TCP-Socket.html#WR-FAIL:CAPS"/>
+ <keyword type="constant" name="PSEUDO_TCP_DEBUG_NONE" link="libnice-Pseudo-TCP-Socket.html#PSEUDO-TCP-DEBUG-NONE:CAPS"/>
+ <keyword type="constant" name="PSEUDO_TCP_DEBUG_NORMAL" link="libnice-Pseudo-TCP-Socket.html#PSEUDO-TCP-DEBUG-NORMAL:CAPS"/>
+ <keyword type="constant" name="PSEUDO_TCP_DEBUG_VERBOSE" link="libnice-Pseudo-TCP-Socket.html#PSEUDO-TCP-DEBUG-VERBOSE:CAPS"/>
+ <keyword type="constant" name="PSEUDO_TCP_SHUTDOWN_RD" link="libnice-Pseudo-TCP-Socket.html#PSEUDO-TCP-SHUTDOWN-RD:CAPS"/>
+ <keyword type="constant" name="PSEUDO_TCP_SHUTDOWN_WR" link="libnice-Pseudo-TCP-Socket.html#PSEUDO-TCP-SHUTDOWN-WR:CAPS"/>
+ <keyword type="constant" name="PSEUDO_TCP_SHUTDOWN_RDWR" link="libnice-Pseudo-TCP-Socket.html#PSEUDO-TCP-SHUTDOWN-RDWR:CAPS"/>
+ <keyword type="member" name="NiceInputMessage.buffers" link="NiceAgent.html#NiceInputMessage.buffers"/>
+ <keyword type="member" name="NiceInputMessage.n-buffers" link="NiceAgent.html#NiceInputMessage.n-buffers"/>
+ <keyword type="member" name="NiceInputMessage.from" link="NiceAgent.html#NiceInputMessage.from"/>
+ <keyword type="member" name="NiceInputMessage.length" link="NiceAgent.html#NiceInputMessage.length"/>
+ <keyword type="member" name="NiceOutputMessage.buffers" link="NiceAgent.html#NiceOutputMessage.buffers"/>
+ <keyword type="member" name="NiceOutputMessage.n-buffers" link="NiceAgent.html#NiceOutputMessage.n-buffers"/>
+ <keyword type="member" name="NiceCandidate-struct.type" link="NiceCandidate.html#NiceCandidate-struct.type"/>
+ <keyword type="member" name="NiceCandidate-struct.transport" link="NiceCandidate.html#NiceCandidate-struct.transport"/>
+ <keyword type="member" name="NiceCandidate-struct.addr" link="NiceCandidate.html#NiceCandidate-struct.addr"/>
+ <keyword type="member" name="NiceCandidate-struct.base-addr" link="NiceCandidate.html#NiceCandidate-struct.base-addr"/>
+ <keyword type="member" name="NiceCandidate-struct.priority" link="NiceCandidate.html#NiceCandidate-struct.priority"/>
+ <keyword type="member" name="NiceCandidate-struct.stream-id" link="NiceCandidate.html#NiceCandidate-struct.stream-id"/>
+ <keyword type="member" name="NiceCandidate-struct.component-id" link="NiceCandidate.html#NiceCandidate-struct.component-id"/>
+ <keyword type="member" name="NiceCandidate-struct.foundation" link="NiceCandidate.html#NiceCandidate-struct.foundation"/>
+ <keyword type="member" name="NiceCandidate-struct.username" link="NiceCandidate.html#NiceCandidate-struct.username"/>
+ <keyword type="member" name="NiceCandidate-struct.password" link="NiceCandidate.html#NiceCandidate-struct.password"/>
+ <keyword type="member" name="NiceCandidate-struct.turn" link="NiceCandidate.html#NiceCandidate-struct.turn"/>
+ <keyword type="member" name="NiceCandidate-struct.sockptr" link="NiceCandidate.html#NiceCandidate-struct.sockptr"/>
+ <keyword type="member" name="TurnServer.ref-count" link="NiceCandidate.html#TurnServer.ref-count"/>
+ <keyword type="member" name="TurnServer.server" link="NiceCandidate.html#TurnServer.server"/>
+ <keyword type="member" name="TurnServer.username" link="NiceCandidate.html#TurnServer.username"/>
+ <keyword type="member" name="TurnServer.password" link="NiceCandidate.html#TurnServer.password"/>
+ <keyword type="member" name="TurnServer.type" link="NiceCandidate.html#TurnServer.type"/>
+ <keyword type="member" name="StunDefaultValidaterData.username" link="libnice-StunAgent.html#StunDefaultValidaterData.username"/>
+ <keyword type="member" name="StunDefaultValidaterData.username-len" link="libnice-StunAgent.html#StunDefaultValidaterData.username-len"/>
+ <keyword type="member" name="StunDefaultValidaterData.password" link="libnice-StunAgent.html#StunDefaultValidaterData.password"/>
+ <keyword type="member" name="StunDefaultValidaterData.password-len" link="libnice-StunAgent.html#StunDefaultValidaterData.password-len"/>
+ <keyword type="member" name="StunMessage.agent" link="libnice-StunMessage.html#StunMessage.agent"/>
+ <keyword type="member" name="StunMessage.buffer" link="libnice-StunMessage.html#StunMessage.buffer"/>
+ <keyword type="member" name="StunMessage.buffer-len" link="libnice-StunMessage.html#StunMessage.buffer-len"/>
+ <keyword type="member" name="StunMessage.key" link="libnice-StunMessage.html#StunMessage.key"/>
+ <keyword type="member" name="StunMessage.key-len" link="libnice-StunMessage.html#StunMessage.key-len"/>
+ <keyword type="member" name="StunMessage.long-term-key" link="libnice-StunMessage.html#StunMessage.long-term-key"/>
+ <keyword type="member" name="StunMessage.long-term-valid" link="libnice-StunMessage.html#StunMessage.long-term-valid"/>
+ <keyword type="member" name="StunInputVector.buffer" link="libnice-StunMessage.html#StunInputVector.buffer"/>
+ <keyword type="member" name="StunInputVector.size" link="libnice-StunMessage.html#StunInputVector.size"/>
+ <keyword type="member" name="PseudoTcpCallbacks.user-data" link="libnice-Pseudo-TCP-Socket.html#PseudoTcpCallbacks.user-data"/>
+ <keyword type="member" name="PseudoTcpCallbacks.PseudoTcpOpened" link="libnice-Pseudo-TCP-Socket.html#PseudoTcpCallbacks.PseudoTcpOpened"/>
+ <keyword type="member" name="PseudoTcpCallbacks.PseudoTcpReadable" link="libnice-Pseudo-TCP-Socket.html#PseudoTcpCallbacks.PseudoTcpReadable"/>
+ <keyword type="member" name="PseudoTcpCallbacks.PseudoTcpWritable" link="libnice-Pseudo-TCP-Socket.html#PseudoTcpCallbacks.PseudoTcpWritable"/>
+ <keyword type="member" name="PseudoTcpCallbacks.PseudoTcpClosed" link="libnice-Pseudo-TCP-Socket.html#PseudoTcpCallbacks.PseudoTcpClosed"/>
+ <keyword type="member" name="PseudoTcpCallbacks.WritePacket" link="libnice-Pseudo-TCP-Socket.html#PseudoTcpCallbacks.WritePacket"/>
+ </functions>
+</book>
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Part I. ICE Library: libnice Reference Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets Vsnapshot">
+<link rel="home" href="index.html" title="libnice Reference Manual">
+<link rel="up" href="index.html" title="libnice Reference Manual">
+<link rel="prev" href="index.html" title="libnice Reference Manual">
+<link rel="next" href="ch01.html" title="">
+<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><img src="up-insensitive.png" width="16" height="16" border="0"></td>
+<td><a accesskey="p" href="index.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="ch01.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="part">
+<div class="titlepage"><div><div><h1 class="title">
+<a name="id-1.2"></a>Part I. ICE Library</h1></div></div></div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl class="toc">
+<dt><span class="chapter"><a href="ch01.html"></a></span></dt>
+<dd><dl>
+<dt>
+<span class="refentrytitle"><a href="NiceAgent.html">NiceAgent</a></span><span class="refpurpose"> — ICE agent API implementation</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="libnice-NiceAddress.html">NiceAddress</a></span><span class="refpurpose"> — IP address convenience library</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="NiceCandidate.html">NiceCandidate</a></span><span class="refpurpose"> — ICE candidate representation</span>
+</dt>
+</dl></dd>
+<dt><span class="chapter"><a href="ch02.html">Libnice helper functions</a></span></dt>
+<dd><dl>
+<dt>
+<span class="refentrytitle"><a href="libnice-Debug-messages.html">Debug messages</a></span><span class="refpurpose"> — Debug messages utility functions</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="libnice-Network-interfaces-discovery.html">Network interfaces discovery</a></span><span class="refpurpose"> — Utility functions to discover local network interfaces</span>
+</dt>
+</dl></dd>
+</dl>
+</div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.29</div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Part II. STUN Library: libnice Reference Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets Vsnapshot">
+<link rel="home" href="index.html" title="libnice Reference Manual">
+<link rel="up" href="index.html" title="libnice Reference Manual">
+<link rel="prev" href="libnice-Network-interfaces-discovery.html" title="Network interfaces discovery">
+<link rel="next" href="ch03.html" title="">
+<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><img src="up-insensitive.png" width="16" height="16" border="0"></td>
+<td><a accesskey="p" href="libnice-Network-interfaces-discovery.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="ch03.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="part">
+<div class="titlepage"><div><div><h1 class="title">
+<a name="id-1.3"></a>Part II. STUN Library</h1></div></div></div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl class="toc">
+<dt><span class="chapter"><a href="ch03.html"></a></span></dt>
+<dd><dl>
+<dt>
+<span class="refentrytitle"><a href="libnice-StunAgent.html">StunAgent</a></span><span class="refpurpose"> — STUN agent for building and validating STUN messages</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="libnice-StunMessage.html">StunMessage</a></span><span class="refpurpose"> — STUN messages parsing and formatting functions</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="libnice-STUN-Constants.html">STUN Constants</a></span><span class="refpurpose"> — STUN constants</span>
+</dt>
+</dl></dd>
+<dt><span class="chapter"><a href="ch04.html">STUN usages</a></span></dt>
+<dd><dl>
+<dt>
+<span class="refentrytitle"><a href="libnice-Bind.html">Bind</a></span><span class="refpurpose"> — STUN Binding Usage</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="libnice-ICE.html">ICE</a></span><span class="refpurpose"> — STUN ICE Usage</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="libnice-TURN.html">TURN</a></span><span class="refpurpose"> — TURN Allocation Usage</span>
+</dt>
+<dt>
+<span class="refentrytitle"><a href="libnice-Timer.html">Timer</a></span><span class="refpurpose"> — STUN timer Usage</span>
+</dt>
+</dl></dd>
+</dl>
+</div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.29</div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Part III. Pseudo TCP Socket implementation: libnice Reference Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets Vsnapshot">
+<link rel="home" href="index.html" title="libnice Reference Manual">
+<link rel="up" href="index.html" title="libnice Reference Manual">
+<link rel="prev" href="libnice-Timer.html" title="Timer">
+<link rel="next" href="ch05.html" title="">
+<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><img src="up-insensitive.png" width="16" height="16" border="0"></td>
+<td><a accesskey="p" href="libnice-Timer.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="ch05.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="part">
+<div class="titlepage"><div><div><h1 class="title">
+<a name="id-1.4"></a>Part III. Pseudo TCP Socket implementation</h1></div></div></div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl class="toc">
+<dt><span class="chapter"><a href="ch05.html"></a></span></dt>
+<dd><dl><dt>
+<span class="refentrytitle"><a href="libnice-Pseudo-TCP-Socket.html">Pseudo TCP Socket</a></span><span class="refpurpose"> — Pseudo TCP implementation</span>
+</dt></dl></dd>
+</dl>
+</div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.29</div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Part IV. Appendices: libnice Reference Manual</title>
+<meta name="generator" content="DocBook XSL Stylesheets Vsnapshot">
+<link rel="home" href="index.html" title="libnice Reference Manual">
+<link rel="up" href="index.html" title="libnice Reference Manual">
+<link rel="prev" href="libnice-Pseudo-TCP-Socket.html" title="Pseudo TCP Socket">
+<link rel="next" href="api-index-full.html" title="API Index">
+<meta name="generator" content="GTK-Doc V1.29 (XML mode)">
+<link rel="stylesheet" href="style.css" type="text/css">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table class="navigation" id="top" width="100%" summary="Navigation header" cellpadding="2" cellspacing="5"><tr valign="middle">
+<td width="100%" align="left" class="shortcuts"></td>
+<td><a accesskey="h" href="index.html"><img src="home.png" width="16" height="16" border="0" alt="Home"></a></td>
+<td><img src="up-insensitive.png" width="16" height="16" border="0"></td>
+<td><a accesskey="p" href="libnice-Pseudo-TCP-Socket.html"><img src="left.png" width="16" height="16" border="0" alt="Prev"></a></td>
+<td><a accesskey="n" href="api-index-full.html"><img src="right.png" width="16" height="16" border="0" alt="Next"></a></td>
+</tr></table>
+<div class="part">
+<div class="titlepage"><div><div><h1 class="title">
+<a name="id-1.6"></a>Part IV. Appendices</h1></div></div></div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl class="toc">
+<dt><span class="index"><a href="api-index-full.html">API Index</a></span></dt>
+<dt><span class="index"><a href="api-index-deprecated.html">Index of deprecated symbols</a></span></dt>
+<dt><span class="glossary"><a href="annotation-glossary.html">Annotation Glossary</a></span></dt>
+</dl>
+</div>
+</div>
+<div class="footer">
+<hr>Generated by GTK-Doc V1.29</div>
+</body>
+</html>
\ No newline at end of file
--- /dev/null
+body
+{
+ font-family: cantarell, sans-serif;
+}
+.synopsis, .classsynopsis
+{
+ /* tango:aluminium 1/2 */
+ background: #eeeeec;
+ background: rgba(238, 238, 236, 0.5);
+ border: solid 1px rgb(238, 238, 236);
+ padding: 0.5em;
+}
+.programlisting
+{
+ /* tango:sky blue 0/1 */
+ /* fallback for no rgba support */
+ background: #e6f3ff;
+ border: solid 1px #729fcf;
+ background: rgba(114, 159, 207, 0.1);
+ border: solid 1px rgba(114, 159, 207, 0.2);
+ padding: 0.5em;
+}
+.variablelist
+{
+ padding: 4px;
+ margin-left: 3em;
+}
+.variablelist td:first-child
+{
+ vertical-align: top;
+}
+
+span.nowrap {
+ white-space: nowrap;
+}
+
+div.gallery-float
+{
+ float: left;
+ padding: 10px;
+}
+div.gallery-float img
+{
+ border-style: none;
+}
+div.gallery-spacer
+{
+ clear: both;
+}
+
+a, a:visited
+{
+ text-decoration: none;
+ /* tango:sky blue 2 */
+ color: #3465a4;
+}
+a:hover
+{
+ text-decoration: underline;
+ /* tango:sky blue 1 */
+ color: #729fcf;
+}
+
+div.informaltable table
+{
+ border-collapse: separate;
+ border-spacing: 1em 0.3em;
+ border: none;
+}
+
+div.informaltable table td, div.informaltable table th
+{
+ vertical-align: top;
+}
+
+.function_type,
+.variable_type,
+.property_type,
+.signal_type,
+.parameter_name,
+.struct_member_name,
+.union_member_name,
+.define_keyword,
+.datatype_keyword,
+.typedef_keyword
+{
+ text-align: right;
+}
+
+/* dim non-primary columns */
+.c_punctuation,
+.function_type,
+.variable_type,
+.property_type,
+.signal_type,
+.define_keyword,
+.datatype_keyword,
+.typedef_keyword,
+.property_flags,
+.signal_flags,
+.parameter_annotations,
+.enum_member_annotations,
+.struct_member_annotations,
+.union_member_annotations
+{
+ color: #888a85;
+}
+
+.function_type a,
+.function_type a:visited,
+.function_type a:hover,
+.property_type a,
+.property_type a:visited,
+.property_type a:hover,
+.signal_type a,
+.signal_type a:visited,
+.signal_type a:hover,
+.signal_flags a,
+.signal_flags a:visited,
+.signal_flags a:hover
+{
+ color: #729fcf;
+}
+
+td p
+{
+ margin: 0.25em;
+}
+
+div.table table
+{
+ border-collapse: collapse;
+ border-spacing: 0px;
+ /* tango:aluminium 3 */
+ border: solid 1px #babdb6;
+}
+
+div.table table td, div.table table th
+{
+ /* tango:aluminium 3 */
+ border: solid 1px #babdb6;
+ padding: 3px;
+ vertical-align: top;
+}
+
+div.table table th
+{
+ /* tango:aluminium 2 */
+ background-color: #d3d7cf;
+}
+
+h4
+{
+ color: #555753;
+ margin-top: 1em;
+ margin-bottom: 1em;
+}
+
+hr
+{
+ /* tango:aluminium 1 */
+ color: #d3d7cf;
+ background: #d3d7cf;
+ border: none 0px;
+ height: 1px;
+ clear: both;
+ margin: 2.0em 0em 2.0em 0em;
+}
+
+dl.toc dt
+{
+ padding-bottom: 0.25em;
+}
+
+dl.toc > dt
+{
+ padding-top: 0.25em;
+ padding-bottom: 0.25em;
+ font-weight: bold;
+}
+
+dl.toc > dl
+{
+ padding-bottom: 0.5em;
+}
+
+.parameter
+{
+ font-style: normal;
+}
+
+.footer
+{
+ padding-top: 3.5em;
+ /* tango:aluminium 3 */
+ color: #babdb6;
+ text-align: center;
+ font-size: 80%;
+}
+
+.informalfigure,
+.figure
+{
+ margin: 1em;
+}
+
+.informalexample,
+.example
+{
+ margin-top: 1em;
+ margin-bottom: 1em;
+}
+
+.warning
+{
+ /* tango:orange 0/1 */
+ background: #ffeed9;
+ background: rgba(252, 175, 62, 0.1);
+ border-color: #ffb04f;
+ border-color: rgba(252, 175, 62, 0.2);
+}
+.note
+{
+ /* tango:chameleon 0/0.5 */
+ background: #d8ffb2;
+ background: rgba(138, 226, 52, 0.1);
+ border-color: #abf562;
+ border-color: rgba(138, 226, 52, 0.2);
+}
+div.blockquote
+{
+ border-color: #eeeeec;
+}
+.note, .warning, div.blockquote
+{
+ padding: 0.5em;
+ border-width: 1px;
+ border-style: solid;
+ margin: 2em;
+}
+.note p, .warning p
+{
+ margin: 0;
+}
+
+div.warning h3.title,
+div.note h3.title
+{
+ display: none;
+}
+
+p + div.section
+{
+ margin-top: 1em;
+}
+
+div.refnamediv,
+div.refsynopsisdiv,
+div.refsect1,
+div.refsect2,
+div.toc,
+div.section
+{
+ margin-bottom: 1em;
+}
+
+/* blob links */
+h2 .extralinks, h3 .extralinks
+{
+ float: right;
+ /* tango:aluminium 3 */
+ color: #babdb6;
+ font-size: 80%;
+ font-weight: normal;
+}
+
+.lineart
+{
+ color: #d3d7cf;
+ font-weight: normal;
+}
+
+.annotation
+{
+ /* tango:aluminium 5 */
+ color: #555753;
+ font-weight: normal;
+}
+
+.structfield
+{
+ font-style: normal;
+ font-weight: normal;
+}
+
+acronym,abbr
+{
+ border-bottom: 1px dotted gray;
+}
+
+/* code listings */
+
+.listing_code .programlisting .normal,
+.listing_code .programlisting .normal a,
+.listing_code .programlisting .number,
+.listing_code .programlisting .cbracket,
+.listing_code .programlisting .symbol { color: #555753; }
+.listing_code .programlisting .comment,
+.listing_code .programlisting .linenum { color: #babdb6; } /* tango: aluminium 3 */
+.listing_code .programlisting .function,
+.listing_code .programlisting .function a,
+.listing_code .programlisting .preproc { color: #204a87; } /* tango: sky blue 3 */
+.listing_code .programlisting .string { color: #ad7fa8; } /* tango: plum */
+.listing_code .programlisting .keyword,
+.listing_code .programlisting .usertype,
+.listing_code .programlisting .type,
+.listing_code .programlisting .type a { color: #4e9a06; } /* tango: chameleon 3 */
+
+.listing_frame {
+ /* tango:sky blue 1 */
+ border: solid 1px #729fcf;
+ border: solid 1px rgba(114, 159, 207, 0.2);
+ padding: 0px;
+}
+
+.listing_lines, .listing_code {
+ margin-top: 0px;
+ margin-bottom: 0px;
+ padding: 0.5em;
+}
+.listing_lines {
+ /* tango:sky blue 0.5 */
+ background: #a6c5e3;
+ background: rgba(114, 159, 207, 0.2);
+ /* tango:aluminium 6 */
+ color: #2e3436;
+}
+.listing_code {
+ /* tango:sky blue 0 */
+ background: #e6f3ff;
+ background: rgba(114, 159, 207, 0.1);
+}
+.listing_code .programlisting {
+ /* override from previous */
+ border: none 0px;
+ padding: 0px;
+ background: none;
+}
+.listing_lines pre, .listing_code pre {
+ margin: 0px;
+}
+
+@media screen {
+ /* these have a <sup> as a first child, but since there are no parent selectors
+ * we can't use that. */
+ a.footnote
+ {
+ position: relative;
+ top: 0em ! important;
+ }
+ /* this is needed so that the local anchors are displayed below the naviagtion */
+ div.footnote a[name], div.refnamediv a[name], div.refsect1 a[name], div.refsect2 a[name], div.index a[name], div.glossary a[name], div.sect1 a[name]
+ {
+ display: inline-block;
+ position: relative;
+ top:-5em;
+ }
+ /* this seems to be a bug in the xsl style sheets when generating indexes */
+ div.index div.index
+ {
+ top: 0em;
+ }
+ /* make space for the fixed navigation bar and add space at the bottom so that
+ * link targets appear somewhat close to top
+ */
+ body
+ {
+ padding-top: 2.5em;
+ padding-bottom: 500px;
+ max-width: 60em;
+ }
+ p
+ {
+ max-width: 60em;
+ }
+ /* style and size the navigation bar */
+ table.navigation#top
+ {
+ position: fixed;
+ background: #e2e2e2;
+ border-bottom: solid 1px #babdb6;
+ border-spacing: 5px;
+ margin-top: 0;
+ margin-bottom: 0;
+ top: 0;
+ left: 0;
+ z-index: 10;
+ }
+ table.navigation#top td
+ {
+ padding-left: 6px;
+ padding-right: 6px;
+ }
+ .navigation a, .navigation a:visited
+ {
+ /* tango:sky blue 3 */
+ color: #204a87;
+ }
+ .navigation a:hover
+ {
+ /* tango:sky blue 2 */
+ color: #3465a4;
+ }
+ td.shortcuts
+ {
+ /* tango:sky blue 2 */
+ color: #3465a4;
+ font-size: 80%;
+ white-space: nowrap;
+ }
+ td.shortcuts .dim
+ {
+ color: #babdb6;
+ }
+ .navigation .title
+ {
+ font-size: 80%;
+ max-width: none;
+ margin: 0px;
+ font-weight: normal;
+ }
+}
+@media screen and (min-width: 60em) {
+ /* screen larger than 60em */
+ body { margin: auto; }
+}
+@media screen and (max-width: 60em) {
+ /* screen less than 60em */
+ #nav_hierarchy { display: none; }
+ #nav_interfaces { display: none; }
+ #nav_prerequisites { display: none; }
+ #nav_derived_interfaces { display: none; }
+ #nav_implementations { display: none; }
+ #nav_child_properties { display: none; }
+ #nav_style_properties { display: none; }
+ #nav_index { display: none; }
+ #nav_glossary { display: none; }
+ .gallery_image { display: none; }
+ .property_flags { display: none; }
+ .signal_flags { display: none; }
+ .parameter_annotations { display: none; }
+ .enum_member_annotations { display: none; }
+ .struct_member_annotations { display: none; }
+ .union_member_annotations { display: none; }
+ /* now that a column is hidden, optimize space */
+ col.parameters_name { width: auto; }
+ col.parameters_description { width: auto; }
+ col.struct_members_name { width: auto; }
+ col.struct_members_description { width: auto; }
+ col.enum_members_name { width: auto; }
+ col.enum_members_description { width: auto; }
+ col.union_members_name { width: auto; }
+ col.union_members_description { width: auto; }
+ .listing_lines { display: none; }
+}
+@media print {
+ table.navigation {
+ visibility: collapse;
+ display: none;
+ }
+ div.titlepage table.navigation {
+ visibility: visible;
+ display: table;
+ background: #e2e2e2;
+ border: solid 1px #babdb6;
+ margin-top: 0;
+ margin-bottom: 0;
+ top: 0;
+ left: 0;
+ height: 3em;
+ }
+}
+
--- /dev/null
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
+<book id="index" xmlns:xi="http://www.w3.org/2003/XInclude">
+ <bookinfo>
+ <title>libnice Reference Manual</title>
+ <releaseinfo>
+ The latest version of this documentation can be found on-line at
+ <ulink role="online-location" url="http://nice.freedesktop.org/libnice/index.html">http://nice.freedesktop.org/libnice/</ulink>.
+ </releaseinfo>
+ </bookinfo>
+
+
+ <part>
+ <title>ICE Library</title>
+ <chapter>
+ <xi:include href="xml/agent.xml"/>
+ <xi:include href="xml/address.xml"/>
+ <xi:include href="xml/candidate.xml"/>
+ </chapter>
+ <chapter>
+ <title>Libnice helper functions</title>
+ <xi:include href="xml/debug.xml"/>
+ <xi:include href="xml/interfaces.xml"/>
+ </chapter>
+ </part>
+ <part>
+ <title>STUN Library</title>
+ <chapter>
+ <xi:include href="xml/stunagent.xml"/>
+ <xi:include href="xml/stunmessage.xml"/>
+ <xi:include href="xml/stunconstants.xml"/>
+ </chapter>
+ <chapter>
+ <title>STUN usages</title>
+ <xi:include href="xml/bind.xml"/>
+ <xi:include href="xml/ice.xml"/>
+ <xi:include href="xml/turn.xml"/>
+ <xi:include href="xml/timer.xml"/>
+ </chapter>
+ </part>
+
+ <part>
+ <title>Pseudo TCP Socket implementation</title>
+ <chapter>
+ <xi:include href="xml/pseudotcp.xml"/>
+ </chapter>
+ </part>
+
+ <para>The libnice library contains the ICE library and the
+ STUN library as well as a Pseudo TCP socket implementation.
+ </para>
+
+ <part>
+ <title>Appendices</title>
+ <index id="api-index-full">
+ <title>API Index</title>
+ <xi:include href="xml/api-index-full.xml"><xi:fallback/></xi:include>
+ </index>
+ <index id="api-index-deprecated">
+ <title>Index of deprecated symbols</title>
+ <xi:include href="xml/api-index-deprecated.xml"><xi:fallback/></xi:include>
+ </index>
+ <index role="0.0.4">
+ <title>Index of new symbols in 0.0.4</title>
+ <xi:include href="xml/api-index-0.0.4.xml"><xi:fallback/></xi:include>
+ </index>
+ <index role="0.0.6">
+ <title>Index of new symbols in 0.0.6</title>
+ <xi:include href="xml/api-index-0.0.6.xml"><xi:fallback/></xi:include>
+ </index>
+ <index role="0.0.7">
+ <title>Index of new symbols in 0.0.7</title>
+ <xi:include href="xml/api-index-0.0.7.xml"><xi:fallback/></xi:include>
+ </index>
+ <index role="0.0.9">
+ <title>Index of new symbols in 0.0.9</title>
+ <xi:include href="xml/api-index-0.0.9.xml"><xi:fallback/></xi:include>
+ </index>
+ <index role="0.0.10">
+ <title>Index of new symbols in 0.0.10</title>
+ <xi:include href="xml/api-index-0.0.10.xml"><xi:fallback/></xi:include>
+ </index>
+ <index role="0.0.11">
+ <title>Index of new symbols in 0.0.11</title>
+ <xi:include href="xml/api-index-0.0.11.xml"><xi:fallback/></xi:include>
+ </index>
+ <index role="0.1.4">
+ <title>Index of new symbols in 0.1.4</title>
+ <xi:include href="xml/api-index-0.1.4.xml"><xi:fallback/></xi:include>
+ </index>
+ <index role="0.1.5">
+ <title>Index of new symbols in 0.1.5</title>
+ <xi:include href="xml/api-index-0.1.5.xml"><xi:fallback/></xi:include>
+ </index>
+ <index role="0.1.6">
+ <title>Index of new symbols in 0.1.6</title>
+ <xi:include href="xml/api-index-0.1.6.xml"><xi:fallback/></xi:include>
+ </index>
+ <index role="0.1.8">
+ <title>Index of new symbols in 0.1.8</title>
+ <xi:include href="xml/api-index-0.1.8.xml"><xi:fallback/></xi:include>
+ </index>
+ <index role="0.1.14">
+ <title>Index of new symbols in 0.1.14</title>
+ <xi:include href="xml/api-index-0.1.14.xml"><xi:fallback/></xi:include>
+ </index>
+ <index role="0.1.15">
+ <title>Index of new symbols in 0.1.15</title>
+ <xi:include href="xml/api-index-0.1.15.xml"><xi:fallback/></xi:include>
+ </index>
+ <index role="0.1.16">
+ <title>Index of new symbols in 0.1.16</title>
+ <xi:include href="xml/api-index-0.1.16.xml"><xi:fallback/></xi:include>
+ </index>
+ <xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
+ </part>
+</book>
--- /dev/null
+<SECTION>
+<FILE>agent</FILE>
+<TITLE>NiceAgent</TITLE>
+NiceAgent
+NiceComponentState
+NiceComponentType
+NiceProxyType
+NiceNominationMode
+NiceCompatibility
+NiceAgentRecvFunc
+NiceInputMessage
+NiceOutputMessage
+NICE_AGENT_MAX_REMOTE_CANDIDATES
+nice_agent_new
+nice_agent_new_reliable
+nice_agent_new_full
+NiceAgentOption
+nice_agent_add_local_address
+nice_agent_set_port_range
+nice_agent_add_stream
+nice_agent_remove_stream
+nice_agent_set_relay_info
+nice_agent_forget_relays
+nice_agent_gather_candidates
+nice_agent_set_remote_credentials
+nice_agent_get_local_credentials
+nice_agent_set_local_credentials
+nice_agent_set_remote_candidates
+nice_agent_get_remote_candidates
+nice_agent_get_local_candidates
+nice_agent_get_selected_pair
+nice_agent_peer_candidate_gathering_done
+nice_agent_send
+nice_agent_send_messages_nonblocking
+nice_agent_recv
+nice_agent_recv_messages
+nice_agent_recv_nonblocking
+nice_agent_recv_messages_nonblocking
+nice_agent_attach_recv
+nice_agent_set_selected_pair
+nice_agent_set_selected_remote_candidate
+nice_agent_set_stream_tos
+nice_agent_set_software
+nice_agent_restart
+nice_agent_restart_stream
+nice_agent_set_stream_name
+nice_agent_get_stream_name
+nice_agent_get_default_local_candidate
+nice_agent_generate_local_sdp
+nice_agent_generate_local_stream_sdp
+nice_agent_generate_local_candidate_sdp
+nice_agent_parse_remote_sdp
+nice_agent_parse_remote_stream_sdp
+nice_agent_parse_remote_candidate_sdp
+nice_agent_get_io_stream
+nice_agent_get_selected_socket
+nice_agent_get_component_state
+nice_agent_close_async
+nice_component_state_to_string
+<SUBSECTION Standard>
+NICE_AGENT
+NICE_IS_AGENT
+NICE_TYPE_AGENT
+nice_agent_get_type
+NICE_AGENT_CLASS
+NICE_IS_AGENT_CLASS
+NICE_AGENT_GET_CLASS
+NICE_TYPE_AGENT_OPTION
+NICE_TYPE_COMPATIBILITY
+NICE_TYPE_COMPONENT_STATE
+NICE_TYPE_COMPONENT_TYPE
+NICE_TYPE_NOMINATION_MODE
+NICE_TYPE_PROXY_TYPE
+nice_agent_option_get_type
+nice_compatibility_get_type
+nice_component_state_get_type
+nice_component_type_get_type
+nice_nomination_mode_get_type
+nice_proxy_type_get_type
+<SUBSECTION Private>
+NiceAgentClass
+</SECTION>
+
+<SECTION>
+<FILE>candidate</FILE>
+<TITLE>NiceCandidate</TITLE>
+NiceCandidate
+NiceCandidateType
+NiceCandidateTransport
+TurnServer
+NiceRelayType
+NICE_CANDIDATE_MAX_FOUNDATION
+nice_candidate_new
+nice_candidate_free
+nice_candidate_copy
+nice_candidate_equal_target
+<SUBSECTION Standard>
+NICE_TYPE_CANDIDATE
+nice_candidate_get_type
+nice_candidate_transport_get_type
+nice_candidate_type_get_type
+nice_relay_type_get_type
+NICE_TYPE_RELAY_TYPE
+NICE_TYPE_CANDIDATE_TRANSPORT
+NICE_TYPE_CANDIDATE_TYPE
+<SUBSECTION Private>
+NICE_CANDIDATE_TYPE_PREF_HOST
+NICE_CANDIDATE_TYPE_PREF_PEER_REFLEXIVE
+NICE_CANDIDATE_TYPE_PREF_SERVER_REFLEXIVE
+NICE_CANDIDATE_TYPE_PREF_RELAYED
+NICE_CANDIDATE_TYPE_PREF_NAT_ASSISTED
+NICE_CANDIDATE_TYPE_PREF_UDP_TUNNELED
+NICE_CANDIDATE_TYPE_PREF_RELAYED_UDP
+NICE_CANDIDATE_DIRECTION_MS_PREF_ACTIVE
+NICE_CANDIDATE_DIRECTION_MS_PREF_PASSIVE
+NICE_CANDIDATE_TRANSPORT_MS_PREF_TCP
+NICE_CANDIDATE_TRANSPORT_MS_PREF_UDP
+</SECTION>
+
+<SECTION>
+<FILE>address</FILE>
+<TITLE>NiceAddress</TITLE>
+NiceAddress
+NICE_ADDRESS_STRING_LEN
+nice_address_init
+nice_address_new
+nice_address_free
+nice_address_dup
+nice_address_set_ipv4
+nice_address_set_ipv6
+nice_address_set_port
+nice_address_get_port
+nice_address_set_from_string
+nice_address_set_from_sockaddr
+nice_address_copy_to_sockaddr
+nice_address_equal
+nice_address_equal_no_port
+nice_address_to_string
+nice_address_is_private
+nice_address_is_valid
+nice_address_ip_version
+</SECTION>
+
+
+<SECTION>
+<FILE>debug</FILE>
+<TITLE>Debug messages</TITLE>
+nice_debug_enable
+nice_debug_disable
+</SECTION>
+
+<SECTION>
+<FILE>interfaces</FILE>
+<TITLE>Network interfaces discovery</TITLE>
+nice_interfaces_get_ip_for_interface
+nice_interfaces_get_local_interfaces
+nice_interfaces_get_local_ips
+</SECTION>
+
+<SECTION>
+<FILE>stunagent</FILE>
+<TITLE>StunAgent</TITLE>
+StunAgent
+StunCompatibility
+StunAgentUsageFlags
+StunValidationStatus
+StunMessageIntegrityValidate
+StunDefaultValidaterData
+StunDebugHandler
+stun_agent_init
+stun_agent_validate
+stun_agent_default_validater
+stun_agent_init_request
+stun_agent_init_indication
+stun_agent_init_response
+stun_agent_init_error
+stun_agent_build_unknown_attributes_error
+stun_agent_finish_message
+stun_agent_forget_transaction
+stun_agent_set_software
+stun_debug_enable
+stun_debug_disable
+stun_set_debug_handler
+<SUBSECTION Private>
+StunAgentSavedIds
+stun_debug
+stun_debug_bytes
+stun_agent_t
+</SECTION>
+
+
+<SECTION>
+<FILE>stunmessage</FILE>
+<TITLE>StunMessage</TITLE>
+StunMessage
+StunClass
+StunMethod
+StunAttribute
+StunTransactionId
+StunError
+StunMessageReturn
+STUN_MESSAGE_BUFFER_INCOMPLETE
+STUN_MESSAGE_BUFFER_INVALID
+stun_message_init
+stun_message_length
+stun_message_find
+stun_message_find_flag
+stun_message_find32
+stun_message_find64
+stun_message_find_string
+stun_message_find_addr
+stun_message_find_xor_addr
+stun_message_find_xor_addr_full
+stun_message_find_error
+stun_message_append
+stun_message_append_bytes
+stun_message_append_flag
+stun_message_append32
+stun_message_append64
+stun_message_append_string
+stun_message_append_addr
+stun_message_append_xor_addr
+stun_message_append_xor_addr_full
+stun_message_append_error
+stun_message_validate_buffer_length
+StunInputVector
+stun_message_validate_buffer_length_fast
+stun_message_id
+stun_message_get_class
+stun_message_get_method
+stun_message_has_attribute
+stun_message_has_cookie
+stun_optional
+stun_strerror
+</SECTION>
+
+<SECTION>
+<FILE>stunconstants</FILE>
+<TITLE>STUN Constants</TITLE>
+STUN_AGENT_MAX_SAVED_IDS
+STUN_AGENT_MAX_UNKNOWN_ATTRIBUTES
+STUN_ATTRIBUTE_HEADER_LENGTH
+STUN_ATTRIBUTE_LENGTH_LEN
+STUN_ATTRIBUTE_LENGTH_POS
+STUN_ATTRIBUTE_TYPE_LEN
+STUN_ATTRIBUTE_TYPE_POS
+STUN_ATTRIBUTE_VALUE_POS
+STUN_ID_LEN
+STUN_MAGIC_COOKIE
+STUN_MAX_MESSAGE_SIZE
+STUN_MAX_MESSAGE_SIZE_IPV4
+STUN_MAX_MESSAGE_SIZE_IPV6
+STUN_MESSAGE_ATTRIBUTES_POS
+STUN_MESSAGE_HEADER_LENGTH
+STUN_MESSAGE_LENGTH_LEN
+STUN_MESSAGE_LENGTH_POS
+STUN_MESSAGE_TRANS_ID_LEN
+STUN_MESSAGE_TRANS_ID_POS
+STUN_MESSAGE_TYPE_LEN
+STUN_MESSAGE_TYPE_POS
+TURN_MAGIC_COOKIE
+</SECTION>
+
+<SECTION>
+<FILE>turn</FILE>
+<TITLE>TURN</TITLE>
+StunUsageTurnCompatibility
+StunUsageTurnRequestPorts
+StunUsageTurnReturn
+stun_usage_turn_create
+stun_usage_turn_create_refresh
+stun_usage_turn_process
+stun_usage_turn_refresh_process
+stun_usage_turn_create_permission
+</SECTION>
+
+<SECTION>
+<FILE>ice</FILE>
+<TITLE>ICE</TITLE>
+StunUsageIceCompatibility
+StunUsageIceReturn
+stun_usage_ice_conncheck_create
+stun_usage_ice_conncheck_process
+stun_usage_ice_conncheck_create_reply
+stun_usage_ice_conncheck_priority
+stun_usage_ice_conncheck_use_candidate
+</SECTION>
+
+<SECTION>
+<FILE>timer</FILE>
+<TITLE>Timer</TITLE>
+StunTimer
+StunUsageTimerReturn
+STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS
+STUN_TIMER_DEFAULT_RELIABLE_TIMEOUT
+STUN_TIMER_DEFAULT_TIMEOUT
+stun_timer_start
+stun_timer_start_reliable
+stun_timer_refresh
+stun_timer_remainder
+<SUBSECTION Private>
+stun_timer_s
+</SECTION>
+
+<SECTION>
+<FILE>bind</FILE>
+<TITLE>Bind</TITLE>
+StunUsageBindReturn
+stun_usage_bind_create
+stun_usage_bind_process
+stun_usage_bind_keepalive
+stun_usage_bind_run
+</SECTION>
+
+<SECTION>
+<FILE>pseudotcp</FILE>
+<TITLE>Pseudo TCP Socket</TITLE>
+PseudoTcpSocket
+PseudoTcpState
+PseudoTcpWriteResult
+PseudoTcpCallbacks
+PseudoTcpDebugLevel
+PseudoTcpShutdown
+pseudo_tcp_socket_new
+pseudo_tcp_socket_connect
+pseudo_tcp_socket_recv
+pseudo_tcp_socket_send
+pseudo_tcp_socket_close
+pseudo_tcp_socket_shutdown
+pseudo_tcp_socket_is_closed
+pseudo_tcp_socket_is_closed_remotely
+pseudo_tcp_socket_get_error
+pseudo_tcp_socket_get_next_clock
+pseudo_tcp_socket_notify_clock
+pseudo_tcp_socket_notify_mtu
+pseudo_tcp_socket_notify_packet
+pseudo_tcp_set_debug_level
+pseudo_tcp_socket_get_available_bytes
+pseudo_tcp_socket_can_send
+pseudo_tcp_socket_get_available_send_space
+pseudo_tcp_socket_notify_message
+pseudo_tcp_socket_set_time
+<SUBSECTION Standard>
+pseudo_tcp_socket_get_type
+PseudoTcpSocketClass
+PSEUDOTCP_SOCKET_GET_CLASS
+PSEUDO_TCP_SOCKET
+PSEUDO_TCP_SOCKET_CLASS
+PSEUDO_TCP_SOCKET_TYPE
+IS_PSEUDO_TCP_SOCKET
+IS_PSEUDO_TCP_SOCKET_CLASS
+pseudo_tcp_debug_level_get_type
+pseudo_tcp_shutdown_get_type
+pseudo_tcp_state_get_type
+pseudo_tcp_write_result_get_type
+NICE_TYPE_TCP_DEBUG_LEVEL
+NICE_TYPE_TCP_SHUTDOWN
+NICE_TYPE_TCP_STATE
+NICE_TYPE_TCP_WRITE_RESULT
+<SUBSECTION Private>
+PseudoTcpSocketPrivate
+ECONNRESET
+EMSGSIZE
+ENOTCONN
+ETIMEDOUT
+EWOULDBLOCK
+</SECTION>
--- /dev/null
+nice_agent_get_type
+nice_agent_option_get_type
+nice_candidate_get_type
+nice_candidate_transport_get_type
+nice_candidate_type_get_type
+nice_compatibility_get_type
+nice_component_state_get_type
+nice_component_type_get_type
+nice_nomination_mode_get_type
+nice_proxy_type_get_type
+nice_relay_type_get_type
+pseudo_tcp_debug_level_get_type
+pseudo_tcp_shutdown_get_type
+pseudo_tcp_socket_get_type
+pseudo_tcp_state_get_type
+pseudo_tcp_write_result_get_type
--- /dev/null
+docpath = join_paths(nice_datadir, 'gtk-doc', 'html')
+
+ignore_headers = [
+ 'conncheck.h',
+ 'discovery.h',
+ 'stream.h',
+ 'component.h',
+ 'agent-priv.h',
+ 'iostream.h',
+ 'inputstream.h',
+ 'outputstream.h',
+ 'gstnice.h',
+ 'gstnicesrc.h',
+ 'gstnicesink.h',
+ 'md5.h',
+ 'sha1.h',
+ 'stunhmac.h',
+ 'utils.h',
+ 'rand.h',
+ 'stun5389.h',
+ 'stuncrc32.h',
+ 'stund.h',
+ 'agent-signals-marshal.h',
+ 'win32_common.h',
+]
+
+gnome.gtkdoc('libnice',
+ main_xml: 'libnice-docs.xml',
+ namespace: 'nice',
+ mode: 'none',
+ src_dir: ['agent', 'stun'],
+ dependencies: libnice_dep,
+ scan_args: [
+ '--rebuild-types',
+ #'--deprecated-guards=G_DISABLE_DEPRECATED',
+ #'--ignore-decorators=' + '|'.join(ignore_decorators),
+ '--ignore-headers=' + ' '.join(ignore_headers),
+ ],
+ html_assets: [
+ 'states.png',
+ ],
+ fixxref_args:[
+ '--html-dir=' + docpath,
+ ],
+ mkdb_args: [ # not sure if these need to be specified explicitly here
+ '--xml-mode',
+ '--output-format=xml',
+ '--name-space=Nice',
+ ],
+ install: true)
+
+# If we ever need to regenerate this diagram.
+# Since it’s not expected to change much, let’s not depend on GraphViz to
+# build the docs (that's also why we don't use find_program('dot') here)
+run_target('update-states.png',
+ command: ['dot',
+ '-Tpng',
+ '-o', join_paths(meson.current_source_dir(), 'states.png'),
+ '-Gsize=9.6,2.9!',
+ '-Gdpi=200',
+ files('states.gv')])
--- /dev/null
+/* libnice state transition diagram for NiceComponentState. */
+digraph NiceComponentState {
+ rankdir=TB;
+ node [shape = doublecircle]; DISCONNECTED;
+ node [shape = circle];
+
+ /* Colour the normal control flow in green. */
+ DISCONNECTED -> GATHERING [ label = "nice_agent_gather_candidates()", color = chartreuse3 ];
+ GATHERING -> CONNECTING [ label = "nice_agent_set_remote_candidates()", color = chartreuse3 ];
+ CONNECTING -> CONNECTED [ label = "At least one candidate pair succeeds", color = chartreuse3 ];
+ CONNECTED -> READY [ label = "All candidate pairs checks finished", color = chartreuse3 ];
+
+ READY -> CONNECTED [ label = "Selected candidate pair fails" ];
+
+ FAILED -> CONNECTING [ label = "nice_agent_set_remote_candidates()" ];
+
+ DISCONNECTED -> CONNECTING [ label = "nice_agent_set_remote_candidates()" ];
+
+ /* Colour the failure paths in grey. */
+ DISCONNECTED -> FAILED [ label = "Failure", color = gray ];
+ GATHERING -> FAILED [ label = "Failure", color = gray ];
+ CONNECTING -> FAILED [ label = "Failure", color = gray ];
+ CONNECTED -> FAILED [ label = "Failure", color = gray ];
+ READY -> FAILED [ label = "Failure", color = gray ];
+}
--- /dev/null
+#
+# Makefile.am for the Nice Glib ICE library
+#
+# (C) 2006, 2007 Collabora Ltd.
+# (C) 2006, 2007 Nokia Corporation. All rights reserved.
+#
+# Licensed under MPL 1.1/LGPL 2.1. See file COPYING.
+
+include $(top_srcdir)/common.mk
+
+AM_CFLAGS = \
+ -I $(top_srcdir) \
+ -I $(top_srcdir)/agent \
+ -I $(top_srcdir)/random \
+ -I $(top_srcdir)/socket \
+ -I $(top_srcdir)/stun \
+ $(LIBNICE_CFLAGS) \
+ $(GLIB_CFLAGS) \
+ $(GUPNP_CFLAGS)
+
+noinst_PROGRAMS = simple-example threaded-example sdp-example
+
+simple_example_SOURCES = simple-example.c
+simple_example_LDADD = $(top_builddir)/agent/libagent.la \
+ $(GLIB_LIBS) $(GUPNP_LIBS)
+
+threaded_example_SOURCES = threaded-example.c
+threaded_example_LDADD = $(top_builddir)/agent/libagent.la \
+ $(GLIB_LIBS) $(GUPNP_LIBS)
+
+sdp_example_SOURCES = sdp-example.c
+sdp_example_LDADD = $(top_builddir)/agent/libagent.la \
+ $(GLIB_LIBS) $(GUPNP_LIBS)
+
+EXTRA_DIST = meson.build
--- /dev/null
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+#
+# Makefile.am for the Nice Glib ICE library
+#
+# (C) 2006, 2007 Collabora Ltd.
+# (C) 2006, 2007 Nokia Corporation. All rights reserved.
+#
+# Licensed under MPL 1.1/LGPL 2.1. See file COPYING.
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+noinst_PROGRAMS = simple-example$(EXEEXT) threaded-example$(EXEEXT) \
+ sdp-example$(EXEEXT)
+subdir = examples
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/as-compiler-flag.m4 \
+ $(top_srcdir)/m4/ax_check_openssl.m4 \
+ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/introspection.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+PROGRAMS = $(noinst_PROGRAMS)
+am_sdp_example_OBJECTS = sdp-example.$(OBJEXT)
+sdp_example_OBJECTS = $(am_sdp_example_OBJECTS)
+am__DEPENDENCIES_1 =
+sdp_example_DEPENDENCIES = $(top_builddir)/agent/libagent.la \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+am_simple_example_OBJECTS = simple-example.$(OBJEXT)
+simple_example_OBJECTS = $(am_simple_example_OBJECTS)
+simple_example_DEPENDENCIES = $(top_builddir)/agent/libagent.la \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+am_threaded_example_OBJECTS = threaded-example.$(OBJEXT)
+threaded_example_OBJECTS = $(am_threaded_example_OBJECTS)
+threaded_example_DEPENDENCIES = $(top_builddir)/agent/libagent.la \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/sdp-example.Po \
+ ./$(DEPDIR)/simple-example.Po ./$(DEPDIR)/threaded-example.Po
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(sdp_example_SOURCES) $(simple_example_SOURCES) \
+ $(threaded_example_SOURCES)
+DIST_SOURCES = $(sdp_example_SOURCES) $(simple_example_SOURCES) \
+ $(threaded_example_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/common.mk \
+ $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+pkgincludedir = $(includedir)/nice
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCACHE_DISABLE = @CCACHE_DISABLE@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GST010_CFLAGS = @GST010_CFLAGS@
+GST010_LIBS = @GST010_LIBS@
+GST_CFLAGS = @GST_CFLAGS@
+GST_CHECK_CFLAGS = @GST_CHECK_CFLAGS@
+GST_CHECK_LIBS = @GST_CHECK_LIBS@
+GST_LIBS = @GST_LIBS@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@
+GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@
+GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@
+GTKDOC_MKPDF = @GTKDOC_MKPDF@
+GTKDOC_REBASE = @GTKDOC_REBASE@
+GUPNP_CFLAGS = @GUPNP_CFLAGS@
+GUPNP_LIBS = @GUPNP_LIBS@
+GUPNP_PACKAGES = @GUPNP_PACKAGES@
+GUPNP_PACKAGES_PRIVATE = @GUPNP_PACKAGES_PRIVATE@
+GUPNP_PACKAGES_PUBLIC = @GUPNP_PACKAGES_PUBLIC@
+HAVE_GUPNP = @HAVE_GUPNP@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@
+INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@
+INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@
+INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@
+INTROSPECTION_LIBS = @INTROSPECTION_LIBS@
+INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@
+INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
+INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBNICE_CFLAGS = @LIBNICE_CFLAGS@
+LIBNICE_LT_LDFLAGS = @LIBNICE_LT_LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBRT = @LIBRT@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NICE_PACKAGES_PRIVATE = @NICE_PACKAGES_PRIVATE@
+NICE_PACKAGES_PUBLIC = @NICE_PACKAGES_PUBLIC@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_INCLUDES = @OPENSSL_INCLUDES@
+OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+UPNP_ENABLED = @UPNP_ENABLED@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gstplugin010dir = @gstplugin010dir@
+gstplugindir = @gstplugindir@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+CLEANFILES = *.gcno *.gcda
+LOG_DRIVER = $(top_srcdir)/scripts/valgrind-test-driver
+AM_CFLAGS = \
+ -I $(top_srcdir) \
+ -I $(top_srcdir)/agent \
+ -I $(top_srcdir)/random \
+ -I $(top_srcdir)/socket \
+ -I $(top_srcdir)/stun \
+ $(LIBNICE_CFLAGS) \
+ $(GLIB_CFLAGS) \
+ $(GUPNP_CFLAGS)
+
+simple_example_SOURCES = simple-example.c
+simple_example_LDADD = $(top_builddir)/agent/libagent.la \
+ $(GLIB_LIBS) $(GUPNP_LIBS)
+
+threaded_example_SOURCES = threaded-example.c
+threaded_example_LDADD = $(top_builddir)/agent/libagent.la \
+ $(GLIB_LIBS) $(GUPNP_LIBS)
+
+sdp_example_SOURCES = sdp-example.c
+sdp_example_LDADD = $(top_builddir)/agent/libagent.la \
+ $(GLIB_LIBS) $(GUPNP_LIBS)
+
+EXTRA_DIST = meson.build
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/common.mk $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu examples/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu examples/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+$(top_srcdir)/common.mk $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstPROGRAMS:
+ @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+
+sdp-example$(EXEEXT): $(sdp_example_OBJECTS) $(sdp_example_DEPENDENCIES) $(EXTRA_sdp_example_DEPENDENCIES)
+ @rm -f sdp-example$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(sdp_example_OBJECTS) $(sdp_example_LDADD) $(LIBS)
+
+simple-example$(EXEEXT): $(simple_example_OBJECTS) $(simple_example_DEPENDENCIES) $(EXTRA_simple_example_DEPENDENCIES)
+ @rm -f simple-example$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(simple_example_OBJECTS) $(simple_example_LDADD) $(LIBS)
+
+threaded-example$(EXEEXT): $(threaded_example_OBJECTS) $(threaded_example_DEPENDENCIES) $(EXTRA_threaded_example_DEPENDENCIES)
+ @rm -f threaded-example$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(threaded_example_OBJECTS) $(threaded_example_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sdp-example.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/simple-example.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/threaded-example.Po@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/sdp-example.Po
+ -rm -f ./$(DEPDIR)/simple-example.Po
+ -rm -f ./$(DEPDIR)/threaded-example.Po
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f ./$(DEPDIR)/sdp-example.Po
+ -rm -f ./$(DEPDIR)/simple-example.Po
+ -rm -f ./$(DEPDIR)/threaded-example.Po
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-noinstPROGRAMS cscopelist-am \
+ ctags ctags-am distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags tags-am uninstall uninstall-am
+
+.PRECIOUS: Makefile
+
+
+check-valgrind:
+ $(MAKE) TESTS_ENVIRONMENT="USE_VALGRIND=1 " check
+
+.PHONY: check-valgrind
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null
+examples = ['simple-example', 'threaded-example', 'sdp-example']
+
+foreach ex : examples
+ executable(ex, '@0@.c'.format(ex),
+ include_directories: nice_incs,
+ dependencies: gio_deps + [libnice_dep, gupnp_igd_dep],
+ install: false)
+endforeach
--- /dev/null
+/*
+ * Copyright 2013 University of Chicago
+ * Contact: Bryce Allen
+ * Copyright 2013 Collabora Ltd.
+ * Contact: Youness Alaoui
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+/*
+ * Example using libnice to negotiate a UDP connection between two clients,
+ * possibly on the same network or behind different NATs and/or stateful
+ * firewalls.
+ *
+ * Build:
+ * gcc -o sdp-example sdp-example.c `pkg-config --cflags --libs nice`
+ *
+ * Run two clients, one controlling and one controlled:
+ * sdp-example 0 $(host -4 -t A stun.stunprotocol.org | awk '{ print $4 }')
+ * sdp-example 1 $(host -4 -t A stun.stunprotocol.org | awk '{ print $4 }')
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <agent.h>
+
+#include <gio/gnetworking.h>
+
+static GMainLoop *gloop;
+static gchar *stun_addr = NULL;
+static guint stun_port;
+static gboolean controlling;
+static gboolean exit_thread, candidate_gathering_done, negotiation_done;
+static GMutex gather_mutex, negotiate_mutex;
+static GCond gather_cond, negotiate_cond;
+
+static const gchar *state_name[] = {"disconnected", "gathering", "connecting",
+ "connected", "ready", "failed"};
+
+static void cb_candidate_gathering_done(NiceAgent *agent, guint stream_id,
+ gpointer data);
+static void cb_component_state_changed(NiceAgent *agent, guint stream_id,
+ guint component_id, guint state,
+ gpointer data);
+static void cb_nice_recv(NiceAgent *agent, guint stream_id, guint component_id,
+ guint len, gchar *buf, gpointer data);
+
+static void * example_thread(void *data);
+
+int
+main(int argc, char *argv[])
+{
+ GThread *gexamplethread;
+
+ // Parse arguments
+ if (argc > 4 || argc < 2 || argv[1][1] != '\0') {
+ fprintf(stderr, "Usage: %s 0|1 stun_addr [stun_port]\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+ controlling = argv[1][0] - '0';
+ if (controlling != 0 && controlling != 1) {
+ fprintf(stderr, "Usage: %s 0|1 stun_addr [stun_port]\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ if (argc > 2) {
+ stun_addr = argv[2];
+ if (argc > 3)
+ stun_port = atoi(argv[3]);
+ else
+ stun_port = 3478;
+
+ g_debug("Using stun server '[%s]:%u'\n", stun_addr, stun_port);
+ }
+
+ g_networking_init();
+
+ gloop = g_main_loop_new(NULL, FALSE);
+
+ // Run the mainloop and the example thread
+ exit_thread = FALSE;
+ gexamplethread = g_thread_new("example thread", &example_thread, NULL);
+ g_main_loop_run (gloop);
+ exit_thread = TRUE;
+
+ g_thread_join (gexamplethread);
+ g_main_loop_unref(gloop);
+
+ return EXIT_SUCCESS;
+}
+
+static void *
+example_thread(void *data)
+{
+ NiceAgent *agent;
+ GIOChannel* io_stdin;
+ guint stream_id;
+ gchar *line = NULL;
+ gchar *sdp, *sdp64;
+
+#ifdef G_OS_WIN32
+ io_stdin = g_io_channel_win32_new_fd(_fileno(stdin));
+#else
+ io_stdin = g_io_channel_unix_new(fileno(stdin));
+#endif
+ g_io_channel_set_flags(io_stdin, G_IO_FLAG_NONBLOCK, NULL);
+
+ // Create the nice agent
+ agent = nice_agent_new(g_main_loop_get_context (gloop),
+ NICE_COMPATIBILITY_RFC5245);
+ if (agent == NULL)
+ g_error("Failed to create agent");
+
+ // Set the STUN settings and controlling mode
+ if (stun_addr) {
+ g_object_set(agent, "stun-server", stun_addr, NULL);
+ g_object_set(agent, "stun-server-port", stun_port, NULL);
+ }
+ g_object_set(agent, "controlling-mode", controlling, NULL);
+
+ // Connect to the signals
+ g_signal_connect(agent, "candidate-gathering-done",
+ G_CALLBACK(cb_candidate_gathering_done), NULL);
+ g_signal_connect(agent, "component-state-changed",
+ G_CALLBACK(cb_component_state_changed), NULL);
+
+ // Create a new stream with one component
+ stream_id = nice_agent_add_stream(agent, 1);
+ if (stream_id == 0)
+ g_error("Failed to add stream");
+ nice_agent_set_stream_name (agent, stream_id, "text");
+
+ // Attach to the component to receive the data
+ // Without this call, candidates cannot be gathered
+ nice_agent_attach_recv(agent, stream_id, 1,
+ g_main_loop_get_context (gloop), cb_nice_recv, NULL);
+
+ // Start gathering local candidates
+ if (!nice_agent_gather_candidates(agent, stream_id))
+ g_error("Failed to start candidate gathering");
+
+ g_debug("waiting for candidate-gathering-done signal...");
+
+ g_mutex_lock(&gather_mutex);
+ while (!exit_thread && !candidate_gathering_done)
+ g_cond_wait(&gather_cond, &gather_mutex);
+ g_mutex_unlock(&gather_mutex);
+ if (exit_thread)
+ goto end;
+
+ // Candidate gathering is done. Send our local candidates on stdout
+ sdp = nice_agent_generate_local_sdp (agent);
+ printf("Generated SDP from agent :\n%s\n\n", sdp);
+ printf("Copy the following line to remote client:\n");
+ sdp64 = g_base64_encode ((const guchar *)sdp, strlen (sdp));
+ printf("\n %s\n", sdp64);
+ g_free (sdp);
+ g_free (sdp64);
+
+ // Listen on stdin for the remote candidate list
+ printf("Enter remote data (single line, no wrapping):\n");
+ printf("> ");
+ fflush (stdout);
+ while (!exit_thread) {
+ GIOStatus s = g_io_channel_read_line (io_stdin, &line, NULL, NULL, NULL);
+ if (s == G_IO_STATUS_NORMAL) {
+ gsize sdp_len;
+
+ sdp = (gchar *) g_base64_decode (line, &sdp_len);
+ // Parse remote candidate list and set it on the agent
+ if (sdp && nice_agent_parse_remote_sdp (agent, sdp) > 0) {
+ g_free (sdp);
+ g_free (line);
+ break;
+ } else {
+ fprintf(stderr, "ERROR: failed to parse remote data\n");
+ printf("Enter remote data (single line, no wrapping):\n");
+ printf("> ");
+ fflush (stdout);
+ }
+ g_free (sdp);
+ g_free (line);
+ } else if (s == G_IO_STATUS_AGAIN) {
+ g_usleep (100000);
+ }
+ }
+
+ g_debug("waiting for state READY or FAILED signal...");
+ g_mutex_lock(&negotiate_mutex);
+ while (!exit_thread && !negotiation_done)
+ g_cond_wait(&negotiate_cond, &negotiate_mutex);
+ g_mutex_unlock(&negotiate_mutex);
+ if (exit_thread)
+ goto end;
+
+ // Listen to stdin and send data written to it
+ printf("\nSend lines to remote (Ctrl-D to quit):\n");
+ printf("> ");
+ fflush (stdout);
+ while (!exit_thread) {
+ GIOStatus s = g_io_channel_read_line (io_stdin, &line, NULL, NULL, NULL);
+
+ if (s == G_IO_STATUS_NORMAL) {
+ nice_agent_send(agent, stream_id, 1, strlen(line), line);
+ g_free (line);
+ printf("> ");
+ fflush (stdout);
+ } else if (s == G_IO_STATUS_AGAIN) {
+ g_usleep (100000);
+ } else {
+ // Ctrl-D was pressed.
+ nice_agent_send(agent, stream_id, 1, 1, "\0");
+ break;
+ }
+ }
+
+end:
+ g_object_unref(agent);
+ g_io_channel_unref (io_stdin);
+ g_main_loop_quit (gloop);
+
+ return NULL;
+}
+
+static void
+cb_candidate_gathering_done(NiceAgent *agent, guint stream_id,
+ gpointer data)
+{
+ g_debug("SIGNAL candidate gathering done\n");
+
+ g_mutex_lock(&gather_mutex);
+ candidate_gathering_done = TRUE;
+ g_cond_signal(&gather_cond);
+ g_mutex_unlock(&gather_mutex);
+}
+
+static void
+cb_component_state_changed(NiceAgent *agent, guint stream_id,
+ guint component_id, guint state,
+ gpointer data)
+{
+ g_debug("SIGNAL: state changed %d %d %s[%d]\n",
+ stream_id, component_id, state_name[state], state);
+
+ if (state == NICE_COMPONENT_STATE_READY) {
+ g_mutex_lock(&negotiate_mutex);
+ negotiation_done = TRUE;
+ g_cond_signal(&negotiate_cond);
+ g_mutex_unlock(&negotiate_mutex);
+ } else if (state == NICE_COMPONENT_STATE_FAILED) {
+ g_main_loop_quit (gloop);
+ }
+}
+
+static void
+cb_nice_recv(NiceAgent *agent, guint stream_id, guint component_id,
+ guint len, gchar *buf, gpointer data)
+{
+ if (len == 1 && buf[0] == '\0')
+ g_main_loop_quit (gloop);
+
+ printf("%.*s", len, buf);
+ fflush(stdout);
+}
--- /dev/null
+/*
+ * Copyright 2013 University of Chicago
+ * Contact: Bryce Allen
+ * Copyright 2013 Collabora Ltd.
+ * Contact: Youness Alaoui
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+/*
+ * Example using libnice to negotiate a UDP connection between two clients,
+ * possibly on the same network or behind different NATs and/or stateful
+ * firewalls.
+ *
+ * Build:
+ * gcc -o simple-example simple-example.c `pkg-config --cflags --libs nice`
+ *
+ * Run two clients, one controlling and one controlled:
+ * simple-example 0 $(host -4 -t A stun.stunprotocol.org | awk '{ print $4 }')
+ * simple-example 1 $(host -4 -t A stun.stunprotocol.org | awk '{ print $4 }')
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <agent.h>
+
+#include <gio/gnetworking.h>
+
+static GMainLoop *gloop;
+static GIOChannel* io_stdin;
+static guint stream_id;
+
+static const gchar *candidate_type_name[] = {"host", "srflx", "prflx", "relay"};
+
+static const gchar *state_name[] = {"disconnected", "gathering", "connecting",
+ "connected", "ready", "failed"};
+
+static int print_local_data(NiceAgent *agent, guint stream_id,
+ guint component_id);
+static int parse_remote_data(NiceAgent *agent, guint stream_id,
+ guint component_id, char *line);
+static void cb_candidate_gathering_done(NiceAgent *agent, guint stream_id,
+ gpointer data);
+static void cb_new_selected_pair(NiceAgent *agent, guint stream_id,
+ guint component_id, gchar *lfoundation,
+ gchar *rfoundation, gpointer data);
+static void cb_component_state_changed(NiceAgent *agent, guint stream_id,
+ guint component_id, guint state,
+ gpointer data);
+static void cb_nice_recv(NiceAgent *agent, guint stream_id, guint component_id,
+ guint len, gchar *buf, gpointer data);
+static gboolean stdin_remote_info_cb (GIOChannel *source, GIOCondition cond,
+ gpointer data);
+static gboolean stdin_send_data_cb (GIOChannel *source, GIOCondition cond,
+ gpointer data);
+
+int
+main(int argc, char *argv[])
+{
+ NiceAgent *agent;
+ gchar *stun_addr = NULL;
+ guint stun_port = 0;
+ gboolean controlling;
+
+ // Parse arguments
+ if (argc > 4 || argc < 2 || argv[1][1] != '\0') {
+ fprintf(stderr, "Usage: %s 0|1 stun_addr [stun_port]\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+ controlling = argv[1][0] - '0';
+ if (controlling != 0 && controlling != 1) {
+ fprintf(stderr, "Usage: %s 0|1 stun_addr [stun_port]\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ if (argc > 2) {
+ stun_addr = argv[2];
+ if (argc > 3)
+ stun_port = atoi(argv[3]);
+ else
+ stun_port = 3478;
+
+ g_debug("Using stun server '[%s]:%u'\n", stun_addr, stun_port);
+ }
+
+ g_networking_init();
+
+ gloop = g_main_loop_new(NULL, FALSE);
+#ifdef G_OS_WIN32
+ io_stdin = g_io_channel_win32_new_fd(_fileno(stdin));
+#else
+ io_stdin = g_io_channel_unix_new(fileno(stdin));
+#endif
+
+ // Create the nice agent
+ agent = nice_agent_new(g_main_loop_get_context (gloop),
+ NICE_COMPATIBILITY_RFC5245);
+ if (agent == NULL)
+ g_error("Failed to create agent");
+
+ // Set the STUN settings and controlling mode
+ if (stun_addr) {
+ g_object_set(agent, "stun-server", stun_addr, NULL);
+ g_object_set(agent, "stun-server-port", stun_port, NULL);
+ }
+ g_object_set(agent, "controlling-mode", controlling, NULL);
+
+ // Connect to the signals
+ g_signal_connect(agent, "candidate-gathering-done",
+ G_CALLBACK(cb_candidate_gathering_done), NULL);
+ g_signal_connect(agent, "new-selected-pair",
+ G_CALLBACK(cb_new_selected_pair), NULL);
+ g_signal_connect(agent, "component-state-changed",
+ G_CALLBACK(cb_component_state_changed), NULL);
+
+ // Create a new stream with one component
+ stream_id = nice_agent_add_stream(agent, 1);
+ if (stream_id == 0)
+ g_error("Failed to add stream");
+
+ // Attach to the component to receive the data
+ // Without this call, candidates cannot be gathered
+ nice_agent_attach_recv(agent, stream_id, 1,
+ g_main_loop_get_context (gloop), cb_nice_recv, NULL);
+
+ // Start gathering local candidates
+ if (!nice_agent_gather_candidates(agent, stream_id))
+ g_error("Failed to start candidate gathering");
+
+ g_debug("waiting for candidate-gathering-done signal...");
+
+ // Run the mainloop. Everything else will happen asynchronously
+ // when the candidates are done gathering.
+ g_main_loop_run (gloop);
+
+ g_main_loop_unref(gloop);
+ g_object_unref(agent);
+ g_io_channel_unref (io_stdin);
+
+ return EXIT_SUCCESS;
+}
+
+static void
+cb_candidate_gathering_done(NiceAgent *agent, guint _stream_id,
+ gpointer data)
+{
+
+ g_debug("SIGNAL candidate gathering done\n");
+
+ // Candidate gathering is done. Send our local candidates on stdout
+ printf("Copy this line to remote client:\n");
+ printf("\n ");
+ print_local_data(agent, _stream_id, 1);
+ printf("\n");
+
+ // Listen on stdin for the remote candidate list
+ printf("Enter remote data (single line, no wrapping):\n");
+ g_io_add_watch(io_stdin, G_IO_IN, stdin_remote_info_cb, agent);
+ printf("> ");
+ fflush (stdout);
+}
+
+static gboolean
+stdin_remote_info_cb (GIOChannel *source, GIOCondition cond,
+ gpointer data)
+{
+ NiceAgent *agent = data;
+ gchar *line = NULL;
+ int rval;
+ gboolean ret = TRUE;
+
+ if (g_io_channel_read_line (source, &line, NULL, NULL, NULL) ==
+ G_IO_STATUS_NORMAL) {
+
+ // Parse remote candidate list and set it on the agent
+ rval = parse_remote_data(agent, stream_id, 1, line);
+ if (rval == EXIT_SUCCESS) {
+ // Return FALSE so we stop listening to stdin since we parsed the
+ // candidates correctly
+ ret = FALSE;
+ g_debug("waiting for state READY or FAILED signal...");
+ } else {
+ fprintf(stderr, "ERROR: failed to parse remote data\n");
+ printf("Enter remote data (single line, no wrapping):\n");
+ printf("> ");
+ fflush (stdout);
+ }
+ g_free (line);
+ }
+
+ return ret;
+}
+
+static void
+cb_component_state_changed(NiceAgent *agent, guint _stream_id,
+ guint component_id, guint state,
+ gpointer data)
+{
+
+ g_debug("SIGNAL: state changed %d %d %s[%d]\n",
+ _stream_id, component_id, state_name[state], state);
+
+ if (state == NICE_COMPONENT_STATE_CONNECTED) {
+ NiceCandidate *local, *remote;
+
+ // Get current selected candidate pair and print IP address used
+ if (nice_agent_get_selected_pair (agent, _stream_id, component_id,
+ &local, &remote)) {
+ gchar ipaddr[INET6_ADDRSTRLEN];
+
+ nice_address_to_string(&local->addr, ipaddr);
+ printf("\nNegotiation complete: ([%s]:%d,",
+ ipaddr, nice_address_get_port(&local->addr));
+ nice_address_to_string(&remote->addr, ipaddr);
+ printf(" [%s]:%d)\n", ipaddr, nice_address_get_port(&remote->addr));
+ }
+
+ // Listen to stdin and send data written to it
+ printf("\nSend lines to remote (Ctrl-D to quit):\n");
+ g_io_add_watch(io_stdin, G_IO_IN, stdin_send_data_cb, agent);
+ printf("> ");
+ fflush (stdout);
+ } else if (state == NICE_COMPONENT_STATE_FAILED) {
+ g_main_loop_quit (gloop);
+ }
+}
+
+static gboolean
+stdin_send_data_cb (GIOChannel *source, GIOCondition cond,
+ gpointer data)
+{
+ NiceAgent *agent = data;
+ gchar *line = NULL;
+
+ if (g_io_channel_read_line (source, &line, NULL, NULL, NULL) ==
+ G_IO_STATUS_NORMAL) {
+ nice_agent_send(agent, stream_id, 1, strlen(line), line);
+ g_free (line);
+ printf("> ");
+ fflush (stdout);
+ } else {
+ nice_agent_send(agent, stream_id, 1, 1, "\0");
+ // Ctrl-D was pressed.
+ g_main_loop_quit (gloop);
+ }
+
+ return TRUE;
+}
+
+static void
+cb_new_selected_pair(NiceAgent *agent, guint _stream_id,
+ guint component_id, gchar *lfoundation,
+ gchar *rfoundation, gpointer data)
+{
+ g_debug("SIGNAL: selected pair %s %s", lfoundation, rfoundation);
+}
+
+static void
+cb_nice_recv(NiceAgent *agent, guint _stream_id, guint component_id,
+ guint len, gchar *buf, gpointer data)
+{
+ if (len == 1 && buf[0] == '\0')
+ g_main_loop_quit (gloop);
+ printf("%.*s", len, buf);
+ fflush(stdout);
+}
+
+static NiceCandidate *
+parse_candidate(char *scand, guint _stream_id)
+{
+ NiceCandidate *cand = NULL;
+ NiceCandidateType ntype;
+ gchar **tokens = NULL;
+ guint i;
+
+ tokens = g_strsplit (scand, ",", 5);
+ for (i = 0; tokens[i]; i++);
+ if (i != 5)
+ goto end;
+
+ for (i = 0; i < G_N_ELEMENTS (candidate_type_name); i++) {
+ if (strcmp(tokens[4], candidate_type_name[i]) == 0) {
+ ntype = i;
+ break;
+ }
+ }
+ if (i == G_N_ELEMENTS (candidate_type_name))
+ goto end;
+
+ cand = nice_candidate_new(ntype);
+ cand->component_id = 1;
+ cand->stream_id = _stream_id;
+ cand->transport = NICE_CANDIDATE_TRANSPORT_UDP;
+ strncpy(cand->foundation, tokens[0], NICE_CANDIDATE_MAX_FOUNDATION);
+ cand->foundation[NICE_CANDIDATE_MAX_FOUNDATION - 1] = 0;
+ cand->priority = atoi (tokens[1]);
+
+ if (!nice_address_set_from_string(&cand->addr, tokens[2])) {
+ g_message("failed to parse addr: %s", tokens[2]);
+ nice_candidate_free(cand);
+ cand = NULL;
+ goto end;
+ }
+
+ nice_address_set_port(&cand->addr, atoi (tokens[3]));
+
+ end:
+ g_strfreev(tokens);
+
+ return cand;
+}
+
+
+static int
+print_local_data (NiceAgent *agent, guint _stream_id, guint component_id)
+{
+ int result = EXIT_FAILURE;
+ gchar *local_ufrag = NULL;
+ gchar *local_password = NULL;
+ gchar ipaddr[INET6_ADDRSTRLEN];
+ GSList *cands = NULL, *item;
+
+ if (!nice_agent_get_local_credentials(agent, _stream_id,
+ &local_ufrag, &local_password))
+ goto end;
+
+ cands = nice_agent_get_local_candidates(agent, _stream_id, component_id);
+ if (cands == NULL)
+ goto end;
+
+ printf("%s %s", local_ufrag, local_password);
+
+ for (item = cands; item; item = item->next) {
+ NiceCandidate *c = (NiceCandidate *)item->data;
+
+ nice_address_to_string(&c->addr, ipaddr);
+
+ // (foundation),(prio),(addr),(port),(type)
+ printf(" %s,%u,%s,%u,%s",
+ c->foundation,
+ c->priority,
+ ipaddr,
+ nice_address_get_port(&c->addr),
+ candidate_type_name[c->type]);
+ }
+ printf("\n");
+ result = EXIT_SUCCESS;
+
+ end:
+ if (local_ufrag)
+ g_free(local_ufrag);
+ if (local_password)
+ g_free(local_password);
+ if (cands)
+ g_slist_free_full(cands, (GDestroyNotify)&nice_candidate_free);
+
+ return result;
+}
+
+
+static int
+parse_remote_data(NiceAgent *agent, guint _stream_id,
+ guint component_id, char *line)
+{
+ GSList *remote_candidates = NULL;
+ gchar **line_argv = NULL;
+ const gchar *ufrag = NULL;
+ const gchar *passwd = NULL;
+ int result = EXIT_FAILURE;
+ int i;
+
+ line_argv = g_strsplit_set (line, " \t\n", 0);
+ for (i = 0; line_argv && line_argv[i]; i++) {
+ if (strlen (line_argv[i]) == 0)
+ continue;
+
+ // first two args are remote ufrag and password
+ if (!ufrag) {
+ ufrag = line_argv[i];
+ } else if (!passwd) {
+ passwd = line_argv[i];
+ } else {
+ // Remaining args are serialized canidates (at least one is required)
+ NiceCandidate *c = parse_candidate(line_argv[i], _stream_id);
+
+ if (c == NULL) {
+ g_message("failed to parse candidate: %s", line_argv[i]);
+ goto end;
+ }
+ remote_candidates = g_slist_prepend(remote_candidates, c);
+ }
+ }
+ if (ufrag == NULL || passwd == NULL || remote_candidates == NULL) {
+ g_message("line must have at least ufrag, password, and one candidate");
+ goto end;
+ }
+
+ if (!nice_agent_set_remote_credentials(agent, _stream_id, ufrag, passwd)) {
+ g_message("failed to set remote credentials");
+ goto end;
+ }
+
+ // Note: this will trigger the start of negotiation.
+ if (nice_agent_set_remote_candidates(agent, _stream_id, component_id,
+ remote_candidates) < 1) {
+ g_message("failed to set remote candidates");
+ goto end;
+ }
+
+ result = EXIT_SUCCESS;
+
+ end:
+ if (line_argv != NULL)
+ g_strfreev(line_argv);
+ if (remote_candidates != NULL)
+ g_slist_free_full(remote_candidates, (GDestroyNotify)&nice_candidate_free);
+
+ return result;
+}
--- /dev/null
+/*
+ * Copyright 2013 University of Chicago
+ * Contact: Bryce Allen
+ * Copyright 2013 Collabora Ltd.
+ * Contact: Youness Alaoui
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+/*
+ * Example using libnice to negotiate a UDP connection between two clients,
+ * possibly on the same network or behind different NATs and/or stateful
+ * firewalls.
+ *
+ * Build:
+ * gcc -o threaded-example threaded-example.c `pkg-config --cflags --libs nice`
+ *
+ * Run two clients, one controlling and one controlled:
+ * threaded-example 0 $(host -4 -t A stun.stunprotocol.org | awk '{ print $4 }')
+ * threaded-example 1 $(host -4 -t A stun.stunprotocol.org | awk '{ print $4 }')
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <agent.h>
+
+#include <gio/gnetworking.h>
+
+static GMainLoop *gloop;
+static gchar *stun_addr = NULL;
+static guint stun_port;
+static gboolean controlling;
+static gboolean exit_thread, candidate_gathering_done, negotiation_done;
+static GMutex gather_mutex, negotiate_mutex;
+static GCond gather_cond, negotiate_cond;
+
+static const gchar *candidate_type_name[] = {"host", "srflx", "prflx", "relay"};
+
+static const gchar *state_name[] = {"disconnected", "gathering", "connecting",
+ "connected", "ready", "failed"};
+
+static int print_local_data(NiceAgent *agent, guint stream_id,
+ guint component_id);
+static int parse_remote_data(NiceAgent *agent, guint stream_id,
+ guint component_id, char *line);
+static void cb_candidate_gathering_done(NiceAgent *agent, guint stream_id,
+ gpointer data);
+static void cb_new_selected_pair(NiceAgent *agent, guint stream_id,
+ guint component_id, gchar *lfoundation,
+ gchar *rfoundation, gpointer data);
+static void cb_component_state_changed(NiceAgent *agent, guint stream_id,
+ guint component_id, guint state,
+ gpointer data);
+static void cb_nice_recv(NiceAgent *agent, guint stream_id, guint component_id,
+ guint len, gchar *buf, gpointer data);
+
+static void * example_thread(void *data);
+
+int
+main(int argc, char *argv[])
+{
+ GThread *gexamplethread;
+
+ // Parse arguments
+ if (argc > 4 || argc < 2 || argv[1][1] != '\0') {
+ fprintf(stderr, "Usage: %s 0|1 stun_addr [stun_port]\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+ controlling = argv[1][0] - '0';
+ if (controlling != 0 && controlling != 1) {
+ fprintf(stderr, "Usage: %s 0|1 stun_addr [stun_port]\n", argv[0]);
+ return EXIT_FAILURE;
+ }
+
+ if (argc > 2) {
+ stun_addr = argv[2];
+ if (argc > 3)
+ stun_port = atoi(argv[3]);
+ else
+ stun_port = 3478;
+
+ g_debug("Using stun server '[%s]:%u'\n", stun_addr, stun_port);
+ }
+
+ g_networking_init();
+
+ gloop = g_main_loop_new(NULL, FALSE);
+
+ // Run the mainloop and the example thread
+ exit_thread = FALSE;
+ gexamplethread = g_thread_new("example thread", &example_thread, NULL);
+ g_main_loop_run (gloop);
+ exit_thread = TRUE;
+
+ g_thread_join (gexamplethread);
+ g_main_loop_unref(gloop);
+
+ return EXIT_SUCCESS;
+}
+
+static void *
+example_thread(void *data)
+{
+ NiceAgent *agent;
+ NiceCandidate *local, *remote;
+ GIOChannel* io_stdin;
+ guint stream_id;
+ gchar *line = NULL;
+ int rval;
+
+#ifdef G_OS_WIN32
+ io_stdin = g_io_channel_win32_new_fd(_fileno(stdin));
+#else
+ io_stdin = g_io_channel_unix_new(fileno(stdin));
+#endif
+ g_io_channel_set_flags (io_stdin, G_IO_FLAG_NONBLOCK, NULL);
+
+ // Create the nice agent
+ agent = nice_agent_new(g_main_loop_get_context (gloop),
+ NICE_COMPATIBILITY_RFC5245);
+ if (agent == NULL)
+ g_error("Failed to create agent");
+
+ // Set the STUN settings and controlling mode
+ if (stun_addr) {
+ g_object_set(agent, "stun-server", stun_addr, NULL);
+ g_object_set(agent, "stun-server-port", stun_port, NULL);
+ }
+ g_object_set(agent, "controlling-mode", controlling, NULL);
+
+ // Connect to the signals
+ g_signal_connect(agent, "candidate-gathering-done",
+ G_CALLBACK(cb_candidate_gathering_done), NULL);
+ g_signal_connect(agent, "new-selected-pair",
+ G_CALLBACK(cb_new_selected_pair), NULL);
+ g_signal_connect(agent, "component-state-changed",
+ G_CALLBACK(cb_component_state_changed), NULL);
+
+ // Create a new stream with one component
+ stream_id = nice_agent_add_stream(agent, 1);
+ if (stream_id == 0)
+ g_error("Failed to add stream");
+
+ // Attach to the component to receive the data
+ // Without this call, candidates cannot be gathered
+ nice_agent_attach_recv(agent, stream_id, 1,
+ g_main_loop_get_context (gloop), cb_nice_recv, NULL);
+
+ // Start gathering local candidates
+ if (!nice_agent_gather_candidates(agent, stream_id))
+ g_error("Failed to start candidate gathering");
+
+ g_debug("waiting for candidate-gathering-done signal...");
+
+ g_mutex_lock(&gather_mutex);
+ while (!exit_thread && !candidate_gathering_done)
+ g_cond_wait(&gather_cond, &gather_mutex);
+ g_mutex_unlock(&gather_mutex);
+ if (exit_thread)
+ goto end;
+
+ // Candidate gathering is done. Send our local candidates on stdout
+ printf("Copy this line to remote client:\n");
+ printf("\n ");
+ print_local_data(agent, stream_id, 1);
+ printf("\n");
+
+ // Listen on stdin for the remote candidate list
+ printf("Enter remote data (single line, no wrapping):\n");
+ printf("> ");
+ fflush (stdout);
+ while (!exit_thread) {
+ GIOStatus s = g_io_channel_read_line (io_stdin, &line, NULL, NULL, NULL);
+ if (s == G_IO_STATUS_NORMAL) {
+ // Parse remote candidate list and set it on the agent
+ rval = parse_remote_data(agent, stream_id, 1, line);
+ if (rval == EXIT_SUCCESS) {
+ g_free (line);
+ break;
+ } else {
+ fprintf(stderr, "ERROR: failed to parse remote data\n");
+ printf("Enter remote data (single line, no wrapping):\n");
+ printf("> ");
+ fflush (stdout);
+ }
+ g_free (line);
+ } else if (s == G_IO_STATUS_AGAIN) {
+ g_usleep (100000);
+ }
+ }
+
+ g_debug("waiting for state READY or FAILED signal...");
+ g_mutex_lock(&negotiate_mutex);
+ while (!exit_thread && !negotiation_done)
+ g_cond_wait(&negotiate_cond, &negotiate_mutex);
+ g_mutex_unlock(&negotiate_mutex);
+ if (exit_thread)
+ goto end;
+
+ // Get current selected candidate pair and print IP address used
+ if (nice_agent_get_selected_pair (agent, stream_id, 1,
+ &local, &remote)) {
+ gchar ipaddr[INET6_ADDRSTRLEN];
+
+ nice_address_to_string(&local->addr, ipaddr);
+ printf("\nNegotiation complete: ([%s]:%d,",
+ ipaddr, nice_address_get_port(&local->addr));
+ nice_address_to_string(&remote->addr, ipaddr);
+ printf(" [%s]:%d)\n", ipaddr, nice_address_get_port(&remote->addr));
+ }
+
+ // Listen to stdin and send data written to it
+ printf("\nSend lines to remote (Ctrl-D to quit):\n");
+ printf("> ");
+ fflush (stdout);
+ while (!exit_thread) {
+ GIOStatus s = g_io_channel_read_line (io_stdin, &line, NULL, NULL, NULL);
+ if (s == G_IO_STATUS_NORMAL) {
+ nice_agent_send(agent, stream_id, 1, strlen(line), line);
+ g_free (line);
+ printf("> ");
+ fflush (stdout);
+ } else if (s == G_IO_STATUS_AGAIN) {
+ g_usleep (100000);
+ } else {
+ // Ctrl-D was pressed.
+ nice_agent_send(agent, stream_id, 1, 1, "\0");
+ break;
+ }
+ }
+
+end:
+ g_io_channel_unref (io_stdin);
+ g_object_unref(agent);
+ g_main_loop_quit (gloop);
+
+ return NULL;
+}
+
+static void
+cb_candidate_gathering_done(NiceAgent *agent, guint stream_id,
+ gpointer data)
+{
+ g_debug("SIGNAL candidate gathering done\n");
+
+ g_mutex_lock(&gather_mutex);
+ candidate_gathering_done = TRUE;
+ g_cond_signal(&gather_cond);
+ g_mutex_unlock(&gather_mutex);
+}
+
+static void
+cb_component_state_changed(NiceAgent *agent, guint stream_id,
+ guint component_id, guint state,
+ gpointer data)
+{
+ g_debug("SIGNAL: state changed %d %d %s[%d]\n",
+ stream_id, component_id, state_name[state], state);
+
+ if (state == NICE_COMPONENT_STATE_READY) {
+ g_mutex_lock(&negotiate_mutex);
+ negotiation_done = TRUE;
+ g_cond_signal(&negotiate_cond);
+ g_mutex_unlock(&negotiate_mutex);
+ } else if (state == NICE_COMPONENT_STATE_FAILED) {
+ g_main_loop_quit (gloop);
+ }
+}
+
+
+static void
+cb_new_selected_pair(NiceAgent *agent, guint stream_id,
+ guint component_id, gchar *lfoundation,
+ gchar *rfoundation, gpointer data)
+{
+ g_debug("SIGNAL: selected pair %s %s", lfoundation, rfoundation);
+}
+
+static void
+cb_nice_recv(NiceAgent *agent, guint stream_id, guint component_id,
+ guint len, gchar *buf, gpointer data)
+{
+ if (len == 1 && buf[0] == '\0')
+ g_main_loop_quit (gloop);
+
+ printf("%.*s", len, buf);
+ fflush(stdout);
+}
+
+static NiceCandidate *
+parse_candidate(char *scand, guint stream_id)
+{
+ NiceCandidate *cand = NULL;
+ NiceCandidateType ntype;
+ gchar **tokens = NULL;
+ guint i;
+
+ tokens = g_strsplit (scand, ",", 5);
+ for (i = 0; tokens[i]; i++);
+ if (i != 5)
+ goto end;
+
+ for (i = 0; i < G_N_ELEMENTS (candidate_type_name); i++) {
+ if (strcmp(tokens[4], candidate_type_name[i]) == 0) {
+ ntype = i;
+ break;
+ }
+ }
+ if (i == G_N_ELEMENTS (candidate_type_name))
+ goto end;
+
+ cand = nice_candidate_new(ntype);
+ cand->component_id = 1;
+ cand->stream_id = stream_id;
+ cand->transport = NICE_CANDIDATE_TRANSPORT_UDP;
+ strncpy(cand->foundation, tokens[0], NICE_CANDIDATE_MAX_FOUNDATION);
+ cand->foundation[NICE_CANDIDATE_MAX_FOUNDATION - 1] = 0;
+ cand->priority = atoi (tokens[1]);
+
+ if (!nice_address_set_from_string(&cand->addr, tokens[2])) {
+ g_message("failed to parse addr: %s", tokens[2]);
+ nice_candidate_free(cand);
+ cand = NULL;
+ goto end;
+ }
+
+ nice_address_set_port(&cand->addr, atoi (tokens[3]));
+
+ end:
+ g_strfreev(tokens);
+
+ return cand;
+}
+
+
+static int
+print_local_data (NiceAgent *agent, guint stream_id, guint component_id)
+{
+ int result = EXIT_FAILURE;
+ gchar *local_ufrag = NULL;
+ gchar *local_password = NULL;
+ gchar ipaddr[INET6_ADDRSTRLEN];
+ GSList *cands = NULL, *item;
+
+ if (!nice_agent_get_local_credentials(agent, stream_id,
+ &local_ufrag, &local_password))
+ goto end;
+
+ cands = nice_agent_get_local_candidates(agent, stream_id, component_id);
+ if (cands == NULL)
+ goto end;
+
+ printf("%s %s", local_ufrag, local_password);
+
+ for (item = cands; item; item = item->next) {
+ NiceCandidate *c = (NiceCandidate *)item->data;
+
+ nice_address_to_string(&c->addr, ipaddr);
+
+ // (foundation),(prio),(addr),(port),(type)
+ printf(" %s,%u,%s,%u,%s",
+ c->foundation,
+ c->priority,
+ ipaddr,
+ nice_address_get_port(&c->addr),
+ candidate_type_name[c->type]);
+ }
+ printf("\n");
+ result = EXIT_SUCCESS;
+
+ end:
+ if (local_ufrag)
+ g_free(local_ufrag);
+ if (local_password)
+ g_free(local_password);
+ if (cands)
+ g_slist_free_full(cands, (GDestroyNotify)&nice_candidate_free);
+
+ return result;
+}
+
+
+static int
+parse_remote_data(NiceAgent *agent, guint stream_id,
+ guint component_id, char *line)
+{
+ GSList *remote_candidates = NULL;
+ gchar **line_argv = NULL;
+ const gchar *ufrag = NULL;
+ const gchar *passwd = NULL;
+ int result = EXIT_FAILURE;
+ int i;
+
+ line_argv = g_strsplit_set (line, " \t\n", 0);
+ for (i = 0; line_argv && line_argv[i]; i++) {
+ if (strlen (line_argv[i]) == 0)
+ continue;
+
+ // first two args are remote ufrag and password
+ if (!ufrag) {
+ ufrag = line_argv[i];
+ } else if (!passwd) {
+ passwd = line_argv[i];
+ } else {
+ // Remaining args are serialized canidates (at least one is required)
+ NiceCandidate *c = parse_candidate(line_argv[i], stream_id);
+
+ if (c == NULL) {
+ g_message("failed to parse candidate: %s", line_argv[i]);
+ goto end;
+ }
+ remote_candidates = g_slist_prepend(remote_candidates, c);
+ }
+ }
+ if (ufrag == NULL || passwd == NULL || remote_candidates == NULL) {
+ g_message("line must have at least ufrag, password, and one candidate");
+ goto end;
+ }
+
+ if (!nice_agent_set_remote_credentials(agent, stream_id, ufrag, passwd)) {
+ g_message("failed to set remote credentials");
+ goto end;
+ }
+
+ // Note: this will trigger the start of negotiation.
+ if (nice_agent_set_remote_candidates(agent, stream_id, component_id,
+ remote_candidates) < 1) {
+ g_message("failed to set remote candidates");
+ goto end;
+ }
+
+ result = EXIT_SUCCESS;
+
+ end:
+ if (line_argv != NULL)
+ g_strfreev(line_argv);
+ if (remote_candidates != NULL)
+ g_slist_free_full(remote_candidates, (GDestroyNotify)&nice_candidate_free);
+
+ return result;
+}
--- /dev/null
+#
+# Makefile.am for the Nice Glib ICE library
+#
+# (C) 2006, 2007 Collabora Ltd.
+# (C) 2006, 2007 Nokia Corporation. All rights reserved.
+#
+# Licensed under MPL 1.1/LGPL 2.1. See file COPYING.
+
+AM_CFLAGS = $(LIBNICE_CFLAGS) \
+ -I $(top_srcdir) \
+ -I $(top_srcdir)/socket \
+ -I $(top_srcdir)/agent \
+ -I $(top_srcdir)/random \
+ -I $(top_srcdir)/stun
+
+COMMON_LIBADD = \
+ $(top_builddir)/nice/libnice.la
+
+# libgstnice
+
+if WITH_GSTREAMER
+gstplugin_LTLIBRARIES = libgstnice.la
+
+libgstnice_la_CFLAGS = $(AM_CFLAGS) $(GST_CFLAGS) -DGST_USE_UNSTABLE_API
+
+libgstnice_la_SOURCES = \
+ gstnicesrc.h \
+ gstnicesrc.c \
+ gstnicesink.h \
+ gstnicesink.c \
+ gstnice.h \
+ gstnice.c
+
+libgstnice_la_LIBADD = $(COMMON_LIBADD) $(GST_LIBS)
+
+libgstnice_la_LDFLAGS = -module -avoid-version -no-undefined
+endif
+
+
+if WITH_GSTREAMER010
+gstplugin010_LTLIBRARIES = libgstnice010.la
+
+libgstnice010_la_CFLAGS = $(AM_CFLAGS) $(GST010_CFLAGS)
+
+libgstnice010_la_SOURCES = \
+ gstnicesrc.h \
+ gstnicesrc.c \
+ gstnicesink.h \
+ gstnicesink.c \
+ gstnice.h \
+ gstnice.c
+
+libgstnice010_la_LIBADD = $(COMMON_LIBADD) $(GST010_LIBS)
+
+libgstnice010_la_LDFLAGS = -module -avoid-version -no-undefined
+endif
+
+EXTRA_DIST = meson.build
--- /dev/null
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+#
+# Makefile.am for the Nice Glib ICE library
+#
+# (C) 2006, 2007 Collabora Ltd.
+# (C) 2006, 2007 Nokia Corporation. All rights reserved.
+#
+# Licensed under MPL 1.1/LGPL 2.1. See file COPYING.
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = gst
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/as-compiler-flag.m4 \
+ $(top_srcdir)/m4/ax_check_openssl.m4 \
+ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/introspection.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(gstplugindir)" \
+ "$(DESTDIR)$(gstplugin010dir)"
+LTLIBRARIES = $(gstplugin_LTLIBRARIES) $(gstplugin010_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+@WITH_GSTREAMER_TRUE@libgstnice_la_DEPENDENCIES = $(COMMON_LIBADD) \
+@WITH_GSTREAMER_TRUE@ $(am__DEPENDENCIES_1)
+am__libgstnice_la_SOURCES_DIST = gstnicesrc.h gstnicesrc.c \
+ gstnicesink.h gstnicesink.c gstnice.h gstnice.c
+@WITH_GSTREAMER_TRUE@am_libgstnice_la_OBJECTS = \
+@WITH_GSTREAMER_TRUE@ libgstnice_la-gstnicesrc.lo \
+@WITH_GSTREAMER_TRUE@ libgstnice_la-gstnicesink.lo \
+@WITH_GSTREAMER_TRUE@ libgstnice_la-gstnice.lo
+libgstnice_la_OBJECTS = $(am_libgstnice_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+libgstnice_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libgstnice_la_CFLAGS) \
+ $(CFLAGS) $(libgstnice_la_LDFLAGS) $(LDFLAGS) -o $@
+@WITH_GSTREAMER_TRUE@am_libgstnice_la_rpath = -rpath $(gstplugindir)
+@WITH_GSTREAMER010_TRUE@libgstnice010_la_DEPENDENCIES = \
+@WITH_GSTREAMER010_TRUE@ $(COMMON_LIBADD) $(am__DEPENDENCIES_1)
+am__libgstnice010_la_SOURCES_DIST = gstnicesrc.h gstnicesrc.c \
+ gstnicesink.h gstnicesink.c gstnice.h gstnice.c
+@WITH_GSTREAMER010_TRUE@am_libgstnice010_la_OBJECTS = \
+@WITH_GSTREAMER010_TRUE@ libgstnice010_la-gstnicesrc.lo \
+@WITH_GSTREAMER010_TRUE@ libgstnice010_la-gstnicesink.lo \
+@WITH_GSTREAMER010_TRUE@ libgstnice010_la-gstnice.lo
+libgstnice010_la_OBJECTS = $(am_libgstnice010_la_OBJECTS)
+libgstnice010_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(libgstnice010_la_CFLAGS) $(CFLAGS) \
+ $(libgstnice010_la_LDFLAGS) $(LDFLAGS) -o $@
+@WITH_GSTREAMER010_TRUE@am_libgstnice010_la_rpath = -rpath \
+@WITH_GSTREAMER010_TRUE@ $(gstplugin010dir)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/libgstnice010_la-gstnice.Plo \
+ ./$(DEPDIR)/libgstnice010_la-gstnicesink.Plo \
+ ./$(DEPDIR)/libgstnice010_la-gstnicesrc.Plo \
+ ./$(DEPDIR)/libgstnice_la-gstnice.Plo \
+ ./$(DEPDIR)/libgstnice_la-gstnicesink.Plo \
+ ./$(DEPDIR)/libgstnice_la-gstnicesrc.Plo
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(libgstnice_la_SOURCES) $(libgstnice010_la_SOURCES)
+DIST_SOURCES = $(am__libgstnice_la_SOURCES_DIST) \
+ $(am__libgstnice010_la_SOURCES_DIST)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCACHE_DISABLE = @CCACHE_DISABLE@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GST010_CFLAGS = @GST010_CFLAGS@
+GST010_LIBS = @GST010_LIBS@
+GST_CFLAGS = @GST_CFLAGS@
+GST_CHECK_CFLAGS = @GST_CHECK_CFLAGS@
+GST_CHECK_LIBS = @GST_CHECK_LIBS@
+GST_LIBS = @GST_LIBS@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@
+GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@
+GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@
+GTKDOC_MKPDF = @GTKDOC_MKPDF@
+GTKDOC_REBASE = @GTKDOC_REBASE@
+GUPNP_CFLAGS = @GUPNP_CFLAGS@
+GUPNP_LIBS = @GUPNP_LIBS@
+GUPNP_PACKAGES = @GUPNP_PACKAGES@
+GUPNP_PACKAGES_PRIVATE = @GUPNP_PACKAGES_PRIVATE@
+GUPNP_PACKAGES_PUBLIC = @GUPNP_PACKAGES_PUBLIC@
+HAVE_GUPNP = @HAVE_GUPNP@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@
+INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@
+INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@
+INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@
+INTROSPECTION_LIBS = @INTROSPECTION_LIBS@
+INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@
+INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
+INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBNICE_CFLAGS = @LIBNICE_CFLAGS@
+LIBNICE_LT_LDFLAGS = @LIBNICE_LT_LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBRT = @LIBRT@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NICE_PACKAGES_PRIVATE = @NICE_PACKAGES_PRIVATE@
+NICE_PACKAGES_PUBLIC = @NICE_PACKAGES_PUBLIC@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_INCLUDES = @OPENSSL_INCLUDES@
+OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+UPNP_ENABLED = @UPNP_ENABLED@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gstplugin010dir = @gstplugin010dir@
+gstplugindir = @gstplugindir@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_CFLAGS = $(LIBNICE_CFLAGS) \
+ -I $(top_srcdir) \
+ -I $(top_srcdir)/socket \
+ -I $(top_srcdir)/agent \
+ -I $(top_srcdir)/random \
+ -I $(top_srcdir)/stun
+
+COMMON_LIBADD = \
+ $(top_builddir)/nice/libnice.la
+
+
+# libgstnice
+@WITH_GSTREAMER_TRUE@gstplugin_LTLIBRARIES = libgstnice.la
+@WITH_GSTREAMER_TRUE@libgstnice_la_CFLAGS = $(AM_CFLAGS) $(GST_CFLAGS) -DGST_USE_UNSTABLE_API
+@WITH_GSTREAMER_TRUE@libgstnice_la_SOURCES = \
+@WITH_GSTREAMER_TRUE@ gstnicesrc.h \
+@WITH_GSTREAMER_TRUE@ gstnicesrc.c \
+@WITH_GSTREAMER_TRUE@ gstnicesink.h \
+@WITH_GSTREAMER_TRUE@ gstnicesink.c \
+@WITH_GSTREAMER_TRUE@ gstnice.h \
+@WITH_GSTREAMER_TRUE@ gstnice.c
+
+@WITH_GSTREAMER_TRUE@libgstnice_la_LIBADD = $(COMMON_LIBADD) $(GST_LIBS)
+@WITH_GSTREAMER_TRUE@libgstnice_la_LDFLAGS = -module -avoid-version -no-undefined
+@WITH_GSTREAMER010_TRUE@gstplugin010_LTLIBRARIES = libgstnice010.la
+@WITH_GSTREAMER010_TRUE@libgstnice010_la_CFLAGS = $(AM_CFLAGS) $(GST010_CFLAGS)
+@WITH_GSTREAMER010_TRUE@libgstnice010_la_SOURCES = \
+@WITH_GSTREAMER010_TRUE@ gstnicesrc.h \
+@WITH_GSTREAMER010_TRUE@ gstnicesrc.c \
+@WITH_GSTREAMER010_TRUE@ gstnicesink.h \
+@WITH_GSTREAMER010_TRUE@ gstnicesink.c \
+@WITH_GSTREAMER010_TRUE@ gstnice.h \
+@WITH_GSTREAMER010_TRUE@ gstnice.c
+
+@WITH_GSTREAMER010_TRUE@libgstnice010_la_LIBADD = $(COMMON_LIBADD) $(GST010_LIBS)
+@WITH_GSTREAMER010_TRUE@libgstnice010_la_LDFLAGS = -module -avoid-version -no-undefined
+EXTRA_DIST = meson.build
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu gst/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu gst/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+install-gstpluginLTLIBRARIES: $(gstplugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ @list='$(gstplugin_LTLIBRARIES)'; test -n "$(gstplugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(gstplugindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(gstplugindir)" || exit 1; \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(gstplugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(gstplugindir)"; \
+ }
+
+uninstall-gstpluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(gstplugin_LTLIBRARIES)'; test -n "$(gstplugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(gstplugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(gstplugindir)/$$f"; \
+ done
+
+clean-gstpluginLTLIBRARIES:
+ -test -z "$(gstplugin_LTLIBRARIES)" || rm -f $(gstplugin_LTLIBRARIES)
+ @list='$(gstplugin_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+install-gstplugin010LTLIBRARIES: $(gstplugin010_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ @list='$(gstplugin010_LTLIBRARIES)'; test -n "$(gstplugin010dir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(gstplugin010dir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(gstplugin010dir)" || exit 1; \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(gstplugin010dir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(gstplugin010dir)"; \
+ }
+
+uninstall-gstplugin010LTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(gstplugin010_LTLIBRARIES)'; test -n "$(gstplugin010dir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(gstplugin010dir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(gstplugin010dir)/$$f"; \
+ done
+
+clean-gstplugin010LTLIBRARIES:
+ -test -z "$(gstplugin010_LTLIBRARIES)" || rm -f $(gstplugin010_LTLIBRARIES)
+ @list='$(gstplugin010_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+libgstnice.la: $(libgstnice_la_OBJECTS) $(libgstnice_la_DEPENDENCIES) $(EXTRA_libgstnice_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libgstnice_la_LINK) $(am_libgstnice_la_rpath) $(libgstnice_la_OBJECTS) $(libgstnice_la_LIBADD) $(LIBS)
+
+libgstnice010.la: $(libgstnice010_la_OBJECTS) $(libgstnice010_la_DEPENDENCIES) $(EXTRA_libgstnice010_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libgstnice010_la_LINK) $(am_libgstnice010_la_rpath) $(libgstnice010_la_OBJECTS) $(libgstnice010_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstnice010_la-gstnice.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstnice010_la-gstnicesink.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstnice010_la-gstnicesrc.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstnice_la-gstnice.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstnice_la-gstnicesink.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgstnice_la-gstnicesrc.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+libgstnice_la-gstnicesrc.lo: gstnicesrc.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstnice_la_CFLAGS) $(CFLAGS) -MT libgstnice_la-gstnicesrc.lo -MD -MP -MF $(DEPDIR)/libgstnice_la-gstnicesrc.Tpo -c -o libgstnice_la-gstnicesrc.lo `test -f 'gstnicesrc.c' || echo '$(srcdir)/'`gstnicesrc.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstnice_la-gstnicesrc.Tpo $(DEPDIR)/libgstnice_la-gstnicesrc.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstnicesrc.c' object='libgstnice_la-gstnicesrc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstnice_la_CFLAGS) $(CFLAGS) -c -o libgstnice_la-gstnicesrc.lo `test -f 'gstnicesrc.c' || echo '$(srcdir)/'`gstnicesrc.c
+
+libgstnice_la-gstnicesink.lo: gstnicesink.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstnice_la_CFLAGS) $(CFLAGS) -MT libgstnice_la-gstnicesink.lo -MD -MP -MF $(DEPDIR)/libgstnice_la-gstnicesink.Tpo -c -o libgstnice_la-gstnicesink.lo `test -f 'gstnicesink.c' || echo '$(srcdir)/'`gstnicesink.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstnice_la-gstnicesink.Tpo $(DEPDIR)/libgstnice_la-gstnicesink.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstnicesink.c' object='libgstnice_la-gstnicesink.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstnice_la_CFLAGS) $(CFLAGS) -c -o libgstnice_la-gstnicesink.lo `test -f 'gstnicesink.c' || echo '$(srcdir)/'`gstnicesink.c
+
+libgstnice_la-gstnice.lo: gstnice.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstnice_la_CFLAGS) $(CFLAGS) -MT libgstnice_la-gstnice.lo -MD -MP -MF $(DEPDIR)/libgstnice_la-gstnice.Tpo -c -o libgstnice_la-gstnice.lo `test -f 'gstnice.c' || echo '$(srcdir)/'`gstnice.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstnice_la-gstnice.Tpo $(DEPDIR)/libgstnice_la-gstnice.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstnice.c' object='libgstnice_la-gstnice.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstnice_la_CFLAGS) $(CFLAGS) -c -o libgstnice_la-gstnice.lo `test -f 'gstnice.c' || echo '$(srcdir)/'`gstnice.c
+
+libgstnice010_la-gstnicesrc.lo: gstnicesrc.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstnice010_la_CFLAGS) $(CFLAGS) -MT libgstnice010_la-gstnicesrc.lo -MD -MP -MF $(DEPDIR)/libgstnice010_la-gstnicesrc.Tpo -c -o libgstnice010_la-gstnicesrc.lo `test -f 'gstnicesrc.c' || echo '$(srcdir)/'`gstnicesrc.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstnice010_la-gstnicesrc.Tpo $(DEPDIR)/libgstnice010_la-gstnicesrc.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstnicesrc.c' object='libgstnice010_la-gstnicesrc.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstnice010_la_CFLAGS) $(CFLAGS) -c -o libgstnice010_la-gstnicesrc.lo `test -f 'gstnicesrc.c' || echo '$(srcdir)/'`gstnicesrc.c
+
+libgstnice010_la-gstnicesink.lo: gstnicesink.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstnice010_la_CFLAGS) $(CFLAGS) -MT libgstnice010_la-gstnicesink.lo -MD -MP -MF $(DEPDIR)/libgstnice010_la-gstnicesink.Tpo -c -o libgstnice010_la-gstnicesink.lo `test -f 'gstnicesink.c' || echo '$(srcdir)/'`gstnicesink.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstnice010_la-gstnicesink.Tpo $(DEPDIR)/libgstnice010_la-gstnicesink.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstnicesink.c' object='libgstnice010_la-gstnicesink.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstnice010_la_CFLAGS) $(CFLAGS) -c -o libgstnice010_la-gstnicesink.lo `test -f 'gstnicesink.c' || echo '$(srcdir)/'`gstnicesink.c
+
+libgstnice010_la-gstnice.lo: gstnice.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstnice010_la_CFLAGS) $(CFLAGS) -MT libgstnice010_la-gstnice.lo -MD -MP -MF $(DEPDIR)/libgstnice010_la-gstnice.Tpo -c -o libgstnice010_la-gstnice.lo `test -f 'gstnice.c' || echo '$(srcdir)/'`gstnice.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgstnice010_la-gstnice.Tpo $(DEPDIR)/libgstnice010_la-gstnice.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gstnice.c' object='libgstnice010_la-gstnice.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgstnice010_la_CFLAGS) $(CFLAGS) -c -o libgstnice010_la-gstnice.lo `test -f 'gstnice.c' || echo '$(srcdir)/'`gstnice.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(gstplugindir)" "$(DESTDIR)$(gstplugin010dir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-gstplugin010LTLIBRARIES \
+ clean-gstpluginLTLIBRARIES clean-libtool mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/libgstnice010_la-gstnice.Plo
+ -rm -f ./$(DEPDIR)/libgstnice010_la-gstnicesink.Plo
+ -rm -f ./$(DEPDIR)/libgstnice010_la-gstnicesrc.Plo
+ -rm -f ./$(DEPDIR)/libgstnice_la-gstnice.Plo
+ -rm -f ./$(DEPDIR)/libgstnice_la-gstnicesink.Plo
+ -rm -f ./$(DEPDIR)/libgstnice_la-gstnicesrc.Plo
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-gstplugin010LTLIBRARIES \
+ install-gstpluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f ./$(DEPDIR)/libgstnice010_la-gstnice.Plo
+ -rm -f ./$(DEPDIR)/libgstnice010_la-gstnicesink.Plo
+ -rm -f ./$(DEPDIR)/libgstnice010_la-gstnicesrc.Plo
+ -rm -f ./$(DEPDIR)/libgstnice_la-gstnice.Plo
+ -rm -f ./$(DEPDIR)/libgstnice_la-gstnicesink.Plo
+ -rm -f ./$(DEPDIR)/libgstnice_la-gstnicesrc.Plo
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-gstplugin010LTLIBRARIES \
+ uninstall-gstpluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-gstplugin010LTLIBRARIES \
+ clean-gstpluginLTLIBRARIES clean-libtool cscopelist-am ctags \
+ ctags-am distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-gstplugin010LTLIBRARIES \
+ install-gstpluginLTLIBRARIES install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags tags-am uninstall uninstall-am \
+ uninstall-gstplugin010LTLIBRARIES \
+ uninstall-gstpluginLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2006, 2007 Collabora Ltd.
+ * Contact: Dafydd Harries
+ * (C) 2006, 2007 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Dafydd Harries, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "gstnicesrc.h"
+#include "gstnicesink.h"
+
+static gboolean
+plugin_init (GstPlugin *plugin)
+{
+ if (!gst_element_register (plugin, "nicesrc",
+ GST_RANK_NONE, GST_TYPE_NICE_SRC))
+ return FALSE;
+
+ if (!gst_element_register (plugin, "nicesink",
+ GST_RANK_NONE, GST_TYPE_NICE_SINK))
+ return FALSE;
+
+ return TRUE;
+}
+
+#if GST_CHECK_VERSION (1,0,0)
+#define PLUGIN_NAME nice
+#else
+#define PLUGIN_NAME "nice"
+#endif
+
+GST_PLUGIN_DEFINE (
+ GST_VERSION_MAJOR,
+ GST_VERSION_MINOR,
+ PLUGIN_NAME,
+ "Interactive UDP connectivity establishment",
+ plugin_init, VERSION, "LGPL", PACKAGE_NAME,
+ "https://nice.freedesktop.org/");
+
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2006, 2007 Collabora Ltd.
+ * Contact: Dafydd Harries
+ * (C) 2006, 2007 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Dafydd Harries, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#include "gstnicesrc.h"
+#include "gstnicesink.h"
+
--- /dev/null
+
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2006, 2007 Collabora Ltd.
+ * Contact: Dafydd Harries
+ * (C) 2006, 2007 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Dafydd Harries, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "gstnicesink.h"
+
+
+GST_DEBUG_CATEGORY_STATIC (nicesink_debug);
+#define GST_CAT_DEFAULT nicesink_debug
+
+static GstFlowReturn
+gst_nice_sink_render (
+ GstBaseSink *basesink,
+ GstBuffer *buffer);
+#if GST_CHECK_VERSION (1,0,0)
+static GstFlowReturn
+gst_nice_sink_render_list (
+ GstBaseSink *basesink,
+ GstBufferList *buffer_list);
+#endif
+
+static gboolean
+gst_nice_sink_unlock (GstBaseSink *basesink);
+
+static gboolean
+gst_nice_sink_unlock_stop (GstBaseSink *basesink);
+
+static void
+_reliable_transport_writable (
+ NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ GstNiceSink *sink);
+
+static void
+gst_nice_sink_set_property (
+ GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+
+static void
+gst_nice_sink_get_property (
+ GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+
+static void
+gst_nice_sink_dispose (GObject *object);
+#if GST_CHECK_VERSION (1,0,0)
+static void
+gst_nice_sink_finalize (GObject *object);
+#endif
+
+static GstStateChangeReturn
+gst_nice_sink_change_state (
+ GstElement * element,
+ GstStateChange transition);
+
+static GstStaticPadTemplate gst_nice_sink_sink_template =
+GST_STATIC_PAD_TEMPLATE (
+ "sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS_ANY);
+
+G_DEFINE_TYPE (GstNiceSink, gst_nice_sink, GST_TYPE_BASE_SINK);
+
+enum
+{
+ PROP_AGENT = 1,
+ PROP_STREAM,
+ PROP_COMPONENT
+};
+
+static void
+gst_nice_sink_class_init (GstNiceSinkClass *klass)
+{
+ GstBaseSinkClass *gstbasesink_class;
+ GstElementClass *gstelement_class;
+ GObjectClass *gobject_class;
+
+ GST_DEBUG_CATEGORY_INIT (nicesink_debug, "nicesink",
+ 0, "libnice sink");
+
+ gstbasesink_class = (GstBaseSinkClass *) klass;
+ gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_nice_sink_render);
+#if GST_CHECK_VERSION (1,0,0)
+ gstbasesink_class->render_list = GST_DEBUG_FUNCPTR (gst_nice_sink_render_list);
+#endif
+ gstbasesink_class->unlock = GST_DEBUG_FUNCPTR (gst_nice_sink_unlock);
+ gstbasesink_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_nice_sink_unlock_stop);
+
+ gobject_class = (GObjectClass *) klass;
+ gobject_class->set_property = gst_nice_sink_set_property;
+ gobject_class->get_property = gst_nice_sink_get_property;
+ gobject_class->dispose = gst_nice_sink_dispose;
+#if GST_CHECK_VERSION (1,0,0)
+ gobject_class->finalize = gst_nice_sink_finalize;
+#endif
+
+ gstelement_class = (GstElementClass *) klass;
+ gstelement_class->change_state = gst_nice_sink_change_state;
+
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&gst_nice_sink_sink_template));
+#if GST_CHECK_VERSION (1,0,0)
+ gst_element_class_set_metadata (gstelement_class,
+#else
+ gst_element_class_set_details_simple (gstelement_class,
+#endif
+ "ICE sink",
+ "Sink",
+ "Interactive UDP connectivity establishment",
+ "Dafydd Harries <dafydd.harries@collabora.co.uk>");
+
+
+ g_object_class_install_property (gobject_class, PROP_AGENT,
+ g_param_spec_object (
+ "agent",
+ "Agent",
+ "The NiceAgent this source is bound to",
+ NICE_TYPE_AGENT,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_STREAM,
+ g_param_spec_uint (
+ "stream",
+ "Stream ID",
+ "The ID of the stream to read from",
+ 0,
+ G_MAXUINT,
+ 0,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_COMPONENT,
+ g_param_spec_uint (
+ "component",
+ "Component ID",
+ "The ID of the component to read from",
+ 0,
+ G_MAXUINT,
+ 0,
+ G_PARAM_READWRITE));
+}
+
+static void
+gst_nice_sink_init (GstNiceSink *sink)
+{
+#if GST_CHECK_VERSION (1,0,0)
+ guint max_mem;
+#endif
+
+ g_cond_init (&sink->writable_cond);
+
+#if GST_CHECK_VERSION (1,0,0)
+ /* pre-allocate OutputVector, MapInfo and OutputMessage arrays
+ * for use in the render and render_list functions */
+ max_mem = gst_buffer_get_max_memory ();
+
+ sink->n_vecs = max_mem;
+ sink->vecs = g_new (GOutputVector, sink->n_vecs);
+
+ sink->n_maps = max_mem;
+ sink->maps = g_new (GstMapInfo, sink->n_maps);
+
+ sink->n_messages = 1;
+ sink->messages = g_new (NiceOutputMessage, sink->n_messages);
+#endif
+}
+
+static void
+_reliable_transport_writable (NiceAgent *agent, guint stream_id,
+ guint component_id, GstNiceSink *sink)
+{
+ GST_OBJECT_LOCK (sink);
+ if (stream_id == sink->stream_id && component_id == sink->component_id) {
+ g_cond_broadcast (&sink->writable_cond);
+ }
+ GST_OBJECT_UNLOCK (sink);
+}
+
+#if GST_CHECK_VERSION (1,0,0)
+static gsize
+fill_vectors (GOutputVector * vecs, GstMapInfo * maps, guint n, GstBuffer * buf)
+{
+ GstMemory *mem;
+ gsize size = 0;
+ guint i;
+
+ g_assert (gst_buffer_n_memory (buf) == n);
+
+ for (i = 0; i < n; ++i) {
+ mem = gst_buffer_peek_memory (buf, i);
+ if (gst_memory_map (mem, &maps[i], GST_MAP_READ)) {
+ vecs[i].buffer = maps[i].data;
+ vecs[i].size = maps[i].size;
+ } else {
+ GST_WARNING ("Failed to map memory %p for reading", mem);
+ vecs[i].buffer = "";
+ vecs[i].size = 0;
+ }
+ size += vecs[i].size;
+ }
+
+ return size;
+}
+
+/* Buffer list code written by
+ * Tim-Philipp Müller <tim@centricular.com>
+ * taken from
+ * gst-plugins-good/gst/udp/gstmultiudpsink.c
+ */
+static GstFlowReturn
+gst_nice_sink_render_buffers (GstNiceSink * sink, GstBuffer ** buffers,
+ guint num_buffers, guint8 * mem_nums, guint total_mem_num)
+{
+ NiceOutputMessage *msgs;
+ GOutputVector *vecs;
+ GstMapInfo *map_infos;
+ guint i, mem;
+ guint written = 0;
+ gint ret;
+ GstFlowReturn flow_ret = GST_FLOW_OK;
+
+ GST_LOG_OBJECT (sink, "%u buffers, %u memories -> to be sent",
+ num_buffers, total_mem_num);
+
+ if (sink->n_vecs < total_mem_num) {
+ sink->n_vecs = GST_ROUND_UP_16 (total_mem_num);
+ g_free (sink->vecs);
+ sink->vecs = g_new (GOutputVector, sink->n_vecs);
+ }
+ vecs = sink->vecs;
+
+ if (sink->n_maps < total_mem_num) {
+ sink->n_maps = GST_ROUND_UP_16 (total_mem_num);
+ g_free (sink->maps);
+ sink->maps = g_new (GstMapInfo, sink->n_maps);
+ }
+ map_infos = sink->maps;
+
+ if (sink->n_messages < num_buffers) {
+ sink->n_messages = GST_ROUND_UP_16 (num_buffers);
+ g_free (sink->messages);
+ sink->messages = g_new (NiceOutputMessage, sink->n_messages);
+ }
+ msgs = sink->messages;
+
+ for (i = 0, mem = 0; i < num_buffers; ++i) {
+ fill_vectors (&vecs[mem], &map_infos[mem], mem_nums[i], buffers[i]);
+ msgs[i].buffers = &vecs[mem];
+ msgs[i].n_buffers = mem_nums[i];
+ mem += mem_nums[i];
+ }
+
+ GST_OBJECT_LOCK (sink);
+ do {
+ ret = nice_agent_send_messages_nonblocking(sink->agent, sink->stream_id,
+ sink->component_id, msgs + written, num_buffers - written, NULL, NULL);
+
+ if (ret > 0)
+ written += ret;
+
+ if (sink->reliable && written < num_buffers)
+ g_cond_wait (&sink->writable_cond, GST_OBJECT_GET_LOCK (sink));
+
+ if (sink->flushing) {
+ flow_ret = GST_FLOW_FLUSHING;
+ break;
+ }
+ } while (sink->reliable && written < num_buffers);
+ GST_OBJECT_UNLOCK (sink);
+
+ for (i = 0; i < mem; ++i)
+ gst_memory_unmap (map_infos[i].memory, &map_infos[i]);
+
+ return flow_ret;
+}
+#endif
+
+static GstFlowReturn
+gst_nice_sink_render (GstBaseSink *basesink, GstBuffer *buffer)
+{
+ GstNiceSink *nicesink = GST_NICE_SINK (basesink);
+ GstFlowReturn flow_ret = GST_FLOW_OK;
+#if GST_CHECK_VERSION (1,0,0)
+ guint8 n_mem;
+
+ n_mem = gst_buffer_n_memory (buffer);
+
+ if (n_mem > 0) {
+ flow_ret = gst_nice_sink_render_buffers (nicesink, &buffer, 1, &n_mem,
+ n_mem);
+ }
+
+#else
+ guint written = 0;
+ gint ret;
+ gchar *data = NULL;
+ guint size = 0;
+
+ data = (gchar *) GST_BUFFER_DATA (buffer);
+ size = GST_BUFFER_SIZE (buffer);
+
+ GST_OBJECT_LOCK (nicesink);
+ do {
+ ret = nice_agent_send (nicesink->agent, nicesink->stream_id,
+ nicesink->component_id, size - written, data + written);
+ if (ret > 0)
+ written += ret;
+
+ if (nicesink->reliable && written < size)
+ g_cond_wait (&nicesink->writable_cond, GST_OBJECT_GET_LOCK (nicesink));
+ if (nicesink->flushing) {
+ flow_ret = GST_FLOW_WRONG_STATE;
+ break;
+ }
+ } while (nicesink->reliable && written < size);
+ GST_OBJECT_UNLOCK (nicesink);
+
+#endif
+ return flow_ret;
+}
+
+#if GST_CHECK_VERSION (1,0,0)
+static GstFlowReturn
+gst_nice_sink_render_list (GstBaseSink *basesink, GstBufferList *buffer_list)
+{
+ GstNiceSink *nicesink = GST_NICE_SINK (basesink);
+ GstBuffer **buffers;
+ GstFlowReturn flow_ret = GST_FLOW_OK;
+ guint8 *mem_nums;
+ guint total_mems;
+ guint i, num_buffers;
+
+ num_buffers = gst_buffer_list_length (buffer_list);
+ if (num_buffers == 0)
+ goto no_data;
+
+ buffers = g_newa (GstBuffer *, num_buffers);
+ mem_nums = g_newa (guint8, num_buffers);
+ for (i = 0, total_mems = 0; i < num_buffers; ++i) {
+ buffers[i] = gst_buffer_list_get (buffer_list, i);
+ mem_nums[i] = gst_buffer_n_memory (buffers[i]);
+ total_mems += mem_nums[i];
+ }
+
+ flow_ret = gst_nice_sink_render_buffers (nicesink, buffers, num_buffers,
+ mem_nums, total_mems);
+
+ return flow_ret;
+
+no_data:
+ {
+ GST_LOG_OBJECT (nicesink, "empty buffer");
+ return GST_FLOW_OK;
+ }
+
+ return flow_ret;
+}
+#endif
+
+static gboolean gst_nice_sink_unlock (GstBaseSink *basesink)
+{
+ GstNiceSink *nicesink = GST_NICE_SINK (basesink);
+
+ GST_OBJECT_LOCK (nicesink);
+ nicesink->flushing = TRUE;
+ g_cond_broadcast (&nicesink->writable_cond);
+ GST_OBJECT_UNLOCK (nicesink);
+
+ return TRUE;
+}
+
+static gboolean gst_nice_sink_unlock_stop (GstBaseSink *basesink)
+{
+ GstNiceSink *nicesink = GST_NICE_SINK (basesink);
+
+ GST_OBJECT_LOCK (nicesink);
+ nicesink->flushing = FALSE;
+ GST_OBJECT_UNLOCK (nicesink);
+
+ return TRUE;
+}
+
+static void
+gst_nice_sink_dispose (GObject *object)
+{
+ GstNiceSink *sink = GST_NICE_SINK (object);
+
+ if (sink->agent && sink->writable_id)
+ g_signal_handler_disconnect (sink->agent, sink->writable_id);
+ sink->writable_id = 0;
+ g_clear_object (&sink->agent);
+
+ g_cond_clear (&sink->writable_cond);
+
+ G_OBJECT_CLASS (gst_nice_sink_parent_class)->dispose (object);
+}
+
+#if GST_CHECK_VERSION (1,0,0)
+static void
+gst_nice_sink_finalize (GObject *object)
+{
+ GstNiceSink *sink = GST_NICE_SINK (object);
+
+ g_free (sink->vecs);
+ sink->vecs = NULL;
+ sink->n_vecs = 0;
+ g_free (sink->maps);
+ sink->maps = NULL;
+ sink->n_maps = 0;
+ g_free (sink->messages);
+ sink->messages = NULL;
+ sink->n_messages = 0;
+
+ G_OBJECT_CLASS (gst_nice_sink_parent_class)->finalize (object);
+}
+#endif
+
+static void
+gst_nice_sink_set_property (
+ GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GstNiceSink *sink = GST_NICE_SINK (object);
+
+ switch (prop_id)
+ {
+ case PROP_AGENT:
+ if (sink->agent) {
+ GST_ERROR_OBJECT (object,
+ "Changing the agent on a nice sink not allowed");
+ } else {
+ sink->agent = g_value_dup_object (value);
+ g_object_get (sink->agent, "reliable", &sink->reliable, NULL);
+ if (sink->reliable)
+ sink->writable_id = g_signal_connect (sink->agent,
+ "reliable-transport-writable",
+ (GCallback) _reliable_transport_writable, sink);
+ }
+ break;
+
+ case PROP_STREAM:
+ GST_OBJECT_LOCK (sink);
+ sink->stream_id = g_value_get_uint (value);
+ GST_OBJECT_UNLOCK (sink);
+ break;
+
+ case PROP_COMPONENT:
+ {
+ guint new_component_id = g_value_get_uint (value);
+ GST_OBJECT_LOCK (sink);
+ if (sink->component_id != new_component_id) {
+ sink->component_id = new_component_id;
+ g_cond_broadcast (&sink->writable_cond);
+ }
+ GST_OBJECT_UNLOCK (sink);
+ }
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_nice_sink_get_property (
+ GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GstNiceSink *sink = GST_NICE_SINK (object);
+
+ switch (prop_id)
+ {
+ case PROP_AGENT:
+ g_value_set_object (value, sink->agent);
+ break;
+
+ case PROP_STREAM:
+ GST_OBJECT_LOCK (sink);
+ g_value_set_uint (value, sink->stream_id);
+ GST_OBJECT_UNLOCK (sink);
+ break;
+
+ case PROP_COMPONENT:
+ GST_OBJECT_LOCK (sink);
+ g_value_set_uint (value, sink->component_id);
+ GST_OBJECT_UNLOCK (sink);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GstStateChangeReturn
+gst_nice_sink_change_state (GstElement * element, GstStateChange transition)
+{
+ GstNiceSink *sink;
+ GstStateChangeReturn ret;
+
+ sink = GST_NICE_SINK (element);
+
+ switch (transition) {
+ case GST_STATE_CHANGE_NULL_TO_READY:
+ if (sink->agent == NULL)
+ {
+ GST_ERROR_OBJECT (element,
+ "Trying to start Nice sink without an agent set");
+ return GST_STATE_CHANGE_FAILURE;
+ }
+ else if (sink->stream_id == 0)
+ {
+ GST_ERROR_OBJECT (element,
+ "Trying to start Nice sink without a stream set");
+ return GST_STATE_CHANGE_FAILURE;
+ }
+ else if (sink->component_id == 0)
+ {
+ GST_ERROR_OBJECT (element,
+ "Trying to start Nice sink without a component set");
+ return GST_STATE_CHANGE_FAILURE;
+ }
+ break;
+ case GST_STATE_CHANGE_READY_TO_PAUSED:
+ case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+ case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+ case GST_STATE_CHANGE_PAUSED_TO_READY:
+ case GST_STATE_CHANGE_READY_TO_NULL:
+ default:
+ break;
+ }
+
+ ret = GST_ELEMENT_CLASS (gst_nice_sink_parent_class)->change_state (element,
+ transition);
+
+ return ret;
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2006, 2007 Collabora Ltd.
+ * Contact: Dafydd Harries
+ * (C) 2006, 2007 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Dafydd Harries, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef _GST_NICE_SINK_H
+#define _GST_NICE_SINK_H
+
+#include <gst/gst.h>
+#include <gst/base/gstbasesink.h>
+
+#include <nice/nice.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_NICE_SINK \
+ (gst_nice_sink_get_type())
+#define GST_NICE_SINK(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_NICE_SINK,GstNiceSink))
+#define GST_NICE_SINK_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_NICE_SINK,GstNiceSinkClass))
+#define GST_IS_NICE_SINK(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_NICE_SINK))
+#define GST_IS_NICE_SINK_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_NICE_SINK))
+
+typedef struct _GstNiceSink GstNiceSink;
+
+struct _GstNiceSink
+{
+ GstBaseSink parent;
+ GstPad *sinkpad;
+ NiceAgent *agent;
+ guint stream_id;
+ guint component_id;
+ gboolean reliable;
+ GCond writable_cond;
+ gulong writable_id;
+ gboolean flushing;
+
+#if GST_CHECK_VERSION (1,0,0)
+ /* pre-allocated scrap space for render function */
+ GOutputVector *vecs;
+ guint n_vecs;
+ GstMapInfo *maps;
+ guint n_maps;
+ NiceOutputMessage *messages;
+ guint n_messages;
+#endif
+};
+
+typedef struct _GstNiceSinkClass GstNiceSinkClass;
+
+struct _GstNiceSinkClass
+{
+ GstBaseSinkClass parent_class;
+};
+
+GType gst_nice_sink_get_type (void);
+
+G_END_DECLS
+
+#endif
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2006, 2007 Collabora Ltd.
+ * Contact: Dafydd Harries
+ * (C) 2006, 2007 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Dafydd Harries, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+
+#include "gstnicesrc.h"
+
+GST_DEBUG_CATEGORY_STATIC (nicesrc_debug);
+#define GST_CAT_DEFAULT nicesrc_debug
+
+
+#define BUFFER_SIZE (65536)
+
+static GstFlowReturn
+gst_nice_src_create (
+ GstPushSrc *basesrc,
+ GstBuffer **buffer);
+
+static gboolean
+gst_nice_src_unlock (
+ GstBaseSrc *basesrc);
+
+static gboolean
+gst_nice_src_unlock_stop (
+ GstBaseSrc *basesrc);
+
+static void
+gst_nice_src_set_property (
+ GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+
+static void
+gst_nice_src_get_property (
+ GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+
+
+static void
+gst_nice_src_dispose (GObject *object);
+
+static GstStateChangeReturn
+gst_nice_src_change_state (
+ GstElement * element,
+ GstStateChange transition);
+
+static GstStaticPadTemplate gst_nice_src_src_template =
+GST_STATIC_PAD_TEMPLATE (
+ "src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS_ANY);
+
+G_DEFINE_TYPE (GstNiceSrc, gst_nice_src, GST_TYPE_PUSH_SRC);
+
+enum
+{
+ PROP_AGENT = 1,
+ PROP_STREAM,
+ PROP_COMPONENT
+};
+
+
+static void
+gst_nice_src_class_init (GstNiceSrcClass *klass)
+{
+ GstPushSrcClass *gstpushsrc_class;
+ GstBaseSrcClass *gstbasesrc_class;
+ GstElementClass *gstelement_class;
+ GObjectClass *gobject_class;
+
+ GST_DEBUG_CATEGORY_INIT (nicesrc_debug, "nicesrc",
+ 0, "libnice source");
+
+ gstpushsrc_class = (GstPushSrcClass *) klass;
+ gstpushsrc_class->create = GST_DEBUG_FUNCPTR (gst_nice_src_create);
+
+ gstbasesrc_class = (GstBaseSrcClass *) klass;
+ gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_nice_src_unlock);
+ gstbasesrc_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_nice_src_unlock_stop);
+
+ gobject_class = (GObjectClass *) klass;
+ gobject_class->set_property = gst_nice_src_set_property;
+ gobject_class->get_property = gst_nice_src_get_property;
+ gobject_class->dispose = gst_nice_src_dispose;
+
+ gstelement_class = (GstElementClass *) klass;
+ gstelement_class->change_state = gst_nice_src_change_state;
+
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&gst_nice_src_src_template));
+#if GST_CHECK_VERSION (1,0,0)
+ gst_element_class_set_metadata (gstelement_class,
+#else
+ gst_element_class_set_details_simple (gstelement_class,
+#endif
+ "ICE source",
+ "Source",
+ "Interactive UDP connectivity establishment",
+ "Dafydd Harries <dafydd.harries@collabora.co.uk>");
+
+ g_object_class_install_property (gobject_class, PROP_AGENT,
+ g_param_spec_object (
+ "agent",
+ "Agent",
+ "The NiceAgent this source is bound to",
+ NICE_TYPE_AGENT,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_STREAM,
+ g_param_spec_uint (
+ "stream",
+ "Stream ID",
+ "The ID of the stream to read from",
+ 0,
+ G_MAXUINT,
+ 0,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_COMPONENT,
+ g_param_spec_uint (
+ "component",
+ "Component ID",
+ "The ID of the component to read from",
+ 0,
+ G_MAXUINT,
+ 0,
+ G_PARAM_READWRITE));
+}
+
+static void
+gst_nice_src_init (GstNiceSrc *src)
+{
+ gst_base_src_set_live (GST_BASE_SRC (src), TRUE);
+ gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME);
+ gst_base_src_set_do_timestamp (GST_BASE_SRC (src), TRUE);
+ src->agent = NULL;
+ src->stream_id = 0;
+ src->component_id = 0;
+ src->mainctx = g_main_context_new ();
+ src->mainloop = g_main_loop_new (src->mainctx, FALSE);
+ src->unlocked = FALSE;
+ src->idle_source = NULL;
+ src->outbufs = g_queue_new ();
+}
+
+static void
+gst_nice_src_read_callback (NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ guint len,
+ gchar *buf,
+ gpointer data)
+{
+ GstBaseSrc *basesrc = GST_BASE_SRC (data);
+ GstNiceSrc *nicesrc = GST_NICE_SRC (basesrc);
+ GstBuffer *buffer = NULL;
+
+ GST_LOG_OBJECT (agent, "Got buffer, getting out of the main loop");
+
+#if GST_CHECK_VERSION (1,0,0)
+ buffer = gst_buffer_new_allocate (NULL, len, NULL);
+ gst_buffer_fill (buffer, 0, buf, len);
+#else
+ buffer = gst_buffer_new_and_alloc (len);
+ memcpy (GST_BUFFER_DATA (buffer), buf, len);
+#endif
+ GST_OBJECT_LOCK (nicesrc);
+ g_queue_push_tail (nicesrc->outbufs, buffer);
+ g_main_loop_quit (nicesrc->mainloop);
+ GST_OBJECT_UNLOCK (nicesrc);
+}
+
+static gboolean
+gst_nice_src_unlock_idler (gpointer data)
+{
+ GstNiceSrc *nicesrc = GST_NICE_SRC (data);
+
+ GST_OBJECT_LOCK (nicesrc);
+ if (nicesrc->unlocked)
+ g_main_loop_quit (nicesrc->mainloop);
+
+ if (nicesrc->idle_source) {
+ g_source_destroy (nicesrc->idle_source);
+ g_source_unref (nicesrc->idle_source);
+ nicesrc->idle_source = NULL;
+ }
+ GST_OBJECT_UNLOCK (nicesrc);
+
+ return FALSE;
+}
+
+static gboolean
+gst_nice_src_unlock (GstBaseSrc *src)
+{
+ GstNiceSrc *nicesrc = GST_NICE_SRC (src);
+
+ GST_OBJECT_LOCK (src);
+ nicesrc->unlocked = TRUE;
+
+ g_main_loop_quit (nicesrc->mainloop);
+
+ if (!nicesrc->idle_source) {
+ nicesrc->idle_source = g_idle_source_new ();
+ g_source_set_priority (nicesrc->idle_source, G_PRIORITY_HIGH);
+ g_source_set_callback (nicesrc->idle_source, gst_nice_src_unlock_idler, src, NULL);
+ g_source_attach (nicesrc->idle_source, g_main_loop_get_context (nicesrc->mainloop));
+ }
+ GST_OBJECT_UNLOCK (src);
+
+ return TRUE;
+}
+
+static gboolean
+gst_nice_src_unlock_stop (GstBaseSrc *src)
+{
+ GstNiceSrc *nicesrc = GST_NICE_SRC (src);
+
+ GST_OBJECT_LOCK (src);
+ nicesrc->unlocked = FALSE;
+ if (nicesrc->idle_source) {
+ g_source_destroy (nicesrc->idle_source);
+ g_source_unref(nicesrc->idle_source);
+ }
+ nicesrc->idle_source = NULL;
+ GST_OBJECT_UNLOCK (src);
+
+ return TRUE;
+}
+
+static GstFlowReturn
+gst_nice_src_create (
+ GstPushSrc *basesrc,
+ GstBuffer **buffer)
+{
+ GstNiceSrc *nicesrc = GST_NICE_SRC (basesrc);
+
+ GST_LOG_OBJECT (nicesrc, "create called");
+
+ GST_OBJECT_LOCK (basesrc);
+ if (nicesrc->unlocked) {
+ GST_OBJECT_UNLOCK (basesrc);
+#if GST_CHECK_VERSION (1,0,0)
+ return GST_FLOW_FLUSHING;
+#else
+ return GST_FLOW_WRONG_STATE;
+#endif
+ }
+ if (g_queue_is_empty (nicesrc->outbufs)) {
+ GST_OBJECT_UNLOCK (basesrc);
+ g_main_loop_run (nicesrc->mainloop);
+ GST_OBJECT_LOCK (basesrc);
+ }
+
+ *buffer = g_queue_pop_head (nicesrc->outbufs);
+ GST_OBJECT_UNLOCK (basesrc);
+
+ if (*buffer != NULL) {
+ GST_LOG_OBJECT (nicesrc, "Got buffer, pushing");
+ return GST_FLOW_OK;
+ } else {
+ GST_LOG_OBJECT (nicesrc, "Got interrupting, returning wrong-state");
+#if GST_CHECK_VERSION (1,0,0)
+ return GST_FLOW_FLUSHING;
+#else
+ return GST_FLOW_WRONG_STATE;
+#endif
+ }
+
+}
+
+static void
+gst_nice_src_dispose (GObject *object)
+{
+ GstNiceSrc *src = GST_NICE_SRC (object);
+
+ if (src->agent)
+ g_object_unref (src->agent);
+ src->agent = NULL;
+
+ if (src->mainloop)
+ g_main_loop_unref (src->mainloop);
+ src->mainloop = NULL;
+
+ if (src->mainctx)
+ g_main_context_unref (src->mainctx);
+ src->mainctx = NULL;
+
+ if (src->outbufs) {
+ g_queue_free_full (src->outbufs, (GDestroyNotify) gst_buffer_unref);
+ }
+ src->outbufs = NULL;
+
+ G_OBJECT_CLASS (gst_nice_src_parent_class)->dispose (object);
+}
+
+static void
+gst_nice_src_set_property (
+ GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GstNiceSrc *src = GST_NICE_SRC (object);
+
+ switch (prop_id)
+ {
+ case PROP_AGENT:
+ if (src->agent)
+ GST_ERROR_OBJECT (object,
+ "Changing the agent on a nice src not allowed");
+ else
+ src->agent = g_value_dup_object (value);
+ break;
+
+ case PROP_STREAM:
+ src->stream_id = g_value_get_uint (value);
+ break;
+
+ case PROP_COMPONENT:
+ src->component_id = g_value_get_uint (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_nice_src_get_property (
+ GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GstNiceSrc *src = GST_NICE_SRC (object);
+
+ switch (prop_id)
+ {
+ case PROP_AGENT:
+ g_value_set_object (value, src->agent);
+ break;
+
+ case PROP_STREAM:
+ g_value_set_uint (value, src->stream_id);
+ break;
+
+ case PROP_COMPONENT:
+ g_value_set_uint (value, src->component_id);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GstStateChangeReturn
+gst_nice_src_change_state (GstElement * element, GstStateChange transition)
+{
+ GstNiceSrc *src;
+ GstStateChangeReturn ret;
+
+ src = GST_NICE_SRC (element);
+
+ switch (transition) {
+ case GST_STATE_CHANGE_NULL_TO_READY:
+ if (src->agent == NULL)
+ {
+ GST_ERROR_OBJECT (element,
+ "Trying to start Nice source without an agent set");
+ return GST_STATE_CHANGE_FAILURE;
+ }
+ else if (src->stream_id == 0)
+ {
+ GST_ERROR_OBJECT (element,
+ "Trying to start Nice source without a stream set");
+ return GST_STATE_CHANGE_FAILURE;
+ }
+ else if (src->component_id == 0)
+ {
+ GST_ERROR_OBJECT (element,
+ "Trying to start Nice source without a component set");
+ return GST_STATE_CHANGE_FAILURE;
+ }
+ break;
+ case GST_STATE_CHANGE_PAUSED_TO_READY:
+ nice_agent_attach_recv (src->agent, src->stream_id, src->component_id,
+ src->mainctx, NULL, NULL);
+ GST_OBJECT_LOCK (src);
+ g_list_free_full (src->outbufs->head, (GDestroyNotify) gst_buffer_unref);
+ g_queue_init (src->outbufs);
+ GST_OBJECT_UNLOCK (src);
+ break;
+ case GST_STATE_CHANGE_READY_TO_PAUSED:
+ case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+ case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+ case GST_STATE_CHANGE_READY_TO_NULL:
+ default:
+ break;
+ }
+
+ ret = GST_ELEMENT_CLASS (gst_nice_src_parent_class)->change_state (element,
+ transition);
+
+ switch (transition) {
+ case GST_STATE_CHANGE_READY_TO_PAUSED:
+ nice_agent_attach_recv (src->agent, src->stream_id, src->component_id,
+ src->mainctx, gst_nice_src_read_callback, (gpointer) src);
+ break;
+ case GST_STATE_CHANGE_NULL_TO_READY:
+ case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
+ case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
+ case GST_STATE_CHANGE_PAUSED_TO_READY:
+ case GST_STATE_CHANGE_READY_TO_NULL:
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2006, 2007 Collabora Ltd.
+ * Contact: Dafydd Harries
+ * (C) 2006, 2007 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Dafydd Harries, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef _GSTNICESRC_H
+#define _GSTNICESRC_H
+
+#include <gst/gst.h>
+#include <gst/base/gstpushsrc.h>
+
+#include <nice/nice.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_NICE_SRC \
+ (gst_nice_src_get_type())
+#define GST_NICE_SRC(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_NICE_SRC,GstNiceSrc))
+#define GST_NICE_SRC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_NICE_SRC,GstNiceSrcClass))
+#define GST_IS_NICE_SRC(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_NICE_SRC))
+#define GST_IS_NICE_SRC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_NICE_SRC))
+
+typedef struct _GstNiceSrc GstNiceSrc;
+
+struct _GstNiceSrc
+{
+ GstPushSrc parent;
+ GstPad *srcpad;
+ NiceAgent *agent;
+ guint stream_id;
+ guint component_id;
+ GMainContext *mainctx;
+ GMainLoop *mainloop;
+ GQueue *outbufs;
+ gboolean unlocked;
+ GSource *idle_source;
+};
+
+typedef struct _GstNiceSrcClass GstNiceSrcClass;
+
+struct _GstNiceSrcClass
+{
+ GstPushSrcClass parent_class;
+};
+
+GType gst_nice_src_get_type (void);
+
+G_END_DECLS
+
+#endif // _GSTNICESRC_H
+
--- /dev/null
+gst_nice_sources = [
+ 'gstnicesrc.c',
+ 'gstnicesink.c',
+ 'gstnice.c',
+]
+
+gst_nice_args = ['-DGST_USE_UNSTABLE_API']
+
+gst_plugins_install_dir = join_paths(get_option('libdir'), 'gstreamer-1.0')
+
+libgstnice = library('gstnice',
+ gst_nice_sources,
+ c_args : gst_nice_args,
+ include_directories: nice_incs,
+ dependencies: [nice_deps, gst_dep],
+ link_with: libnice,
+ install_dir: gst_plugins_install_dir,
+ install: true)
+
+# Generate pc files for static plugins if we build static plugins
+if get_option('default_library') != 'shared'
+ pkg.generate(libgstnice, install_dir: join_paths(gst_plugins_install_dir, 'pkgconfig'))
+endif
--- /dev/null
+# -*- mode: makefile -*-
+
+####################################
+# Everything below here is generic #
+####################################
+
+if GTK_DOC_USE_LIBTOOL
+GTKDOC_CC = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+GTKDOC_LD = $(LIBTOOL) --tag=CC --mode=link $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS)
+GTKDOC_RUN = $(LIBTOOL) --mode=execute
+else
+GTKDOC_CC = $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+GTKDOC_LD = $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS)
+GTKDOC_RUN =
+endif
+
+# We set GPATH here; this gives us semantics for GNU make
+# which are more like other make's VPATH, when it comes to
+# whether a source that is a target of one rule is then
+# searched for in VPATH/GPATH.
+#
+GPATH = $(srcdir)
+
+TARGET_DIR=$(HTML_DIR)/$(DOC_MODULE)
+
+SETUP_FILES = \
+ $(content_files) \
+ $(expand_content_files) \
+ $(DOC_MAIN_SGML_FILE) \
+ $(DOC_MODULE)-sections.txt \
+ $(DOC_MODULE)-overrides.txt
+
+EXTRA_DIST = \
+ $(HTML_IMAGES) \
+ $(SETUP_FILES)
+
+DOC_STAMPS=setup-build.stamp scan-build.stamp sgml-build.stamp \
+ html-build.stamp pdf-build.stamp \
+ sgml.stamp html.stamp pdf.stamp
+
+SCANOBJ_FILES = \
+ $(DOC_MODULE).args \
+ $(DOC_MODULE).hierarchy \
+ $(DOC_MODULE).interfaces \
+ $(DOC_MODULE).prerequisites \
+ $(DOC_MODULE).signals
+
+REPORT_FILES = \
+ $(DOC_MODULE)-undocumented.txt \
+ $(DOC_MODULE)-undeclared.txt \
+ $(DOC_MODULE)-unused.txt
+
+gtkdoc-check.test: Makefile
+ $(AM_V_GEN)echo "#!/bin/sh -e" > $@; \
+ echo "$(GTKDOC_CHECK_PATH) || exit 1" >> $@; \
+ chmod +x $@
+
+CLEANFILES = $(SCANOBJ_FILES) $(REPORT_FILES) $(DOC_STAMPS) gtkdoc-check.test
+
+if GTK_DOC_BUILD_HTML
+HTML_BUILD_STAMP=html-build.stamp
+else
+HTML_BUILD_STAMP=
+endif
+if GTK_DOC_BUILD_PDF
+PDF_BUILD_STAMP=pdf-build.stamp
+else
+PDF_BUILD_STAMP=
+endif
+
+all-gtk-doc: $(HTML_BUILD_STAMP) $(PDF_BUILD_STAMP)
+.PHONY: all-gtk-doc
+
+if ENABLE_GTK_DOC
+all-local: all-gtk-doc
+endif
+
+docs: $(HTML_BUILD_STAMP) $(PDF_BUILD_STAMP)
+
+$(REPORT_FILES): sgml-build.stamp
+
+#### setup ####
+
+GTK_DOC_V_SETUP=$(GTK_DOC_V_SETUP_$(V))
+GTK_DOC_V_SETUP_=$(GTK_DOC_V_SETUP_$(AM_DEFAULT_VERBOSITY))
+GTK_DOC_V_SETUP_0=@echo " DOC Preparing build";
+
+setup-build.stamp:
+ -$(GTK_DOC_V_SETUP)if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \
+ files=`echo $(SETUP_FILES) $(DOC_MODULE).types`; \
+ if test "x$$files" != "x" ; then \
+ for file in $$files ; do \
+ destdir=`dirname $(abs_builddir)/$$file`; \
+ test -d "$$destdir" || mkdir -p "$$destdir"; \
+ test -f $(abs_srcdir)/$$file && \
+ cp -pf $(abs_srcdir)/$$file $(abs_builddir)/$$file || true; \
+ done; \
+ fi; \
+ fi
+ $(AM_V_at)touch setup-build.stamp
+
+
+#### scan ####
+
+GTK_DOC_V_SCAN=$(GTK_DOC_V_SCAN_$(V))
+GTK_DOC_V_SCAN_=$(GTK_DOC_V_SCAN_$(AM_DEFAULT_VERBOSITY))
+GTK_DOC_V_SCAN_0=@echo " DOC Scanning header files";
+
+GTK_DOC_V_INTROSPECT=$(GTK_DOC_V_INTROSPECT_$(V))
+GTK_DOC_V_INTROSPECT_=$(GTK_DOC_V_INTROSPECT_$(AM_DEFAULT_VERBOSITY))
+GTK_DOC_V_INTROSPECT_0=@echo " DOC Introspecting gobjects";
+
+scan-build.stamp: setup-build.stamp $(HFILE_GLOB) $(CFILE_GLOB)
+ $(GTK_DOC_V_SCAN)_source_dir='' ; \
+ for i in $(DOC_SOURCE_DIR) ; do \
+ _source_dir="$${_source_dir} --source-dir=$$i" ; \
+ done ; \
+ gtkdoc-scan --module=$(DOC_MODULE) --ignore-headers="$(IGNORE_HFILES)" $${_source_dir} $(SCAN_OPTIONS) $(EXTRA_HFILES)
+ $(GTK_DOC_V_INTROSPECT)if grep -l '^..*$$' $(DOC_MODULE).types > /dev/null 2>&1 ; then \
+ scanobj_options=""; \
+ gtkdoc-scangobj 2>&1 --help | grep >/dev/null "\-\-verbose"; \
+ if test "$$?" = "0"; then \
+ if test "x$(V)" = "x1"; then \
+ scanobj_options="--verbose"; \
+ fi; \
+ fi; \
+ CC="$(GTKDOC_CC)" LD="$(GTKDOC_LD)" RUN="$(GTKDOC_RUN)" CFLAGS="$(GTKDOC_CFLAGS) $(CFLAGS)" LDFLAGS="$(GTKDOC_LIBS) $(LDFLAGS)" \
+ gtkdoc-scangobj $(SCANGOBJ_OPTIONS) $$scanobj_options --module=$(DOC_MODULE); \
+ else \
+ for i in $(SCANOBJ_FILES) ; do \
+ test -f $$i || touch $$i ; \
+ done \
+ fi
+ $(AM_V_at)touch scan-build.stamp
+
+$(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt: scan-build.stamp
+ @true
+
+#### xml ####
+
+GTK_DOC_V_XML=$(GTK_DOC_V_XML_$(V))
+GTK_DOC_V_XML_=$(GTK_DOC_V_XML_$(AM_DEFAULT_VERBOSITY))
+GTK_DOC_V_XML_0=@echo " DOC Building XML";
+
+sgml-build.stamp: setup-build.stamp $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(HFILE_GLOB) $(CFILE_GLOB) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt $(expand_content_files) xml/gtkdocentities.ent
+ $(GTK_DOC_V_XML)_source_dir='' ; \
+ for i in $(DOC_SOURCE_DIR) ; do \
+ _source_dir="$${_source_dir} --source-dir=$$i" ; \
+ done ; \
+ gtkdoc-mkdb --module=$(DOC_MODULE) --output-format=xml --expand-content-files="$(expand_content_files)" --main-sgml-file=$(DOC_MAIN_SGML_FILE) $${_source_dir} $(MKDB_OPTIONS)
+ $(AM_V_at)touch sgml-build.stamp
+
+sgml.stamp: sgml-build.stamp
+ @true
+
+xml/gtkdocentities.ent: Makefile
+ $(GTK_DOC_V_XML)$(MKDIR_P) $(@D) && ( \
+ echo "<!ENTITY package \"$(PACKAGE)\">"; \
+ echo "<!ENTITY package_bugreport \"$(PACKAGE_BUGREPORT)\">"; \
+ echo "<!ENTITY package_name \"$(PACKAGE_NAME)\">"; \
+ echo "<!ENTITY package_string \"$(PACKAGE_STRING)\">"; \
+ echo "<!ENTITY package_tarname \"$(PACKAGE_TARNAME)\">"; \
+ echo "<!ENTITY package_url \"$(PACKAGE_URL)\">"; \
+ echo "<!ENTITY package_version \"$(PACKAGE_VERSION)\">"; \
+ ) > $@
+
+#### html ####
+
+GTK_DOC_V_HTML=$(GTK_DOC_V_HTML_$(V))
+GTK_DOC_V_HTML_=$(GTK_DOC_V_HTML_$(AM_DEFAULT_VERBOSITY))
+GTK_DOC_V_HTML_0=@echo " DOC Building HTML";
+
+GTK_DOC_V_XREF=$(GTK_DOC_V_XREF_$(V))
+GTK_DOC_V_XREF_=$(GTK_DOC_V_XREF_$(AM_DEFAULT_VERBOSITY))
+GTK_DOC_V_XREF_0=@echo " DOC Fixing cross-references";
+
+html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_content_files)
+ $(GTK_DOC_V_HTML)rm -rf html && mkdir html && \
+ mkhtml_options=""; \
+ gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-verbose"; \
+ if test "$$?" = "0"; then \
+ if test "x$(V)" = "x1"; then \
+ mkhtml_options="$$mkhtml_options --verbose"; \
+ fi; \
+ fi; \
+ gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-path"; \
+ if test "$$?" = "0"; then \
+ mkhtml_options="$$mkhtml_options --path=\"$(abs_srcdir)\""; \
+ fi; \
+ cd html && gtkdoc-mkhtml $$mkhtml_options $(MKHTML_OPTIONS) $(DOC_MODULE) ../$(DOC_MAIN_SGML_FILE)
+ -@test "x$(HTML_IMAGES)" = "x" || \
+ for file in $(HTML_IMAGES) ; do \
+ if test -f $(abs_srcdir)/$$file ; then \
+ cp $(abs_srcdir)/$$file $(abs_builddir)/html; \
+ fi; \
+ if test -f $(abs_builddir)/$$file ; then \
+ cp $(abs_builddir)/$$file $(abs_builddir)/html; \
+ fi; \
+ done;
+ $(GTK_DOC_V_XREF)gtkdoc-fixxref --module=$(DOC_MODULE) --module-dir=html --html-dir=$(HTML_DIR) $(FIXXREF_OPTIONS)
+ $(AM_V_at)touch html-build.stamp
+
+#### pdf ####
+
+GTK_DOC_V_PDF=$(GTK_DOC_V_PDF_$(V))
+GTK_DOC_V_PDF_=$(GTK_DOC_V_PDF_$(AM_DEFAULT_VERBOSITY))
+GTK_DOC_V_PDF_0=@echo " DOC Building PDF";
+
+pdf-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_content_files)
+ $(GTK_DOC_V_PDF)rm -f $(DOC_MODULE).pdf && \
+ mkpdf_options=""; \
+ gtkdoc-mkpdf 2>&1 --help | grep >/dev/null "\-\-verbose"; \
+ if test "$$?" = "0"; then \
+ if test "x$(V)" = "x1"; then \
+ mkpdf_options="$$mkpdf_options --verbose"; \
+ fi; \
+ fi; \
+ if test "x$(HTML_IMAGES)" != "x"; then \
+ for img in $(HTML_IMAGES); do \
+ part=`dirname $$img`; \
+ echo $$mkpdf_options | grep >/dev/null "\-\-imgdir=$$part "; \
+ if test $$? != 0; then \
+ mkpdf_options="$$mkpdf_options --imgdir=$$part"; \
+ fi; \
+ done; \
+ fi; \
+ gtkdoc-mkpdf --path="$(abs_srcdir)" $$mkpdf_options $(DOC_MODULE) $(DOC_MAIN_SGML_FILE) $(MKPDF_OPTIONS)
+ $(AM_V_at)touch pdf-build.stamp
+
+##############
+
+clean-local:
+ @rm -f *~ *.bak
+ @rm -rf .libs
+ @if echo $(SCAN_OPTIONS) | grep -q "\-\-rebuild-types" ; then \
+ rm -f $(DOC_MODULE).types; \
+ fi
+ @if echo $(SCAN_OPTIONS) | grep -q "\-\-rebuild-sections" ; then \
+ rm -f $(DOC_MODULE)-sections.txt; \
+ fi
+
+distclean-local:
+ @rm -rf xml html $(REPORT_FILES) $(DOC_MODULE).pdf \
+ $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt
+ @if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \
+ rm -f $(SETUP_FILES) $(DOC_MODULE).types; \
+ fi
+
+maintainer-clean-local:
+ @rm -rf xml html
+
+install-data-local:
+ @installfiles=`echo $(builddir)/html/*`; \
+ if test "$$installfiles" = '$(builddir)/html/*'; \
+ then echo 1>&2 'Nothing to install' ; \
+ else \
+ if test -n "$(DOC_MODULE_VERSION)"; then \
+ installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \
+ else \
+ installdir="$(DESTDIR)$(TARGET_DIR)"; \
+ fi; \
+ $(mkinstalldirs) $${installdir} ; \
+ for i in $$installfiles; do \
+ echo ' $(INSTALL_DATA) '$$i ; \
+ $(INSTALL_DATA) $$i $${installdir}; \
+ done; \
+ if test -n "$(DOC_MODULE_VERSION)"; then \
+ mv -f $${installdir}/$(DOC_MODULE).devhelp2 \
+ $${installdir}/$(DOC_MODULE)-$(DOC_MODULE_VERSION).devhelp2; \
+ fi; \
+ $(GTKDOC_REBASE) --relative --dest-dir=$(DESTDIR) --html-dir=$${installdir}; \
+ fi
+
+uninstall-local:
+ @if test -n "$(DOC_MODULE_VERSION)"; then \
+ installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \
+ else \
+ installdir="$(DESTDIR)$(TARGET_DIR)"; \
+ fi; \
+ rm -rf $${installdir}
+
+#
+# Require gtk-doc when making dist
+#
+if HAVE_GTK_DOC
+dist-check-gtkdoc: docs
+else
+dist-check-gtkdoc:
+ @echo "*** gtk-doc is needed to run 'make dist'. ***"
+ @echo "*** gtk-doc was not found when 'configure' ran. ***"
+ @echo "*** please install gtk-doc and rerun 'configure'. ***"
+ @false
+endif
+
+dist-hook: dist-check-gtkdoc all-gtk-doc dist-hook-local
+ @mkdir $(distdir)/html
+ @cp ./html/* $(distdir)/html
+ @-cp ./$(DOC_MODULE).pdf $(distdir)/
+ @-cp ./$(DOC_MODULE).types $(distdir)/
+ @-cp ./$(DOC_MODULE)-sections.txt $(distdir)/
+ @cd $(distdir) && rm -f $(DISTCLEANFILES)
+ @$(GTKDOC_REBASE) --online --relative --html-dir=$(distdir)/html
+
+.PHONY : dist-hook-local docs
--- /dev/null
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2018-03-11.20; # UTC
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# 'make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+
+tab=' '
+nl='
+'
+IFS=" $tab$nl"
+
+# Set DOITPROG to "echo" to test this script.
+
+doit=${DOITPROG-}
+doit_exec=${doit:-exec}
+
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+
+chgrpprog=${CHGRPPROG-chgrp}
+chmodprog=${CHMODPROG-chmod}
+chownprog=${CHOWNPROG-chown}
+cmpprog=${CMPPROG-cmp}
+cpprog=${CPPROG-cp}
+mkdirprog=${MKDIRPROG-mkdir}
+mvprog=${MVPROG-mv}
+rmprog=${RMPROG-rm}
+stripprog=${STRIPPROG-strip}
+
+posix_mkdir=
+
+# Desired mode of installed file.
+mode=0755
+
+chgrpcmd=
+chmodcmd=$chmodprog
+chowncmd=
+mvcmd=$mvprog
+rmcmd="$rmprog -f"
+stripcmd=
+
+src=
+dst=
+dir_arg=
+dst_arg=
+
+copy_on_change=false
+is_target_a_directory=possibly
+
+usage="\
+Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+ or: $0 [OPTION]... SRCFILES... DIRECTORY
+ or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+ or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+ --help display this help and exit.
+ --version display version info and exit.
+
+ -c (ignored)
+ -C install only if different (preserve the last data modification time)
+ -d create directories instead of installing files.
+ -g GROUP $chgrpprog installed files to GROUP.
+ -m MODE $chmodprog installed files to MODE.
+ -o USER $chownprog installed files to USER.
+ -s $stripprog installed files.
+ -t DIRECTORY install into DIRECTORY.
+ -T report an error if DSTFILE is a directory.
+
+Environment variables override the default commands:
+ CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
+ RMPROG STRIPPROG
+"
+
+while test $# -ne 0; do
+ case $1 in
+ -c) ;;
+
+ -C) copy_on_change=true;;
+
+ -d) dir_arg=true;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift;;
+
+ --help) echo "$usage"; exit $?;;
+
+ -m) mode=$2
+ case $mode in
+ *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
+ echo "$0: invalid mode: $mode" >&2
+ exit 1;;
+ esac
+ shift;;
+
+ -o) chowncmd="$chownprog $2"
+ shift;;
+
+ -s) stripcmd=$stripprog;;
+
+ -t)
+ is_target_a_directory=always
+ dst_arg=$2
+ # Protect names problematic for 'test' and other utilities.
+ case $dst_arg in
+ -* | [=\(\)!]) dst_arg=./$dst_arg;;
+ esac
+ shift;;
+
+ -T) is_target_a_directory=never;;
+
+ --version) echo "$0 $scriptversion"; exit $?;;
+
+ --) shift
+ break;;
+
+ -*) echo "$0: invalid option: $1" >&2
+ exit 1;;
+
+ *) break;;
+ esac
+ shift
+done
+
+# We allow the use of options -d and -T together, by making -d
+# take the precedence; this is for compatibility with GNU install.
+
+if test -n "$dir_arg"; then
+ if test -n "$dst_arg"; then
+ echo "$0: target directory not allowed when installing a directory." >&2
+ exit 1
+ fi
+fi
+
+if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
+ # When -d is used, all remaining arguments are directories to create.
+ # When -t is used, the destination is already specified.
+ # Otherwise, the last argument is the destination. Remove it from $@.
+ for arg
+ do
+ if test -n "$dst_arg"; then
+ # $@ is not empty: it contains at least $arg.
+ set fnord "$@" "$dst_arg"
+ shift # fnord
+ fi
+ shift # arg
+ dst_arg=$arg
+ # Protect names problematic for 'test' and other utilities.
+ case $dst_arg in
+ -* | [=\(\)!]) dst_arg=./$dst_arg;;
+ esac
+ done
+fi
+
+if test $# -eq 0; then
+ if test -z "$dir_arg"; then
+ echo "$0: no input file specified." >&2
+ exit 1
+ fi
+ # It's OK to call 'install-sh -d' without argument.
+ # This can happen when creating conditional directories.
+ exit 0
+fi
+
+if test -z "$dir_arg"; then
+ if test $# -gt 1 || test "$is_target_a_directory" = always; then
+ if test ! -d "$dst_arg"; then
+ echo "$0: $dst_arg: Is not a directory." >&2
+ exit 1
+ fi
+ fi
+fi
+
+if test -z "$dir_arg"; then
+ do_exit='(exit $ret); exit $ret'
+ trap "ret=129; $do_exit" 1
+ trap "ret=130; $do_exit" 2
+ trap "ret=141; $do_exit" 13
+ trap "ret=143; $do_exit" 15
+
+ # Set umask so as not to create temps with too-generous modes.
+ # However, 'strip' requires both read and write access to temps.
+ case $mode in
+ # Optimize common cases.
+ *644) cp_umask=133;;
+ *755) cp_umask=22;;
+
+ *[0-7])
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw='% 200'
+ fi
+ cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+ *)
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw=,u+rw
+ fi
+ cp_umask=$mode$u_plus_rw;;
+ esac
+fi
+
+for src
+do
+ # Protect names problematic for 'test' and other utilities.
+ case $src in
+ -* | [=\(\)!]) src=./$src;;
+ esac
+
+ if test -n "$dir_arg"; then
+ dst=$src
+ dstdir=$dst
+ test -d "$dstdir"
+ dstdir_status=$?
+ else
+
+ # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+ # might cause directories to be created, which would be especially bad
+ # if $src (and thus $dsttmp) contains '*'.
+ if test ! -f "$src" && test ! -d "$src"; then
+ echo "$0: $src does not exist." >&2
+ exit 1
+ fi
+
+ if test -z "$dst_arg"; then
+ echo "$0: no destination specified." >&2
+ exit 1
+ fi
+ dst=$dst_arg
+
+ # If destination is a directory, append the input filename.
+ if test -d "$dst"; then
+ if test "$is_target_a_directory" = never; then
+ echo "$0: $dst_arg: Is a directory" >&2
+ exit 1
+ fi
+ dstdir=$dst
+ dstbase=`basename "$src"`
+ case $dst in
+ */) dst=$dst$dstbase;;
+ *) dst=$dst/$dstbase;;
+ esac
+ dstdir_status=0
+ else
+ dstdir=`dirname "$dst"`
+ test -d "$dstdir"
+ dstdir_status=$?
+ fi
+ fi
+
+ case $dstdir in
+ */) dstdirslash=$dstdir;;
+ *) dstdirslash=$dstdir/;;
+ esac
+
+ obsolete_mkdir_used=false
+
+ if test $dstdir_status != 0; then
+ case $posix_mkdir in
+ '')
+ # Create intermediate dirs using mode 755 as modified by the umask.
+ # This is like FreeBSD 'install' as of 1997-10-28.
+ umask=`umask`
+ case $stripcmd.$umask in
+ # Optimize common cases.
+ *[2367][2367]) mkdir_umask=$umask;;
+ .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
+
+ *[0-7])
+ mkdir_umask=`expr $umask + 22 \
+ - $umask % 100 % 40 + $umask % 20 \
+ - $umask % 10 % 4 + $umask % 2
+ `;;
+ *) mkdir_umask=$umask,go-w;;
+ esac
+
+ # With -d, create the new directory with the user-specified mode.
+ # Otherwise, rely on $mkdir_umask.
+ if test -n "$dir_arg"; then
+ mkdir_mode=-m$mode
+ else
+ mkdir_mode=
+ fi
+
+ posix_mkdir=false
+ case $umask in
+ *[123567][0-7][0-7])
+ # POSIX mkdir -p sets u+wx bits regardless of umask, which
+ # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
+ ;;
+ *)
+ # Note that $RANDOM variable is not portable (e.g. dash); Use it
+ # here however when possible just to lower collision chance.
+ tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+
+ trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0
+
+ # Because "mkdir -p" follows existing symlinks and we likely work
+ # directly in world-writeable /tmp, make sure that the '$tmpdir'
+ # directory is successfully created first before we actually test
+ # 'mkdir -p' feature.
+ if (umask $mkdir_umask &&
+ $mkdirprog $mkdir_mode "$tmpdir" &&
+ exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
+ then
+ if test -z "$dir_arg" || {
+ # Check for POSIX incompatibilities with -m.
+ # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+ # other-writable bit of parent directory when it shouldn't.
+ # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+ test_tmpdir="$tmpdir/a"
+ ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
+ case $ls_ld_tmpdir in
+ d????-?r-*) different_mode=700;;
+ d????-?--*) different_mode=755;;
+ *) false;;
+ esac &&
+ $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
+ ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
+ test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+ }
+ }
+ then posix_mkdir=:
+ fi
+ rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
+ else
+ # Remove any dirs left behind by ancient mkdir implementations.
+ rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
+ fi
+ trap '' 0;;
+ esac;;
+ esac
+
+ if
+ $posix_mkdir && (
+ umask $mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+ )
+ then :
+ else
+
+ # The umask is ridiculous, or mkdir does not conform to POSIX,
+ # or it failed possibly due to a race condition. Create the
+ # directory the slow way, step by step, checking for races as we go.
+
+ case $dstdir in
+ /*) prefix='/';;
+ [-=\(\)!]*) prefix='./';;
+ *) prefix='';;
+ esac
+
+ oIFS=$IFS
+ IFS=/
+ set -f
+ set fnord $dstdir
+ shift
+ set +f
+ IFS=$oIFS
+
+ prefixes=
+
+ for d
+ do
+ test X"$d" = X && continue
+
+ prefix=$prefix$d
+ if test -d "$prefix"; then
+ prefixes=
+ else
+ if $posix_mkdir; then
+ (umask=$mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+ # Don't fail if two instances are running concurrently.
+ test -d "$prefix" || exit 1
+ else
+ case $prefix in
+ *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) qprefix=$prefix;;
+ esac
+ prefixes="$prefixes '$qprefix'"
+ fi
+ fi
+ prefix=$prefix/
+ done
+
+ if test -n "$prefixes"; then
+ # Don't fail if two instances are running concurrently.
+ (umask $mkdir_umask &&
+ eval "\$doit_exec \$mkdirprog $prefixes") ||
+ test -d "$dstdir" || exit 1
+ obsolete_mkdir_used=true
+ fi
+ fi
+ fi
+
+ if test -n "$dir_arg"; then
+ { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+ { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
+ else
+
+ # Make a couple of temp file names in the proper directory.
+ dsttmp=${dstdirslash}_inst.$$_
+ rmtmp=${dstdirslash}_rm.$$_
+
+ # Trap to clean up those temp files at exit.
+ trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+
+ # Copy the file name to the temp name.
+ (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
+
+ # and set any options; do chmod last to preserve setuid bits.
+ #
+ # If any of these fail, we abort the whole thing. If we want to
+ # ignore errors from any of these, just make sure not to ignore
+ # errors from the above "$doit $cpprog $src $dsttmp" command.
+ #
+ { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
+ { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
+ { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+ # If -C, don't bother to copy if it wouldn't change the file.
+ if $copy_on_change &&
+ old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
+ new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
+ set -f &&
+ set X $old && old=:$2:$4:$5:$6 &&
+ set X $new && new=:$2:$4:$5:$6 &&
+ set +f &&
+ test "$old" = "$new" &&
+ $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
+ then
+ rm -f "$dsttmp"
+ else
+ # Rename the file to the real destination.
+ $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
+
+ # The rename failed, perhaps because mv can't rename something else
+ # to itself, or perhaps because mv is so ancient that it does not
+ # support -f.
+ {
+ # Now remove or move aside any old file at destination location.
+ # We try this two ways since rm can't unlink itself on some
+ # systems and the destination file might be busy for other
+ # reasons. In this case, the final cleanup might fail but the new
+ # file should still install successfully.
+ {
+ test ! -f "$dst" ||
+ $doit $rmcmd -f "$dst" 2>/dev/null ||
+ { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+ { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
+ } ||
+ { echo "$0: cannot unlink or rename $dst" >&2
+ (exit 1); exit 1
+ }
+ } &&
+
+ # Now rename the file to the real destination.
+ $doit $mvcmd "$dsttmp" "$dst"
+ }
+ fi || exit 1
+
+ trap '' 0
+ fi
+done
+
+# Local variables:
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC0"
+# time-stamp-end: "; # UTC"
+# End:
--- /dev/null
+#! /bin/sh
+## DO NOT EDIT - This file generated from ./build-aux/ltmain.in
+## by inline-source v2014-01-03.01
+
+# libtool (GNU libtool) 2.4.6
+# Provide generalized library-building support services.
+# Written by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+
+# Copyright (C) 1996-2015 Free Software Foundation, Inc.
+# This is free software; see the source for copying conditions. There is NO
+# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+# GNU Libtool is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# As a special exception to the GNU General Public License,
+# if you distribute this file as part of a program or library that
+# is built using GNU Libtool, you may include this file under the
+# same distribution terms that you use for the rest of that program.
+#
+# GNU Libtool is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+PROGRAM=libtool
+PACKAGE=libtool
+VERSION=2.4.6
+package_revision=2.4.6
+
+
+## ------ ##
+## Usage. ##
+## ------ ##
+
+# Run './libtool --help' for help with using this script from the
+# command line.
+
+
+## ------------------------------- ##
+## User overridable command paths. ##
+## ------------------------------- ##
+
+# After configure completes, it has a better idea of some of the
+# shell tools we need than the defaults used by the functions shared
+# with bootstrap, so set those here where they can still be over-
+# ridden by the user, but otherwise take precedence.
+
+: ${AUTOCONF="autoconf"}
+: ${AUTOMAKE="automake"}
+
+
+## -------------------------- ##
+## Source external libraries. ##
+## -------------------------- ##
+
+# Much of our low-level functionality needs to be sourced from external
+# libraries, which are installed to $pkgauxdir.
+
+# Set a version string for this script.
+scriptversion=2015-01-20.17; # UTC
+
+# General shell script boiler plate, and helper functions.
+# Written by Gary V. Vaughan, 2004
+
+# Copyright (C) 2004-2015 Free Software Foundation, Inc.
+# This is free software; see the source for copying conditions. There is NO
+# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+
+# As a special exception to the GNU General Public License, if you distribute
+# this file as part of a program or library that is built using GNU Libtool,
+# you may include this file under the same distribution terms that you use
+# for the rest of that program.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNES FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Please report bugs or propose patches to gary@gnu.org.
+
+
+## ------ ##
+## Usage. ##
+## ------ ##
+
+# Evaluate this file near the top of your script to gain access to
+# the functions and variables defined here:
+#
+# . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh
+#
+# If you need to override any of the default environment variable
+# settings, do that before evaluating this file.
+
+
+## -------------------- ##
+## Shell normalisation. ##
+## -------------------- ##
+
+# Some shells need a little help to be as Bourne compatible as possible.
+# Before doing anything else, make sure all that help has been provided!
+
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac
+fi
+
+# NLS nuisances: We save the old values in case they are required later.
+_G_user_locale=
+_G_safe_locale=
+for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+do
+ eval "if test set = \"\${$_G_var+set}\"; then
+ save_$_G_var=\$$_G_var
+ $_G_var=C
+ export $_G_var
+ _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\"
+ _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\"
+ fi"
+done
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Make sure IFS has a sensible default
+sp=' '
+nl='
+'
+IFS="$sp $nl"
+
+# There are apparently some retarded systems that use ';' as a PATH separator!
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+
+## ------------------------- ##
+## Locate command utilities. ##
+## ------------------------- ##
+
+
+# func_executable_p FILE
+# ----------------------
+# Check that FILE is an executable regular file.
+func_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+}
+
+
+# func_path_progs PROGS_LIST CHECK_FUNC [PATH]
+# --------------------------------------------
+# Search for either a program that responds to --version with output
+# containing "GNU", or else returned by CHECK_FUNC otherwise, by
+# trying all the directories in PATH with each of the elements of
+# PROGS_LIST.
+#
+# CHECK_FUNC should accept the path to a candidate program, and
+# set $func_check_prog_result if it truncates its output less than
+# $_G_path_prog_max characters.
+func_path_progs ()
+{
+ _G_progs_list=$1
+ _G_check_func=$2
+ _G_PATH=${3-"$PATH"}
+
+ _G_path_prog_max=0
+ _G_path_prog_found=false
+ _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:}
+ for _G_dir in $_G_PATH; do
+ IFS=$_G_save_IFS
+ test -z "$_G_dir" && _G_dir=.
+ for _G_prog_name in $_G_progs_list; do
+ for _exeext in '' .EXE; do
+ _G_path_prog=$_G_dir/$_G_prog_name$_exeext
+ func_executable_p "$_G_path_prog" || continue
+ case `"$_G_path_prog" --version 2>&1` in
+ *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;;
+ *) $_G_check_func $_G_path_prog
+ func_path_progs_result=$func_check_prog_result
+ ;;
+ esac
+ $_G_path_prog_found && break 3
+ done
+ done
+ done
+ IFS=$_G_save_IFS
+ test -z "$func_path_progs_result" && {
+ echo "no acceptable sed could be found in \$PATH" >&2
+ exit 1
+ }
+}
+
+
+# We want to be able to use the functions in this file before configure
+# has figured out where the best binaries are kept, which means we have
+# to search for them ourselves - except when the results are already set
+# where we skip the searches.
+
+# Unless the user overrides by setting SED, search the path for either GNU
+# sed, or the sed that truncates its output the least.
+test -z "$SED" && {
+ _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
+ for _G_i in 1 2 3 4 5 6 7; do
+ _G_sed_script=$_G_sed_script$nl$_G_sed_script
+ done
+ echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed
+ _G_sed_script=
+
+ func_check_prog_sed ()
+ {
+ _G_path_prog=$1
+
+ _G_count=0
+ printf 0123456789 >conftest.in
+ while :
+ do
+ cat conftest.in conftest.in >conftest.tmp
+ mv conftest.tmp conftest.in
+ cp conftest.in conftest.nl
+ echo '' >> conftest.nl
+ "$_G_path_prog" -f conftest.sed <conftest.nl >conftest.out 2>/dev/null || break
+ diff conftest.out conftest.nl >/dev/null 2>&1 || break
+ _G_count=`expr $_G_count + 1`
+ if test "$_G_count" -gt "$_G_path_prog_max"; then
+ # Best one so far, save it but keep looking for a better one
+ func_check_prog_result=$_G_path_prog
+ _G_path_prog_max=$_G_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test 10 -lt "$_G_count" && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out
+ }
+
+ func_path_progs "sed gsed" func_check_prog_sed $PATH:/usr/xpg4/bin
+ rm -f conftest.sed
+ SED=$func_path_progs_result
+}
+
+
+# Unless the user overrides by setting GREP, search the path for either GNU
+# grep, or the grep that truncates its output the least.
+test -z "$GREP" && {
+ func_check_prog_grep ()
+ {
+ _G_path_prog=$1
+
+ _G_count=0
+ _G_path_prog_max=0
+ printf 0123456789 >conftest.in
+ while :
+ do
+ cat conftest.in conftest.in >conftest.tmp
+ mv conftest.tmp conftest.in
+ cp conftest.in conftest.nl
+ echo 'GREP' >> conftest.nl
+ "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' <conftest.nl >conftest.out 2>/dev/null || break
+ diff conftest.out conftest.nl >/dev/null 2>&1 || break
+ _G_count=`expr $_G_count + 1`
+ if test "$_G_count" -gt "$_G_path_prog_max"; then
+ # Best one so far, save it but keep looking for a better one
+ func_check_prog_result=$_G_path_prog
+ _G_path_prog_max=$_G_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test 10 -lt "$_G_count" && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out
+ }
+
+ func_path_progs "grep ggrep" func_check_prog_grep $PATH:/usr/xpg4/bin
+ GREP=$func_path_progs_result
+}
+
+
+## ------------------------------- ##
+## User overridable command paths. ##
+## ------------------------------- ##
+
+# All uppercase variable names are used for environment variables. These
+# variables can be overridden by the user before calling a script that
+# uses them if a suitable command of that name is not already available
+# in the command search PATH.
+
+: ${CP="cp -f"}
+: ${ECHO="printf %s\n"}
+: ${EGREP="$GREP -E"}
+: ${FGREP="$GREP -F"}
+: ${LN_S="ln -s"}
+: ${MAKE="make"}
+: ${MKDIR="mkdir"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+: ${SHELL="${CONFIG_SHELL-/bin/sh}"}
+
+
+## -------------------- ##
+## Useful sed snippets. ##
+## -------------------- ##
+
+sed_dirname='s|/[^/]*$||'
+sed_basename='s|^.*/||'
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst='s|\([`"$\\]\)|\\\1|g'
+
+# Same as above, but do not quote variable references.
+sed_double_quote_subst='s/\(["`\\]\)/\\\1/g'
+
+# Sed substitution that turns a string into a regex matching for the
+# string literally.
+sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g'
+
+# Sed substitution that converts a w32 file name or path
+# that contains forward slashes, into one that contains
+# (escaped) backslashes. A very naive implementation.
+sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g'
+
+# Re-'\' parameter expansions in output of sed_double_quote_subst that
+# were '\'-ed in input to the same. If an odd number of '\' preceded a
+# '$' in input to sed_double_quote_subst, that '$' was protected from
+# expansion. Since each input '\' is now two '\'s, look for any number
+# of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'.
+_G_bs='\\'
+_G_bs2='\\\\'
+_G_bs4='\\\\\\\\'
+_G_dollar='\$'
+sed_double_backslash="\
+ s/$_G_bs4/&\\
+/g
+ s/^$_G_bs2$_G_dollar/$_G_bs&/
+ s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g
+ s/\n//g"
+
+
+## ----------------- ##
+## Global variables. ##
+## ----------------- ##
+
+# Except for the global variables explicitly listed below, the following
+# functions in the '^func_' namespace, and the '^require_' namespace
+# variables initialised in the 'Resource management' section, sourcing
+# this file will not pollute your global namespace with anything
+# else. There's no portable way to scope variables in Bourne shell
+# though, so actually running these functions will sometimes place
+# results into a variable named after the function, and often use
+# temporary variables in the '^_G_' namespace. If you are careful to
+# avoid using those namespaces casually in your sourcing script, things
+# should continue to work as you expect. And, of course, you can freely
+# overwrite any of the functions or variables defined here before
+# calling anything to customize them.
+
+EXIT_SUCCESS=0
+EXIT_FAILURE=1
+EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing.
+EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake.
+
+# Allow overriding, eg assuming that you follow the convention of
+# putting '$debug_cmd' at the start of all your functions, you can get
+# bash to show function call trace with:
+#
+# debug_cmd='eval echo "${FUNCNAME[0]} $*" >&2' bash your-script-name
+debug_cmd=${debug_cmd-":"}
+exit_cmd=:
+
+# By convention, finish your script with:
+#
+# exit $exit_status
+#
+# so that you can set exit_status to non-zero if you want to indicate
+# something went wrong during execution without actually bailing out at
+# the point of failure.
+exit_status=$EXIT_SUCCESS
+
+# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh
+# is ksh but when the shell is invoked as "sh" and the current value of
+# the _XPG environment variable is not equal to 1 (one), the special
+# positional parameter $0, within a function call, is the name of the
+# function.
+progpath=$0
+
+# The name of this program.
+progname=`$ECHO "$progpath" |$SED "$sed_basename"`
+
+# Make sure we have an absolute progpath for reexecution:
+case $progpath in
+ [\\/]*|[A-Za-z]:\\*) ;;
+ *[\\/]*)
+ progdir=`$ECHO "$progpath" |$SED "$sed_dirname"`
+ progdir=`cd "$progdir" && pwd`
+ progpath=$progdir/$progname
+ ;;
+ *)
+ _G_IFS=$IFS
+ IFS=${PATH_SEPARATOR-:}
+ for progdir in $PATH; do
+ IFS=$_G_IFS
+ test -x "$progdir/$progname" && break
+ done
+ IFS=$_G_IFS
+ test -n "$progdir" || progdir=`pwd`
+ progpath=$progdir/$progname
+ ;;
+esac
+
+
+## ----------------- ##
+## Standard options. ##
+## ----------------- ##
+
+# The following options affect the operation of the functions defined
+# below, and should be set appropriately depending on run-time para-
+# meters passed on the command line.
+
+opt_dry_run=false
+opt_quiet=false
+opt_verbose=false
+
+# Categories 'all' and 'none' are always available. Append any others
+# you will pass as the first argument to func_warning from your own
+# code.
+warning_categories=
+
+# By default, display warnings according to 'opt_warning_types'. Set
+# 'warning_func' to ':' to elide all warnings, or func_fatal_error to
+# treat the next displayed warning as a fatal error.
+warning_func=func_warn_and_continue
+
+# Set to 'all' to display all warnings, 'none' to suppress all
+# warnings, or a space delimited list of some subset of
+# 'warning_categories' to display only the listed warnings.
+opt_warning_types=all
+
+
+## -------------------- ##
+## Resource management. ##
+## -------------------- ##
+
+# This section contains definitions for functions that each ensure a
+# particular resource (a file, or a non-empty configuration variable for
+# example) is available, and if appropriate to extract default values
+# from pertinent package files. Call them using their associated
+# 'require_*' variable to ensure that they are executed, at most, once.
+#
+# It's entirely deliberate that calling these functions can set
+# variables that don't obey the namespace limitations obeyed by the rest
+# of this file, in order that that they be as useful as possible to
+# callers.
+
+
+# require_term_colors
+# -------------------
+# Allow display of bold text on terminals that support it.
+require_term_colors=func_require_term_colors
+func_require_term_colors ()
+{
+ $debug_cmd
+
+ test -t 1 && {
+ # COLORTERM and USE_ANSI_COLORS environment variables take
+ # precedence, because most terminfo databases neglect to describe
+ # whether color sequences are supported.
+ test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"}
+
+ if test 1 = "$USE_ANSI_COLORS"; then
+ # Standard ANSI escape sequences
+ tc_reset='\e[0m'
+ tc_bold='\e[1m'; tc_standout='\e[7m'
+ tc_red='\e[31m'; tc_green='\e[32m'
+ tc_blue='\e[34m'; tc_cyan='\e[36m'
+ else
+ # Otherwise trust the terminfo database after all.
+ test -n "`tput sgr0 2>/dev/null`" && {
+ tc_reset=`tput sgr0`
+ test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold`
+ tc_standout=$tc_bold
+ test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso`
+ test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1`
+ test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2`
+ test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4`
+ test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5`
+ }
+ fi
+ }
+
+ require_term_colors=:
+}
+
+
+## ----------------- ##
+## Function library. ##
+## ----------------- ##
+
+# This section contains a variety of useful functions to call in your
+# scripts. Take note of the portable wrappers for features provided by
+# some modern shells, which will fall back to slower equivalents on
+# less featureful shells.
+
+
+# func_append VAR VALUE
+# ---------------------
+# Append VALUE onto the existing contents of VAR.
+
+ # We should try to minimise forks, especially on Windows where they are
+ # unreasonably slow, so skip the feature probes when bash or zsh are
+ # being used:
+ if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then
+ : ${_G_HAVE_ARITH_OP="yes"}
+ : ${_G_HAVE_XSI_OPS="yes"}
+ # The += operator was introduced in bash 3.1
+ case $BASH_VERSION in
+ [12].* | 3.0 | 3.0*) ;;
+ *)
+ : ${_G_HAVE_PLUSEQ_OP="yes"}
+ ;;
+ esac
+ fi
+
+ # _G_HAVE_PLUSEQ_OP
+ # Can be empty, in which case the shell is probed, "yes" if += is
+ # useable or anything else if it does not work.
+ test -z "$_G_HAVE_PLUSEQ_OP" \
+ && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \
+ && _G_HAVE_PLUSEQ_OP=yes
+
+if test yes = "$_G_HAVE_PLUSEQ_OP"
+then
+ # This is an XSI compatible shell, allowing a faster implementation...
+ eval 'func_append ()
+ {
+ $debug_cmd
+
+ eval "$1+=\$2"
+ }'
+else
+ # ...otherwise fall back to using expr, which is often a shell builtin.
+ func_append ()
+ {
+ $debug_cmd
+
+ eval "$1=\$$1\$2"
+ }
+fi
+
+
+# func_append_quoted VAR VALUE
+# ----------------------------
+# Quote VALUE and append to the end of shell variable VAR, separated
+# by a space.
+if test yes = "$_G_HAVE_PLUSEQ_OP"; then
+ eval 'func_append_quoted ()
+ {
+ $debug_cmd
+
+ func_quote_for_eval "$2"
+ eval "$1+=\\ \$func_quote_for_eval_result"
+ }'
+else
+ func_append_quoted ()
+ {
+ $debug_cmd
+
+ func_quote_for_eval "$2"
+ eval "$1=\$$1\\ \$func_quote_for_eval_result"
+ }
+fi
+
+
+# func_append_uniq VAR VALUE
+# --------------------------
+# Append unique VALUE onto the existing contents of VAR, assuming
+# entries are delimited by the first character of VALUE. For example:
+#
+# func_append_uniq options " --another-option option-argument"
+#
+# will only append to $options if " --another-option option-argument "
+# is not already present somewhere in $options already (note spaces at
+# each end implied by leading space in second argument).
+func_append_uniq ()
+{
+ $debug_cmd
+
+ eval _G_current_value='`$ECHO $'$1'`'
+ _G_delim=`expr "$2" : '\(.\)'`
+
+ case $_G_delim$_G_current_value$_G_delim in
+ *"$2$_G_delim"*) ;;
+ *) func_append "$@" ;;
+ esac
+}
+
+
+# func_arith TERM...
+# ------------------
+# Set func_arith_result to the result of evaluating TERMs.
+ test -z "$_G_HAVE_ARITH_OP" \
+ && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \
+ && _G_HAVE_ARITH_OP=yes
+
+if test yes = "$_G_HAVE_ARITH_OP"; then
+ eval 'func_arith ()
+ {
+ $debug_cmd
+
+ func_arith_result=$(( $* ))
+ }'
+else
+ func_arith ()
+ {
+ $debug_cmd
+
+ func_arith_result=`expr "$@"`
+ }
+fi
+
+
+# func_basename FILE
+# ------------------
+# Set func_basename_result to FILE with everything up to and including
+# the last / stripped.
+if test yes = "$_G_HAVE_XSI_OPS"; then
+ # If this shell supports suffix pattern removal, then use it to avoid
+ # forking. Hide the definitions single quotes in case the shell chokes
+ # on unsupported syntax...
+ _b='func_basename_result=${1##*/}'
+ _d='case $1 in
+ */*) func_dirname_result=${1%/*}$2 ;;
+ * ) func_dirname_result=$3 ;;
+ esac'
+
+else
+ # ...otherwise fall back to using sed.
+ _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`'
+ _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"`
+ if test "X$func_dirname_result" = "X$1"; then
+ func_dirname_result=$3
+ else
+ func_append func_dirname_result "$2"
+ fi'
+fi
+
+eval 'func_basename ()
+{
+ $debug_cmd
+
+ '"$_b"'
+}'
+
+
+# func_dirname FILE APPEND NONDIR_REPLACEMENT
+# -------------------------------------------
+# Compute the dirname of FILE. If nonempty, add APPEND to the result,
+# otherwise set result to NONDIR_REPLACEMENT.
+eval 'func_dirname ()
+{
+ $debug_cmd
+
+ '"$_d"'
+}'
+
+
+# func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT
+# --------------------------------------------------------
+# Perform func_basename and func_dirname in a single function
+# call:
+# dirname: Compute the dirname of FILE. If nonempty,
+# add APPEND to the result, otherwise set result
+# to NONDIR_REPLACEMENT.
+# value returned in "$func_dirname_result"
+# basename: Compute filename of FILE.
+# value retuned in "$func_basename_result"
+# For efficiency, we do not delegate to the functions above but instead
+# duplicate the functionality here.
+eval 'func_dirname_and_basename ()
+{
+ $debug_cmd
+
+ '"$_b"'
+ '"$_d"'
+}'
+
+
+# func_echo ARG...
+# ----------------
+# Echo program name prefixed message.
+func_echo ()
+{
+ $debug_cmd
+
+ _G_message=$*
+
+ func_echo_IFS=$IFS
+ IFS=$nl
+ for _G_line in $_G_message; do
+ IFS=$func_echo_IFS
+ $ECHO "$progname: $_G_line"
+ done
+ IFS=$func_echo_IFS
+}
+
+
+# func_echo_all ARG...
+# --------------------
+# Invoke $ECHO with all args, space-separated.
+func_echo_all ()
+{
+ $ECHO "$*"
+}
+
+
+# func_echo_infix_1 INFIX ARG...
+# ------------------------------
+# Echo program name, followed by INFIX on the first line, with any
+# additional lines not showing INFIX.
+func_echo_infix_1 ()
+{
+ $debug_cmd
+
+ $require_term_colors
+
+ _G_infix=$1; shift
+ _G_indent=$_G_infix
+ _G_prefix="$progname: $_G_infix: "
+ _G_message=$*
+
+ # Strip color escape sequences before counting printable length
+ for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan"
+ do
+ test -n "$_G_tc" && {
+ _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"`
+ _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"`
+ }
+ done
+ _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes
+
+ func_echo_infix_1_IFS=$IFS
+ IFS=$nl
+ for _G_line in $_G_message; do
+ IFS=$func_echo_infix_1_IFS
+ $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2
+ _G_prefix=$_G_indent
+ done
+ IFS=$func_echo_infix_1_IFS
+}
+
+
+# func_error ARG...
+# -----------------
+# Echo program name prefixed message to standard error.
+func_error ()
+{
+ $debug_cmd
+
+ $require_term_colors
+
+ func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2
+}
+
+
+# func_fatal_error ARG...
+# -----------------------
+# Echo program name prefixed message to standard error, and exit.
+func_fatal_error ()
+{
+ $debug_cmd
+
+ func_error "$*"
+ exit $EXIT_FAILURE
+}
+
+
+# func_grep EXPRESSION FILENAME
+# -----------------------------
+# Check whether EXPRESSION matches any line of FILENAME, without output.
+func_grep ()
+{
+ $debug_cmd
+
+ $GREP "$1" "$2" >/dev/null 2>&1
+}
+
+
+# func_len STRING
+# ---------------
+# Set func_len_result to the length of STRING. STRING may not
+# start with a hyphen.
+ test -z "$_G_HAVE_XSI_OPS" \
+ && (eval 'x=a/b/c;
+ test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \
+ && _G_HAVE_XSI_OPS=yes
+
+if test yes = "$_G_HAVE_XSI_OPS"; then
+ eval 'func_len ()
+ {
+ $debug_cmd
+
+ func_len_result=${#1}
+ }'
+else
+ func_len ()
+ {
+ $debug_cmd
+
+ func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len`
+ }
+fi
+
+
+# func_mkdir_p DIRECTORY-PATH
+# ---------------------------
+# Make sure the entire path to DIRECTORY-PATH is available.
+func_mkdir_p ()
+{
+ $debug_cmd
+
+ _G_directory_path=$1
+ _G_dir_list=
+
+ if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then
+
+ # Protect directory names starting with '-'
+ case $_G_directory_path in
+ -*) _G_directory_path=./$_G_directory_path ;;
+ esac
+
+ # While some portion of DIR does not yet exist...
+ while test ! -d "$_G_directory_path"; do
+ # ...make a list in topmost first order. Use a colon delimited
+ # list incase some portion of path contains whitespace.
+ _G_dir_list=$_G_directory_path:$_G_dir_list
+
+ # If the last portion added has no slash in it, the list is done
+ case $_G_directory_path in */*) ;; *) break ;; esac
+
+ # ...otherwise throw away the child directory and loop
+ _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"`
+ done
+ _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'`
+
+ func_mkdir_p_IFS=$IFS; IFS=:
+ for _G_dir in $_G_dir_list; do
+ IFS=$func_mkdir_p_IFS
+ # mkdir can fail with a 'File exist' error if two processes
+ # try to create one of the directories concurrently. Don't
+ # stop in that case!
+ $MKDIR "$_G_dir" 2>/dev/null || :
+ done
+ IFS=$func_mkdir_p_IFS
+
+ # Bail out if we (or some other process) failed to create a directory.
+ test -d "$_G_directory_path" || \
+ func_fatal_error "Failed to create '$1'"
+ fi
+}
+
+
+# func_mktempdir [BASENAME]
+# -------------------------
+# Make a temporary directory that won't clash with other running
+# libtool processes, and avoids race conditions if possible. If
+# given, BASENAME is the basename for that directory.
+func_mktempdir ()
+{
+ $debug_cmd
+
+ _G_template=${TMPDIR-/tmp}/${1-$progname}
+
+ if test : = "$opt_dry_run"; then
+ # Return a directory name, but don't create it in dry-run mode
+ _G_tmpdir=$_G_template-$$
+ else
+
+ # If mktemp works, use that first and foremost
+ _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null`
+
+ if test ! -d "$_G_tmpdir"; then
+ # Failing that, at least try and use $RANDOM to avoid a race
+ _G_tmpdir=$_G_template-${RANDOM-0}$$
+
+ func_mktempdir_umask=`umask`
+ umask 0077
+ $MKDIR "$_G_tmpdir"
+ umask $func_mktempdir_umask
+ fi
+
+ # If we're not in dry-run mode, bomb out on failure
+ test -d "$_G_tmpdir" || \
+ func_fatal_error "cannot create temporary directory '$_G_tmpdir'"
+ fi
+
+ $ECHO "$_G_tmpdir"
+}
+
+
+# func_normal_abspath PATH
+# ------------------------
+# Remove doubled-up and trailing slashes, "." path components,
+# and cancel out any ".." path components in PATH after making
+# it an absolute path.
+func_normal_abspath ()
+{
+ $debug_cmd
+
+ # These SED scripts presuppose an absolute path with a trailing slash.
+ _G_pathcar='s|^/\([^/]*\).*$|\1|'
+ _G_pathcdr='s|^/[^/]*||'
+ _G_removedotparts=':dotsl
+ s|/\./|/|g
+ t dotsl
+ s|/\.$|/|'
+ _G_collapseslashes='s|/\{1,\}|/|g'
+ _G_finalslash='s|/*$|/|'
+
+ # Start from root dir and reassemble the path.
+ func_normal_abspath_result=
+ func_normal_abspath_tpath=$1
+ func_normal_abspath_altnamespace=
+ case $func_normal_abspath_tpath in
+ "")
+ # Empty path, that just means $cwd.
+ func_stripname '' '/' "`pwd`"
+ func_normal_abspath_result=$func_stripname_result
+ return
+ ;;
+ # The next three entries are used to spot a run of precisely
+ # two leading slashes without using negated character classes;
+ # we take advantage of case's first-match behaviour.
+ ///*)
+ # Unusual form of absolute path, do nothing.
+ ;;
+ //*)
+ # Not necessarily an ordinary path; POSIX reserves leading '//'
+ # and for example Cygwin uses it to access remote file shares
+ # over CIFS/SMB, so we conserve a leading double slash if found.
+ func_normal_abspath_altnamespace=/
+ ;;
+ /*)
+ # Absolute path, do nothing.
+ ;;
+ *)
+ # Relative path, prepend $cwd.
+ func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath
+ ;;
+ esac
+
+ # Cancel out all the simple stuff to save iterations. We also want
+ # the path to end with a slash for ease of parsing, so make sure
+ # there is one (and only one) here.
+ func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \
+ -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"`
+ while :; do
+ # Processed it all yet?
+ if test / = "$func_normal_abspath_tpath"; then
+ # If we ascended to the root using ".." the result may be empty now.
+ if test -z "$func_normal_abspath_result"; then
+ func_normal_abspath_result=/
+ fi
+ break
+ fi
+ func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \
+ -e "$_G_pathcar"`
+ func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \
+ -e "$_G_pathcdr"`
+ # Figure out what to do with it
+ case $func_normal_abspath_tcomponent in
+ "")
+ # Trailing empty path component, ignore it.
+ ;;
+ ..)
+ # Parent dir; strip last assembled component from result.
+ func_dirname "$func_normal_abspath_result"
+ func_normal_abspath_result=$func_dirname_result
+ ;;
+ *)
+ # Actual path component, append it.
+ func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent"
+ ;;
+ esac
+ done
+ # Restore leading double-slash if one was found on entry.
+ func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result
+}
+
+
+# func_notquiet ARG...
+# --------------------
+# Echo program name prefixed message only when not in quiet mode.
+func_notquiet ()
+{
+ $debug_cmd
+
+ $opt_quiet || func_echo ${1+"$@"}
+
+ # A bug in bash halts the script if the last line of a function
+ # fails when set -e is in force, so we need another command to
+ # work around that:
+ :
+}
+
+
+# func_relative_path SRCDIR DSTDIR
+# --------------------------------
+# Set func_relative_path_result to the relative path from SRCDIR to DSTDIR.
+func_relative_path ()
+{
+ $debug_cmd
+
+ func_relative_path_result=
+ func_normal_abspath "$1"
+ func_relative_path_tlibdir=$func_normal_abspath_result
+ func_normal_abspath "$2"
+ func_relative_path_tbindir=$func_normal_abspath_result
+
+ # Ascend the tree starting from libdir
+ while :; do
+ # check if we have found a prefix of bindir
+ case $func_relative_path_tbindir in
+ $func_relative_path_tlibdir)
+ # found an exact match
+ func_relative_path_tcancelled=
+ break
+ ;;
+ $func_relative_path_tlibdir*)
+ # found a matching prefix
+ func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir"
+ func_relative_path_tcancelled=$func_stripname_result
+ if test -z "$func_relative_path_result"; then
+ func_relative_path_result=.
+ fi
+ break
+ ;;
+ *)
+ func_dirname $func_relative_path_tlibdir
+ func_relative_path_tlibdir=$func_dirname_result
+ if test -z "$func_relative_path_tlibdir"; then
+ # Have to descend all the way to the root!
+ func_relative_path_result=../$func_relative_path_result
+ func_relative_path_tcancelled=$func_relative_path_tbindir
+ break
+ fi
+ func_relative_path_result=../$func_relative_path_result
+ ;;
+ esac
+ done
+
+ # Now calculate path; take care to avoid doubling-up slashes.
+ func_stripname '' '/' "$func_relative_path_result"
+ func_relative_path_result=$func_stripname_result
+ func_stripname '/' '/' "$func_relative_path_tcancelled"
+ if test -n "$func_stripname_result"; then
+ func_append func_relative_path_result "/$func_stripname_result"
+ fi
+
+ # Normalisation. If bindir is libdir, return '.' else relative path.
+ if test -n "$func_relative_path_result"; then
+ func_stripname './' '' "$func_relative_path_result"
+ func_relative_path_result=$func_stripname_result
+ fi
+
+ test -n "$func_relative_path_result" || func_relative_path_result=.
+
+ :
+}
+
+
+# func_quote_for_eval ARG...
+# --------------------------
+# Aesthetically quote ARGs to be evaled later.
+# This function returns two values:
+# i) func_quote_for_eval_result
+# double-quoted, suitable for a subsequent eval
+# ii) func_quote_for_eval_unquoted_result
+# has all characters that are still active within double
+# quotes backslashified.
+func_quote_for_eval ()
+{
+ $debug_cmd
+
+ func_quote_for_eval_unquoted_result=
+ func_quote_for_eval_result=
+ while test 0 -lt $#; do
+ case $1 in
+ *[\\\`\"\$]*)
+ _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;;
+ *)
+ _G_unquoted_arg=$1 ;;
+ esac
+ if test -n "$func_quote_for_eval_unquoted_result"; then
+ func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg"
+ else
+ func_append func_quote_for_eval_unquoted_result "$_G_unquoted_arg"
+ fi
+
+ case $_G_unquoted_arg in
+ # Double-quote args containing shell metacharacters to delay
+ # word splitting, command substitution and variable expansion
+ # for a subsequent eval.
+ # Many Bourne shells cannot handle close brackets correctly
+ # in scan sets, so we specify it separately.
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ _G_quoted_arg=\"$_G_unquoted_arg\"
+ ;;
+ *)
+ _G_quoted_arg=$_G_unquoted_arg
+ ;;
+ esac
+
+ if test -n "$func_quote_for_eval_result"; then
+ func_append func_quote_for_eval_result " $_G_quoted_arg"
+ else
+ func_append func_quote_for_eval_result "$_G_quoted_arg"
+ fi
+ shift
+ done
+}
+
+
+# func_quote_for_expand ARG
+# -------------------------
+# Aesthetically quote ARG to be evaled later; same as above,
+# but do not quote variable references.
+func_quote_for_expand ()
+{
+ $debug_cmd
+
+ case $1 in
+ *[\\\`\"]*)
+ _G_arg=`$ECHO "$1" | $SED \
+ -e "$sed_double_quote_subst" -e "$sed_double_backslash"` ;;
+ *)
+ _G_arg=$1 ;;
+ esac
+
+ case $_G_arg in
+ # Double-quote args containing shell metacharacters to delay
+ # word splitting and command substitution for a subsequent eval.
+ # Many Bourne shells cannot handle close brackets correctly
+ # in scan sets, so we specify it separately.
+ *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
+ _G_arg=\"$_G_arg\"
+ ;;
+ esac
+
+ func_quote_for_expand_result=$_G_arg
+}
+
+
+# func_stripname PREFIX SUFFIX NAME
+# ---------------------------------
+# strip PREFIX and SUFFIX from NAME, and store in func_stripname_result.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+if test yes = "$_G_HAVE_XSI_OPS"; then
+ eval 'func_stripname ()
+ {
+ $debug_cmd
+
+ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are
+ # positional parameters, so assign one to ordinary variable first.
+ func_stripname_result=$3
+ func_stripname_result=${func_stripname_result#"$1"}
+ func_stripname_result=${func_stripname_result%"$2"}
+ }'
+else
+ func_stripname ()
+ {
+ $debug_cmd
+
+ case $2 in
+ .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;;
+ *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;;
+ esac
+ }
+fi
+
+
+# func_show_eval CMD [FAIL_EXP]
+# -----------------------------
+# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is
+# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP
+# is given, then evaluate it.
+func_show_eval ()
+{
+ $debug_cmd
+
+ _G_cmd=$1
+ _G_fail_exp=${2-':'}
+
+ func_quote_for_expand "$_G_cmd"
+ eval "func_notquiet $func_quote_for_expand_result"
+
+ $opt_dry_run || {
+ eval "$_G_cmd"
+ _G_status=$?
+ if test 0 -ne "$_G_status"; then
+ eval "(exit $_G_status); $_G_fail_exp"
+ fi
+ }
+}
+
+
+# func_show_eval_locale CMD [FAIL_EXP]
+# ------------------------------------
+# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is
+# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP
+# is given, then evaluate it. Use the saved locale for evaluation.
+func_show_eval_locale ()
+{
+ $debug_cmd
+
+ _G_cmd=$1
+ _G_fail_exp=${2-':'}
+
+ $opt_quiet || {
+ func_quote_for_expand "$_G_cmd"
+ eval "func_echo $func_quote_for_expand_result"
+ }
+
+ $opt_dry_run || {
+ eval "$_G_user_locale
+ $_G_cmd"
+ _G_status=$?
+ eval "$_G_safe_locale"
+ if test 0 -ne "$_G_status"; then
+ eval "(exit $_G_status); $_G_fail_exp"
+ fi
+ }
+}
+
+
+# func_tr_sh
+# ----------
+# Turn $1 into a string suitable for a shell variable name.
+# Result is stored in $func_tr_sh_result. All characters
+# not in the set a-zA-Z0-9_ are replaced with '_'. Further,
+# if $1 begins with a digit, a '_' is prepended as well.
+func_tr_sh ()
+{
+ $debug_cmd
+
+ case $1 in
+ [0-9]* | *[!a-zA-Z0-9_]*)
+ func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'`
+ ;;
+ * )
+ func_tr_sh_result=$1
+ ;;
+ esac
+}
+
+
+# func_verbose ARG...
+# -------------------
+# Echo program name prefixed message in verbose mode only.
+func_verbose ()
+{
+ $debug_cmd
+
+ $opt_verbose && func_echo "$*"
+
+ :
+}
+
+
+# func_warn_and_continue ARG...
+# -----------------------------
+# Echo program name prefixed warning message to standard error.
+func_warn_and_continue ()
+{
+ $debug_cmd
+
+ $require_term_colors
+
+ func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2
+}
+
+
+# func_warning CATEGORY ARG...
+# ----------------------------
+# Echo program name prefixed warning message to standard error. Warning
+# messages can be filtered according to CATEGORY, where this function
+# elides messages where CATEGORY is not listed in the global variable
+# 'opt_warning_types'.
+func_warning ()
+{
+ $debug_cmd
+
+ # CATEGORY must be in the warning_categories list!
+ case " $warning_categories " in
+ *" $1 "*) ;;
+ *) func_internal_error "invalid warning category '$1'" ;;
+ esac
+
+ _G_category=$1
+ shift
+
+ case " $opt_warning_types " in
+ *" $_G_category "*) $warning_func ${1+"$@"} ;;
+ esac
+}
+
+
+# func_sort_ver VER1 VER2
+# -----------------------
+# 'sort -V' is not generally available.
+# Note this deviates from the version comparison in automake
+# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a
+# but this should suffice as we won't be specifying old
+# version formats or redundant trailing .0 in bootstrap.conf.
+# If we did want full compatibility then we should probably
+# use m4_version_compare from autoconf.
+func_sort_ver ()
+{
+ $debug_cmd
+
+ printf '%s\n%s\n' "$1" "$2" \
+ | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n
+}
+
+# func_lt_ver PREV CURR
+# ---------------------
+# Return true if PREV and CURR are in the correct order according to
+# func_sort_ver, otherwise false. Use it like this:
+#
+# func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..."
+func_lt_ver ()
+{
+ $debug_cmd
+
+ test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q`
+}
+
+
+# Local variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC"
+# time-stamp-time-zone: "UTC"
+# End:
+#! /bin/sh
+
+# Set a version string for this script.
+scriptversion=2014-01-07.03; # UTC
+
+# A portable, pluggable option parser for Bourne shell.
+# Written by Gary V. Vaughan, 2010
+
+# Copyright (C) 2010-2015 Free Software Foundation, Inc.
+# This is free software; see the source for copying conditions. There is NO
+# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Please report bugs or propose patches to gary@gnu.org.
+
+
+## ------ ##
+## Usage. ##
+## ------ ##
+
+# This file is a library for parsing options in your shell scripts along
+# with assorted other useful supporting features that you can make use
+# of too.
+#
+# For the simplest scripts you might need only:
+#
+# #!/bin/sh
+# . relative/path/to/funclib.sh
+# . relative/path/to/options-parser
+# scriptversion=1.0
+# func_options ${1+"$@"}
+# eval set dummy "$func_options_result"; shift
+# ...rest of your script...
+#
+# In order for the '--version' option to work, you will need to have a
+# suitably formatted comment like the one at the top of this file
+# starting with '# Written by ' and ending with '# warranty; '.
+#
+# For '-h' and '--help' to work, you will also need a one line
+# description of your script's purpose in a comment directly above the
+# '# Written by ' line, like the one at the top of this file.
+#
+# The default options also support '--debug', which will turn on shell
+# execution tracing (see the comment above debug_cmd below for another
+# use), and '--verbose' and the func_verbose function to allow your script
+# to display verbose messages only when your user has specified
+# '--verbose'.
+#
+# After sourcing this file, you can plug processing for additional
+# options by amending the variables from the 'Configuration' section
+# below, and following the instructions in the 'Option parsing'
+# section further down.
+
+## -------------- ##
+## Configuration. ##
+## -------------- ##
+
+# You should override these variables in your script after sourcing this
+# file so that they reflect the customisations you have added to the
+# option parser.
+
+# The usage line for option parsing errors and the start of '-h' and
+# '--help' output messages. You can embed shell variables for delayed
+# expansion at the time the message is displayed, but you will need to
+# quote other shell meta-characters carefully to prevent them being
+# expanded when the contents are evaled.
+usage='$progpath [OPTION]...'
+
+# Short help message in response to '-h' and '--help'. Add to this or
+# override it after sourcing this library to reflect the full set of
+# options your script accepts.
+usage_message="\
+ --debug enable verbose shell tracing
+ -W, --warnings=CATEGORY
+ report the warnings falling in CATEGORY [all]
+ -v, --verbose verbosely report processing
+ --version print version information and exit
+ -h, --help print short or long help message and exit
+"
+
+# Additional text appended to 'usage_message' in response to '--help'.
+long_help_message="
+Warning categories include:
+ 'all' show all warnings
+ 'none' turn off all the warnings
+ 'error' warnings are treated as fatal errors"
+
+# Help message printed before fatal option parsing errors.
+fatal_help="Try '\$progname --help' for more information."
+
+
+
+## ------------------------- ##
+## Hook function management. ##
+## ------------------------- ##
+
+# This section contains functions for adding, removing, and running hooks
+# to the main code. A hook is just a named list of of function, that can
+# be run in order later on.
+
+# func_hookable FUNC_NAME
+# -----------------------
+# Declare that FUNC_NAME will run hooks added with
+# 'func_add_hook FUNC_NAME ...'.
+func_hookable ()
+{
+ $debug_cmd
+
+ func_append hookable_fns " $1"
+}
+
+
+# func_add_hook FUNC_NAME HOOK_FUNC
+# ---------------------------------
+# Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must
+# first have been declared "hookable" by a call to 'func_hookable'.
+func_add_hook ()
+{
+ $debug_cmd
+
+ case " $hookable_fns " in
+ *" $1 "*) ;;
+ *) func_fatal_error "'$1' does not accept hook functions." ;;
+ esac
+
+ eval func_append ${1}_hooks '" $2"'
+}
+
+
+# func_remove_hook FUNC_NAME HOOK_FUNC
+# ------------------------------------
+# Remove HOOK_FUNC from the list of functions called by FUNC_NAME.
+func_remove_hook ()
+{
+ $debug_cmd
+
+ eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`'
+}
+
+
+# func_run_hooks FUNC_NAME [ARG]...
+# ---------------------------------
+# Run all hook functions registered to FUNC_NAME.
+# It is assumed that the list of hook functions contains nothing more
+# than a whitespace-delimited list of legal shell function names, and
+# no effort is wasted trying to catch shell meta-characters or preserve
+# whitespace.
+func_run_hooks ()
+{
+ $debug_cmd
+
+ case " $hookable_fns " in
+ *" $1 "*) ;;
+ *) func_fatal_error "'$1' does not support hook funcions.n" ;;
+ esac
+
+ eval _G_hook_fns=\$$1_hooks; shift
+
+ for _G_hook in $_G_hook_fns; do
+ eval $_G_hook '"$@"'
+
+ # store returned options list back into positional
+ # parameters for next 'cmd' execution.
+ eval _G_hook_result=\$${_G_hook}_result
+ eval set dummy "$_G_hook_result"; shift
+ done
+
+ func_quote_for_eval ${1+"$@"}
+ func_run_hooks_result=$func_quote_for_eval_result
+}
+
+
+
+## --------------- ##
+## Option parsing. ##
+## --------------- ##
+
+# In order to add your own option parsing hooks, you must accept the
+# full positional parameter list in your hook function, remove any
+# options that you action, and then pass back the remaining unprocessed
+# options in '<hooked_function_name>_result', escaped suitably for
+# 'eval'. Like this:
+#
+# my_options_prep ()
+# {
+# $debug_cmd
+#
+# # Extend the existing usage message.
+# usage_message=$usage_message'
+# -s, --silent don'\''t print informational messages
+# '
+#
+# func_quote_for_eval ${1+"$@"}
+# my_options_prep_result=$func_quote_for_eval_result
+# }
+# func_add_hook func_options_prep my_options_prep
+#
+#
+# my_silent_option ()
+# {
+# $debug_cmd
+#
+# # Note that for efficiency, we parse as many options as we can
+# # recognise in a loop before passing the remainder back to the
+# # caller on the first unrecognised argument we encounter.
+# while test $# -gt 0; do
+# opt=$1; shift
+# case $opt in
+# --silent|-s) opt_silent=: ;;
+# # Separate non-argument short options:
+# -s*) func_split_short_opt "$_G_opt"
+# set dummy "$func_split_short_opt_name" \
+# "-$func_split_short_opt_arg" ${1+"$@"}
+# shift
+# ;;
+# *) set dummy "$_G_opt" "$*"; shift; break ;;
+# esac
+# done
+#
+# func_quote_for_eval ${1+"$@"}
+# my_silent_option_result=$func_quote_for_eval_result
+# }
+# func_add_hook func_parse_options my_silent_option
+#
+#
+# my_option_validation ()
+# {
+# $debug_cmd
+#
+# $opt_silent && $opt_verbose && func_fatal_help "\
+# '--silent' and '--verbose' options are mutually exclusive."
+#
+# func_quote_for_eval ${1+"$@"}
+# my_option_validation_result=$func_quote_for_eval_result
+# }
+# func_add_hook func_validate_options my_option_validation
+#
+# You'll alse need to manually amend $usage_message to reflect the extra
+# options you parse. It's preferable to append if you can, so that
+# multiple option parsing hooks can be added safely.
+
+
+# func_options [ARG]...
+# ---------------------
+# All the functions called inside func_options are hookable. See the
+# individual implementations for details.
+func_hookable func_options
+func_options ()
+{
+ $debug_cmd
+
+ func_options_prep ${1+"$@"}
+ eval func_parse_options \
+ ${func_options_prep_result+"$func_options_prep_result"}
+ eval func_validate_options \
+ ${func_parse_options_result+"$func_parse_options_result"}
+
+ eval func_run_hooks func_options \
+ ${func_validate_options_result+"$func_validate_options_result"}
+
+ # save modified positional parameters for caller
+ func_options_result=$func_run_hooks_result
+}
+
+
+# func_options_prep [ARG]...
+# --------------------------
+# All initialisations required before starting the option parse loop.
+# Note that when calling hook functions, we pass through the list of
+# positional parameters. If a hook function modifies that list, and
+# needs to propogate that back to rest of this script, then the complete
+# modified list must be put in 'func_run_hooks_result' before
+# returning.
+func_hookable func_options_prep
+func_options_prep ()
+{
+ $debug_cmd
+
+ # Option defaults:
+ opt_verbose=false
+ opt_warning_types=
+
+ func_run_hooks func_options_prep ${1+"$@"}
+
+ # save modified positional parameters for caller
+ func_options_prep_result=$func_run_hooks_result
+}
+
+
+# func_parse_options [ARG]...
+# ---------------------------
+# The main option parsing loop.
+func_hookable func_parse_options
+func_parse_options ()
+{
+ $debug_cmd
+
+ func_parse_options_result=
+
+ # this just eases exit handling
+ while test $# -gt 0; do
+ # Defer to hook functions for initial option parsing, so they
+ # get priority in the event of reusing an option name.
+ func_run_hooks func_parse_options ${1+"$@"}
+
+ # Adjust func_parse_options positional parameters to match
+ eval set dummy "$func_run_hooks_result"; shift
+
+ # Break out of the loop if we already parsed every option.
+ test $# -gt 0 || break
+
+ _G_opt=$1
+ shift
+ case $_G_opt in
+ --debug|-x) debug_cmd='set -x'
+ func_echo "enabling shell trace mode"
+ $debug_cmd
+ ;;
+
+ --no-warnings|--no-warning|--no-warn)
+ set dummy --warnings none ${1+"$@"}
+ shift
+ ;;
+
+ --warnings|--warning|-W)
+ test $# = 0 && func_missing_arg $_G_opt && break
+ case " $warning_categories $1" in
+ *" $1 "*)
+ # trailing space prevents matching last $1 above
+ func_append_uniq opt_warning_types " $1"
+ ;;
+ *all)
+ opt_warning_types=$warning_categories
+ ;;
+ *none)
+ opt_warning_types=none
+ warning_func=:
+ ;;
+ *error)
+ opt_warning_types=$warning_categories
+ warning_func=func_fatal_error
+ ;;
+ *)
+ func_fatal_error \
+ "unsupported warning category: '$1'"
+ ;;
+ esac
+ shift
+ ;;
+
+ --verbose|-v) opt_verbose=: ;;
+ --version) func_version ;;
+ -\?|-h) func_usage ;;
+ --help) func_help ;;
+
+ # Separate optargs to long options (plugins may need this):
+ --*=*) func_split_equals "$_G_opt"
+ set dummy "$func_split_equals_lhs" \
+ "$func_split_equals_rhs" ${1+"$@"}
+ shift
+ ;;
+
+ # Separate optargs to short options:
+ -W*)
+ func_split_short_opt "$_G_opt"
+ set dummy "$func_split_short_opt_name" \
+ "$func_split_short_opt_arg" ${1+"$@"}
+ shift
+ ;;
+
+ # Separate non-argument short options:
+ -\?*|-h*|-v*|-x*)
+ func_split_short_opt "$_G_opt"
+ set dummy "$func_split_short_opt_name" \
+ "-$func_split_short_opt_arg" ${1+"$@"}
+ shift
+ ;;
+
+ --) break ;;
+ -*) func_fatal_help "unrecognised option: '$_G_opt'" ;;
+ *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;;
+ esac
+ done
+
+ # save modified positional parameters for caller
+ func_quote_for_eval ${1+"$@"}
+ func_parse_options_result=$func_quote_for_eval_result
+}
+
+
+# func_validate_options [ARG]...
+# ------------------------------
+# Perform any sanity checks on option settings and/or unconsumed
+# arguments.
+func_hookable func_validate_options
+func_validate_options ()
+{
+ $debug_cmd
+
+ # Display all warnings if -W was not given.
+ test -n "$opt_warning_types" || opt_warning_types=" $warning_categories"
+
+ func_run_hooks func_validate_options ${1+"$@"}
+
+ # Bail if the options were screwed!
+ $exit_cmd $EXIT_FAILURE
+
+ # save modified positional parameters for caller
+ func_validate_options_result=$func_run_hooks_result
+}
+
+
+
+## ----------------- ##
+## Helper functions. ##
+## ----------------- ##
+
+# This section contains the helper functions used by the rest of the
+# hookable option parser framework in ascii-betical order.
+
+
+# func_fatal_help ARG...
+# ----------------------
+# Echo program name prefixed message to standard error, followed by
+# a help hint, and exit.
+func_fatal_help ()
+{
+ $debug_cmd
+
+ eval \$ECHO \""Usage: $usage"\"
+ eval \$ECHO \""$fatal_help"\"
+ func_error ${1+"$@"}
+ exit $EXIT_FAILURE
+}
+
+
+# func_help
+# ---------
+# Echo long help message to standard output and exit.
+func_help ()
+{
+ $debug_cmd
+
+ func_usage_message
+ $ECHO "$long_help_message"
+ exit 0
+}
+
+
+# func_missing_arg ARGNAME
+# ------------------------
+# Echo program name prefixed message to standard error and set global
+# exit_cmd.
+func_missing_arg ()
+{
+ $debug_cmd
+
+ func_error "Missing argument for '$1'."
+ exit_cmd=exit
+}
+
+
+# func_split_equals STRING
+# ------------------------
+# Set func_split_equals_lhs and func_split_equals_rhs shell variables after
+# splitting STRING at the '=' sign.
+test -z "$_G_HAVE_XSI_OPS" \
+ && (eval 'x=a/b/c;
+ test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \
+ && _G_HAVE_XSI_OPS=yes
+
+if test yes = "$_G_HAVE_XSI_OPS"
+then
+ # This is an XSI compatible shell, allowing a faster implementation...
+ eval 'func_split_equals ()
+ {
+ $debug_cmd
+
+ func_split_equals_lhs=${1%%=*}
+ func_split_equals_rhs=${1#*=}
+ test "x$func_split_equals_lhs" = "x$1" \
+ && func_split_equals_rhs=
+ }'
+else
+ # ...otherwise fall back to using expr, which is often a shell builtin.
+ func_split_equals ()
+ {
+ $debug_cmd
+
+ func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'`
+ func_split_equals_rhs=
+ test "x$func_split_equals_lhs" = "x$1" \
+ || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'`
+ }
+fi #func_split_equals
+
+
+# func_split_short_opt SHORTOPT
+# -----------------------------
+# Set func_split_short_opt_name and func_split_short_opt_arg shell
+# variables after splitting SHORTOPT after the 2nd character.
+if test yes = "$_G_HAVE_XSI_OPS"
+then
+ # This is an XSI compatible shell, allowing a faster implementation...
+ eval 'func_split_short_opt ()
+ {
+ $debug_cmd
+
+ func_split_short_opt_arg=${1#??}
+ func_split_short_opt_name=${1%"$func_split_short_opt_arg"}
+ }'
+else
+ # ...otherwise fall back to using expr, which is often a shell builtin.
+ func_split_short_opt ()
+ {
+ $debug_cmd
+
+ func_split_short_opt_name=`expr "x$1" : 'x-\(.\)'`
+ func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'`
+ }
+fi #func_split_short_opt
+
+
+# func_usage
+# ----------
+# Echo short help message to standard output and exit.
+func_usage ()
+{
+ $debug_cmd
+
+ func_usage_message
+ $ECHO "Run '$progname --help |${PAGER-more}' for full usage"
+ exit 0
+}
+
+
+# func_usage_message
+# ------------------
+# Echo short help message to standard output.
+func_usage_message ()
+{
+ $debug_cmd
+
+ eval \$ECHO \""Usage: $usage"\"
+ echo
+ $SED -n 's|^# ||
+ /^Written by/{
+ x;p;x
+ }
+ h
+ /^Written by/q' < "$progpath"
+ echo
+ eval \$ECHO \""$usage_message"\"
+}
+
+
+# func_version
+# ------------
+# Echo version message to standard output and exit.
+func_version ()
+{
+ $debug_cmd
+
+ printf '%s\n' "$progname $scriptversion"
+ $SED -n '
+ /(C)/!b go
+ :more
+ /\./!{
+ N
+ s|\n# | |
+ b more
+ }
+ :go
+ /^# Written by /,/# warranty; / {
+ s|^# ||
+ s|^# *$||
+ s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2|
+ p
+ }
+ /^# Written by / {
+ s|^# ||
+ p
+ }
+ /^warranty; /q' < "$progpath"
+
+ exit $?
+}
+
+
+# Local variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC"
+# time-stamp-time-zone: "UTC"
+# End:
+
+# Set a version string.
+scriptversion='(GNU libtool) 2.4.6'
+
+
+# func_echo ARG...
+# ----------------
+# Libtool also displays the current mode in messages, so override
+# funclib.sh func_echo with this custom definition.
+func_echo ()
+{
+ $debug_cmd
+
+ _G_message=$*
+
+ func_echo_IFS=$IFS
+ IFS=$nl
+ for _G_line in $_G_message; do
+ IFS=$func_echo_IFS
+ $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line"
+ done
+ IFS=$func_echo_IFS
+}
+
+
+# func_warning ARG...
+# -------------------
+# Libtool warnings are not categorized, so override funclib.sh
+# func_warning with this simpler definition.
+func_warning ()
+{
+ $debug_cmd
+
+ $warning_func ${1+"$@"}
+}
+
+
+## ---------------- ##
+## Options parsing. ##
+## ---------------- ##
+
+# Hook in the functions to make sure our own options are parsed during
+# the option parsing loop.
+
+usage='$progpath [OPTION]... [MODE-ARG]...'
+
+# Short help message in response to '-h'.
+usage_message="Options:
+ --config show all configuration variables
+ --debug enable verbose shell tracing
+ -n, --dry-run display commands without modifying any files
+ --features display basic configuration information and exit
+ --mode=MODE use operation mode MODE
+ --no-warnings equivalent to '-Wnone'
+ --preserve-dup-deps don't remove duplicate dependency libraries
+ --quiet, --silent don't print informational messages
+ --tag=TAG use configuration variables from tag TAG
+ -v, --verbose print more informational messages than default
+ --version print version information
+ -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all]
+ -h, --help, --help-all print short, long, or detailed help message
+"
+
+# Additional text appended to 'usage_message' in response to '--help'.
+func_help ()
+{
+ $debug_cmd
+
+ func_usage_message
+ $ECHO "$long_help_message
+
+MODE must be one of the following:
+
+ clean remove files from the build directory
+ compile compile a source file into a libtool object
+ execute automatically set library path, then run a program
+ finish complete the installation of libtool libraries
+ install install libraries or executables
+ link create a library or an executable
+ uninstall remove libraries from an installed directory
+
+MODE-ARGS vary depending on the MODE. When passed as first option,
+'--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that.
+Try '$progname --help --mode=MODE' for a more detailed description of MODE.
+
+When reporting a bug, please describe a test case to reproduce it and
+include the following information:
+
+ host-triplet: $host
+ shell: $SHELL
+ compiler: $LTCC
+ compiler flags: $LTCFLAGS
+ linker: $LD (gnu? $with_gnu_ld)
+ version: $progname (GNU libtool) 2.4.6
+ automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q`
+ autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q`
+
+Report bugs to <bug-libtool@gnu.org>.
+GNU libtool home page: <http://www.gnu.org/software/libtool/>.
+General help using GNU software: <http://www.gnu.org/gethelp/>."
+ exit 0
+}
+
+
+# func_lo2o OBJECT-NAME
+# ---------------------
+# Transform OBJECT-NAME from a '.lo' suffix to the platform specific
+# object suffix.
+
+lo2o=s/\\.lo\$/.$objext/
+o2lo=s/\\.$objext\$/.lo/
+
+if test yes = "$_G_HAVE_XSI_OPS"; then
+ eval 'func_lo2o ()
+ {
+ case $1 in
+ *.lo) func_lo2o_result=${1%.lo}.$objext ;;
+ * ) func_lo2o_result=$1 ;;
+ esac
+ }'
+
+ # func_xform LIBOBJ-OR-SOURCE
+ # ---------------------------
+ # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise)
+ # suffix to a '.lo' libtool-object suffix.
+ eval 'func_xform ()
+ {
+ func_xform_result=${1%.*}.lo
+ }'
+else
+ # ...otherwise fall back to using sed.
+ func_lo2o ()
+ {
+ func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"`
+ }
+
+ func_xform ()
+ {
+ func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'`
+ }
+fi
+
+
+# func_fatal_configuration ARG...
+# -------------------------------
+# Echo program name prefixed message to standard error, followed by
+# a configuration failure hint, and exit.
+func_fatal_configuration ()
+{
+ func_fatal_error ${1+"$@"} \
+ "See the $PACKAGE documentation for more information." \
+ "Fatal configuration error."
+}
+
+
+# func_config
+# -----------
+# Display the configuration for all the tags in this script.
+func_config ()
+{
+ re_begincf='^# ### BEGIN LIBTOOL'
+ re_endcf='^# ### END LIBTOOL'
+
+ # Default configuration.
+ $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath"
+
+ # Now print the configurations for the tags.
+ for tagname in $taglist; do
+ $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath"
+ done
+
+ exit $?
+}
+
+
+# func_features
+# -------------
+# Display the features supported by this script.
+func_features ()
+{
+ echo "host: $host"
+ if test yes = "$build_libtool_libs"; then
+ echo "enable shared libraries"
+ else
+ echo "disable shared libraries"
+ fi
+ if test yes = "$build_old_libs"; then
+ echo "enable static libraries"
+ else
+ echo "disable static libraries"
+ fi
+
+ exit $?
+}
+
+
+# func_enable_tag TAGNAME
+# -----------------------
+# Verify that TAGNAME is valid, and either flag an error and exit, or
+# enable the TAGNAME tag. We also add TAGNAME to the global $taglist
+# variable here.
+func_enable_tag ()
+{
+ # Global variable:
+ tagname=$1
+
+ re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$"
+ re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$"
+ sed_extractcf=/$re_begincf/,/$re_endcf/p
+
+ # Validate tagname.
+ case $tagname in
+ *[!-_A-Za-z0-9,/]*)
+ func_fatal_error "invalid tag name: $tagname"
+ ;;
+ esac
+
+ # Don't test for the "default" C tag, as we know it's
+ # there but not specially marked.
+ case $tagname in
+ CC) ;;
+ *)
+ if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then
+ taglist="$taglist $tagname"
+
+ # Evaluate the configuration. Be careful to quote the path
+ # and the sed script, to avoid splitting on whitespace, but
+ # also don't use non-portable quotes within backquotes within
+ # quotes we have to do it in 2 steps:
+ extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"`
+ eval "$extractedcf"
+ else
+ func_error "ignoring unknown tag $tagname"
+ fi
+ ;;
+ esac
+}
+
+
+# func_check_version_match
+# ------------------------
+# Ensure that we are using m4 macros, and libtool script from the same
+# release of libtool.
+func_check_version_match ()
+{
+ if test "$package_revision" != "$macro_revision"; then
+ if test "$VERSION" != "$macro_version"; then
+ if test -z "$macro_version"; then
+ cat >&2 <<_LT_EOF
+$progname: Version mismatch error. This is $PACKAGE $VERSION, but the
+$progname: definition of this LT_INIT comes from an older release.
+$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
+$progname: and run autoconf again.
+_LT_EOF
+ else
+ cat >&2 <<_LT_EOF
+$progname: Version mismatch error. This is $PACKAGE $VERSION, but the
+$progname: definition of this LT_INIT comes from $PACKAGE $macro_version.
+$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION
+$progname: and run autoconf again.
+_LT_EOF
+ fi
+ else
+ cat >&2 <<_LT_EOF
+$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision,
+$progname: but the definition of this LT_INIT comes from revision $macro_revision.
+$progname: You should recreate aclocal.m4 with macros from revision $package_revision
+$progname: of $PACKAGE $VERSION and run autoconf again.
+_LT_EOF
+ fi
+
+ exit $EXIT_MISMATCH
+ fi
+}
+
+
+# libtool_options_prep [ARG]...
+# -----------------------------
+# Preparation for options parsed by libtool.
+libtool_options_prep ()
+{
+ $debug_mode
+
+ # Option defaults:
+ opt_config=false
+ opt_dlopen=
+ opt_dry_run=false
+ opt_help=false
+ opt_mode=
+ opt_preserve_dup_deps=false
+ opt_quiet=false
+
+ nonopt=
+ preserve_args=
+
+ # Shorthand for --mode=foo, only valid as the first argument
+ case $1 in
+ clean|clea|cle|cl)
+ shift; set dummy --mode clean ${1+"$@"}; shift
+ ;;
+ compile|compil|compi|comp|com|co|c)
+ shift; set dummy --mode compile ${1+"$@"}; shift
+ ;;
+ execute|execut|execu|exec|exe|ex|e)
+ shift; set dummy --mode execute ${1+"$@"}; shift
+ ;;
+ finish|finis|fini|fin|fi|f)
+ shift; set dummy --mode finish ${1+"$@"}; shift
+ ;;
+ install|instal|insta|inst|ins|in|i)
+ shift; set dummy --mode install ${1+"$@"}; shift
+ ;;
+ link|lin|li|l)
+ shift; set dummy --mode link ${1+"$@"}; shift
+ ;;
+ uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u)
+ shift; set dummy --mode uninstall ${1+"$@"}; shift
+ ;;
+ esac
+
+ # Pass back the list of options.
+ func_quote_for_eval ${1+"$@"}
+ libtool_options_prep_result=$func_quote_for_eval_result
+}
+func_add_hook func_options_prep libtool_options_prep
+
+
+# libtool_parse_options [ARG]...
+# ---------------------------------
+# Provide handling for libtool specific options.
+libtool_parse_options ()
+{
+ $debug_cmd
+
+ # Perform our own loop to consume as many options as possible in
+ # each iteration.
+ while test $# -gt 0; do
+ _G_opt=$1
+ shift
+ case $_G_opt in
+ --dry-run|--dryrun|-n)
+ opt_dry_run=:
+ ;;
+
+ --config) func_config ;;
+
+ --dlopen|-dlopen)
+ opt_dlopen="${opt_dlopen+$opt_dlopen
+}$1"
+ shift
+ ;;
+
+ --preserve-dup-deps)
+ opt_preserve_dup_deps=: ;;
+
+ --features) func_features ;;
+
+ --finish) set dummy --mode finish ${1+"$@"}; shift ;;
+
+ --help) opt_help=: ;;
+
+ --help-all) opt_help=': help-all' ;;
+
+ --mode) test $# = 0 && func_missing_arg $_G_opt && break
+ opt_mode=$1
+ case $1 in
+ # Valid mode arguments:
+ clean|compile|execute|finish|install|link|relink|uninstall) ;;
+
+ # Catch anything else as an error
+ *) func_error "invalid argument for $_G_opt"
+ exit_cmd=exit
+ break
+ ;;
+ esac
+ shift
+ ;;
+
+ --no-silent|--no-quiet)
+ opt_quiet=false
+ func_append preserve_args " $_G_opt"
+ ;;
+
+ --no-warnings|--no-warning|--no-warn)
+ opt_warning=false
+ func_append preserve_args " $_G_opt"
+ ;;
+
+ --no-verbose)
+ opt_verbose=false
+ func_append preserve_args " $_G_opt"
+ ;;
+
+ --silent|--quiet)
+ opt_quiet=:
+ opt_verbose=false
+ func_append preserve_args " $_G_opt"
+ ;;
+
+ --tag) test $# = 0 && func_missing_arg $_G_opt && break
+ opt_tag=$1
+ func_append preserve_args " $_G_opt $1"
+ func_enable_tag "$1"
+ shift
+ ;;
+
+ --verbose|-v) opt_quiet=false
+ opt_verbose=:
+ func_append preserve_args " $_G_opt"
+ ;;
+
+ # An option not handled by this hook function:
+ *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;;
+ esac
+ done
+
+
+ # save modified positional parameters for caller
+ func_quote_for_eval ${1+"$@"}
+ libtool_parse_options_result=$func_quote_for_eval_result
+}
+func_add_hook func_parse_options libtool_parse_options
+
+
+
+# libtool_validate_options [ARG]...
+# ---------------------------------
+# Perform any sanity checks on option settings and/or unconsumed
+# arguments.
+libtool_validate_options ()
+{
+ # save first non-option argument
+ if test 0 -lt $#; then
+ nonopt=$1
+ shift
+ fi
+
+ # preserve --debug
+ test : = "$debug_cmd" || func_append preserve_args " --debug"
+
+ case $host in
+ # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452
+ # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788
+ *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*)
+ # don't eliminate duplications in $postdeps and $predeps
+ opt_duplicate_compiler_generated_deps=:
+ ;;
+ *)
+ opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps
+ ;;
+ esac
+
+ $opt_help || {
+ # Sanity checks first:
+ func_check_version_match
+
+ test yes != "$build_libtool_libs" \
+ && test yes != "$build_old_libs" \
+ && func_fatal_configuration "not configured to build any kind of library"
+
+ # Darwin sucks
+ eval std_shrext=\"$shrext_cmds\"
+
+ # Only execute mode is allowed to have -dlopen flags.
+ if test -n "$opt_dlopen" && test execute != "$opt_mode"; then
+ func_error "unrecognized option '-dlopen'"
+ $ECHO "$help" 1>&2
+ exit $EXIT_FAILURE
+ fi
+
+ # Change the help message to a mode-specific one.
+ generic_help=$help
+ help="Try '$progname --help --mode=$opt_mode' for more information."
+ }
+
+ # Pass back the unparsed argument list
+ func_quote_for_eval ${1+"$@"}
+ libtool_validate_options_result=$func_quote_for_eval_result
+}
+func_add_hook func_validate_options libtool_validate_options
+
+
+# Process options as early as possible so that --help and --version
+# can return quickly.
+func_options ${1+"$@"}
+eval set dummy "$func_options_result"; shift
+
+
+
+## ----------- ##
+## Main. ##
+## ----------- ##
+
+magic='%%%MAGIC variable%%%'
+magic_exe='%%%MAGIC EXE variable%%%'
+
+# Global variables.
+extracted_archives=
+extracted_serial=0
+
+# If this variable is set in any of the actions, the command in it
+# will be execed at the end. This prevents here-documents from being
+# left over by shells.
+exec_cmd=
+
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+ eval 'cat <<_LTECHO_EOF
+$1
+_LTECHO_EOF'
+}
+
+# func_generated_by_libtool
+# True iff stdin has been generated by Libtool. This function is only
+# a basic sanity check; it will hardly flush out determined imposters.
+func_generated_by_libtool_p ()
+{
+ $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1
+}
+
+# func_lalib_p file
+# True iff FILE is a libtool '.la' library or '.lo' object file.
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_lalib_p ()
+{
+ test -f "$1" &&
+ $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p
+}
+
+# func_lalib_unsafe_p file
+# True iff FILE is a libtool '.la' library or '.lo' object file.
+# This function implements the same check as func_lalib_p without
+# resorting to external programs. To this end, it redirects stdin and
+# closes it afterwards, without saving the original file descriptor.
+# As a safety measure, use it only where a negative result would be
+# fatal anyway. Works if 'file' does not exist.
+func_lalib_unsafe_p ()
+{
+ lalib_p=no
+ if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then
+ for lalib_p_l in 1 2 3 4
+ do
+ read lalib_p_line
+ case $lalib_p_line in
+ \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;;
+ esac
+ done
+ exec 0<&5 5<&-
+ fi
+ test yes = "$lalib_p"
+}
+
+# func_ltwrapper_script_p file
+# True iff FILE is a libtool wrapper script
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_script_p ()
+{
+ test -f "$1" &&
+ $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p
+}
+
+# func_ltwrapper_executable_p file
+# True iff FILE is a libtool wrapper executable
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_executable_p ()
+{
+ func_ltwrapper_exec_suffix=
+ case $1 in
+ *.exe) ;;
+ *) func_ltwrapper_exec_suffix=.exe ;;
+ esac
+ $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1
+}
+
+# func_ltwrapper_scriptname file
+# Assumes file is an ltwrapper_executable
+# uses $file to determine the appropriate filename for a
+# temporary ltwrapper_script.
+func_ltwrapper_scriptname ()
+{
+ func_dirname_and_basename "$1" "" "."
+ func_stripname '' '.exe' "$func_basename_result"
+ func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper
+}
+
+# func_ltwrapper_p file
+# True iff FILE is a libtool wrapper script or wrapper executable
+# This function is only a basic sanity check; it will hardly flush out
+# determined imposters.
+func_ltwrapper_p ()
+{
+ func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1"
+}
+
+
+# func_execute_cmds commands fail_cmd
+# Execute tilde-delimited COMMANDS.
+# If FAIL_CMD is given, eval that upon failure.
+# FAIL_CMD may read-access the current command in variable CMD!
+func_execute_cmds ()
+{
+ $debug_cmd
+
+ save_ifs=$IFS; IFS='~'
+ for cmd in $1; do
+ IFS=$sp$nl
+ eval cmd=\"$cmd\"
+ IFS=$save_ifs
+ func_show_eval "$cmd" "${2-:}"
+ done
+ IFS=$save_ifs
+}
+
+
+# func_source file
+# Source FILE, adding directory component if necessary.
+# Note that it is not necessary on cygwin/mingw to append a dot to
+# FILE even if both FILE and FILE.exe exist: automatic-append-.exe
+# behavior happens only for exec(3), not for open(2)! Also, sourcing
+# 'FILE.' does not work on cygwin managed mounts.
+func_source ()
+{
+ $debug_cmd
+
+ case $1 in
+ */* | *\\*) . "$1" ;;
+ *) . "./$1" ;;
+ esac
+}
+
+
+# func_resolve_sysroot PATH
+# Replace a leading = in PATH with a sysroot. Store the result into
+# func_resolve_sysroot_result
+func_resolve_sysroot ()
+{
+ func_resolve_sysroot_result=$1
+ case $func_resolve_sysroot_result in
+ =*)
+ func_stripname '=' '' "$func_resolve_sysroot_result"
+ func_resolve_sysroot_result=$lt_sysroot$func_stripname_result
+ ;;
+ esac
+}
+
+# func_replace_sysroot PATH
+# If PATH begins with the sysroot, replace it with = and
+# store the result into func_replace_sysroot_result.
+func_replace_sysroot ()
+{
+ case $lt_sysroot:$1 in
+ ?*:"$lt_sysroot"*)
+ func_stripname "$lt_sysroot" '' "$1"
+ func_replace_sysroot_result='='$func_stripname_result
+ ;;
+ *)
+ # Including no sysroot.
+ func_replace_sysroot_result=$1
+ ;;
+ esac
+}
+
+# func_infer_tag arg
+# Infer tagged configuration to use if any are available and
+# if one wasn't chosen via the "--tag" command line option.
+# Only attempt this if the compiler in the base compile
+# command doesn't match the default compiler.
+# arg is usually of the form 'gcc ...'
+func_infer_tag ()
+{
+ $debug_cmd
+
+ if test -n "$available_tags" && test -z "$tagname"; then
+ CC_quoted=
+ for arg in $CC; do
+ func_append_quoted CC_quoted "$arg"
+ done
+ CC_expanded=`func_echo_all $CC`
+ CC_quoted_expanded=`func_echo_all $CC_quoted`
+ case $@ in
+ # Blanks in the command may have been stripped by the calling shell,
+ # but not from the CC environment variable when configure was run.
+ " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \
+ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;;
+ # Blanks at the start of $base_compile will cause this to fail
+ # if we don't check for them as well.
+ *)
+ for z in $available_tags; do
+ if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then
+ # Evaluate the configuration.
+ eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`"
+ CC_quoted=
+ for arg in $CC; do
+ # Double-quote args containing other shell metacharacters.
+ func_append_quoted CC_quoted "$arg"
+ done
+ CC_expanded=`func_echo_all $CC`
+ CC_quoted_expanded=`func_echo_all $CC_quoted`
+ case "$@ " in
+ " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \
+ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*)
+ # The compiler in the base compile command matches
+ # the one in the tagged configuration.
+ # Assume this is the tagged configuration we want.
+ tagname=$z
+ break
+ ;;
+ esac
+ fi
+ done
+ # If $tagname still isn't set, then no tagged configuration
+ # was found and let the user know that the "--tag" command
+ # line option must be used.
+ if test -z "$tagname"; then
+ func_echo "unable to infer tagged configuration"
+ func_fatal_error "specify a tag with '--tag'"
+# else
+# func_verbose "using $tagname tagged configuration"
+ fi
+ ;;
+ esac
+ fi
+}
+
+
+
+# func_write_libtool_object output_name pic_name nonpic_name
+# Create a libtool object file (analogous to a ".la" file),
+# but don't create it if we're doing a dry run.
+func_write_libtool_object ()
+{
+ write_libobj=$1
+ if test yes = "$build_libtool_libs"; then
+ write_lobj=\'$2\'
+ else
+ write_lobj=none
+ fi
+
+ if test yes = "$build_old_libs"; then
+ write_oldobj=\'$3\'
+ else
+ write_oldobj=none
+ fi
+
+ $opt_dry_run || {
+ cat >${write_libobj}T <<EOF
+# $write_libobj - a libtool object file
+# Generated by $PROGRAM (GNU $PACKAGE) $VERSION
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# Name of the PIC object.
+pic_object=$write_lobj
+
+# Name of the non-PIC object
+non_pic_object=$write_oldobj
+
+EOF
+ $MV "${write_libobj}T" "$write_libobj"
+ }
+}
+
+
+##################################################
+# FILE NAME AND PATH CONVERSION HELPER FUNCTIONS #
+##################################################
+
+# func_convert_core_file_wine_to_w32 ARG
+# Helper function used by file name conversion functions when $build is *nix,
+# and $host is mingw, cygwin, or some other w32 environment. Relies on a
+# correctly configured wine environment available, with the winepath program
+# in $build's $PATH.
+#
+# ARG is the $build file name to be converted to w32 format.
+# Result is available in $func_convert_core_file_wine_to_w32_result, and will
+# be empty on error (or when ARG is empty)
+func_convert_core_file_wine_to_w32 ()
+{
+ $debug_cmd
+
+ func_convert_core_file_wine_to_w32_result=$1
+ if test -n "$1"; then
+ # Unfortunately, winepath does not exit with a non-zero error code, so we
+ # are forced to check the contents of stdout. On the other hand, if the
+ # command is not found, the shell will set an exit code of 127 and print
+ # *an error message* to stdout. So we must check for both error code of
+ # zero AND non-empty stdout, which explains the odd construction:
+ func_convert_core_file_wine_to_w32_tmp=`winepath -w "$1" 2>/dev/null`
+ if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then
+ func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" |
+ $SED -e "$sed_naive_backslashify"`
+ else
+ func_convert_core_file_wine_to_w32_result=
+ fi
+ fi
+}
+# end: func_convert_core_file_wine_to_w32
+
+
+# func_convert_core_path_wine_to_w32 ARG
+# Helper function used by path conversion functions when $build is *nix, and
+# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly
+# configured wine environment available, with the winepath program in $build's
+# $PATH. Assumes ARG has no leading or trailing path separator characters.
+#
+# ARG is path to be converted from $build format to win32.
+# Result is available in $func_convert_core_path_wine_to_w32_result.
+# Unconvertible file (directory) names in ARG are skipped; if no directory names
+# are convertible, then the result may be empty.
+func_convert_core_path_wine_to_w32 ()
+{
+ $debug_cmd
+
+ # unfortunately, winepath doesn't convert paths, only file names
+ func_convert_core_path_wine_to_w32_result=
+ if test -n "$1"; then
+ oldIFS=$IFS
+ IFS=:
+ for func_convert_core_path_wine_to_w32_f in $1; do
+ IFS=$oldIFS
+ func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f"
+ if test -n "$func_convert_core_file_wine_to_w32_result"; then
+ if test -z "$func_convert_core_path_wine_to_w32_result"; then
+ func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result
+ else
+ func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result"
+ fi
+ fi
+ done
+ IFS=$oldIFS
+ fi
+}
+# end: func_convert_core_path_wine_to_w32
+
+
+# func_cygpath ARGS...
+# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when
+# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2)
+# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or
+# (2), returns the Cygwin file name or path in func_cygpath_result (input
+# file name or path is assumed to be in w32 format, as previously converted
+# from $build's *nix or MSYS format). In case (3), returns the w32 file name
+# or path in func_cygpath_result (input file name or path is assumed to be in
+# Cygwin format). Returns an empty string on error.
+#
+# ARGS are passed to cygpath, with the last one being the file name or path to
+# be converted.
+#
+# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH
+# environment variable; do not put it in $PATH.
+func_cygpath ()
+{
+ $debug_cmd
+
+ if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then
+ func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null`
+ if test "$?" -ne 0; then
+ # on failure, ensure result is empty
+ func_cygpath_result=
+ fi
+ else
+ func_cygpath_result=
+ func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'"
+ fi
+}
+#end: func_cygpath
+
+
+# func_convert_core_msys_to_w32 ARG
+# Convert file name or path ARG from MSYS format to w32 format. Return
+# result in func_convert_core_msys_to_w32_result.
+func_convert_core_msys_to_w32 ()
+{
+ $debug_cmd
+
+ # awkward: cmd appends spaces to result
+ func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null |
+ $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"`
+}
+#end: func_convert_core_msys_to_w32
+
+
+# func_convert_file_check ARG1 ARG2
+# Verify that ARG1 (a file name in $build format) was converted to $host
+# format in ARG2. Otherwise, emit an error message, but continue (resetting
+# func_to_host_file_result to ARG1).
+func_convert_file_check ()
+{
+ $debug_cmd
+
+ if test -z "$2" && test -n "$1"; then
+ func_error "Could not determine host file name corresponding to"
+ func_error " '$1'"
+ func_error "Continuing, but uninstalled executables may not work."
+ # Fallback:
+ func_to_host_file_result=$1
+ fi
+}
+# end func_convert_file_check
+
+
+# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH
+# Verify that FROM_PATH (a path in $build format) was converted to $host
+# format in TO_PATH. Otherwise, emit an error message, but continue, resetting
+# func_to_host_file_result to a simplistic fallback value (see below).
+func_convert_path_check ()
+{
+ $debug_cmd
+
+ if test -z "$4" && test -n "$3"; then
+ func_error "Could not determine the host path corresponding to"
+ func_error " '$3'"
+ func_error "Continuing, but uninstalled executables may not work."
+ # Fallback. This is a deliberately simplistic "conversion" and
+ # should not be "improved". See libtool.info.
+ if test "x$1" != "x$2"; then
+ lt_replace_pathsep_chars="s|$1|$2|g"
+ func_to_host_path_result=`echo "$3" |
+ $SED -e "$lt_replace_pathsep_chars"`
+ else
+ func_to_host_path_result=$3
+ fi
+ fi
+}
+# end func_convert_path_check
+
+
+# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG
+# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT
+# and appending REPL if ORIG matches BACKPAT.
+func_convert_path_front_back_pathsep ()
+{
+ $debug_cmd
+
+ case $4 in
+ $1 ) func_to_host_path_result=$3$func_to_host_path_result
+ ;;
+ esac
+ case $4 in
+ $2 ) func_append func_to_host_path_result "$3"
+ ;;
+ esac
+}
+# end func_convert_path_front_back_pathsep
+
+
+##################################################
+# $build to $host FILE NAME CONVERSION FUNCTIONS #
+##################################################
+# invoked via '$to_host_file_cmd ARG'
+#
+# In each case, ARG is the path to be converted from $build to $host format.
+# Result will be available in $func_to_host_file_result.
+
+
+# func_to_host_file ARG
+# Converts the file name ARG from $build format to $host format. Return result
+# in func_to_host_file_result.
+func_to_host_file ()
+{
+ $debug_cmd
+
+ $to_host_file_cmd "$1"
+}
+# end func_to_host_file
+
+
+# func_to_tool_file ARG LAZY
+# converts the file name ARG from $build format to toolchain format. Return
+# result in func_to_tool_file_result. If the conversion in use is listed
+# in (the comma separated) LAZY, no conversion takes place.
+func_to_tool_file ()
+{
+ $debug_cmd
+
+ case ,$2, in
+ *,"$to_tool_file_cmd",*)
+ func_to_tool_file_result=$1
+ ;;
+ *)
+ $to_tool_file_cmd "$1"
+ func_to_tool_file_result=$func_to_host_file_result
+ ;;
+ esac
+}
+# end func_to_tool_file
+
+
+# func_convert_file_noop ARG
+# Copy ARG to func_to_host_file_result.
+func_convert_file_noop ()
+{
+ func_to_host_file_result=$1
+}
+# end func_convert_file_noop
+
+
+# func_convert_file_msys_to_w32 ARG
+# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic
+# conversion to w32 is not available inside the cwrapper. Returns result in
+# func_to_host_file_result.
+func_convert_file_msys_to_w32 ()
+{
+ $debug_cmd
+
+ func_to_host_file_result=$1
+ if test -n "$1"; then
+ func_convert_core_msys_to_w32 "$1"
+ func_to_host_file_result=$func_convert_core_msys_to_w32_result
+ fi
+ func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_msys_to_w32
+
+
+# func_convert_file_cygwin_to_w32 ARG
+# Convert file name ARG from Cygwin to w32 format. Returns result in
+# func_to_host_file_result.
+func_convert_file_cygwin_to_w32 ()
+{
+ $debug_cmd
+
+ func_to_host_file_result=$1
+ if test -n "$1"; then
+ # because $build is cygwin, we call "the" cygpath in $PATH; no need to use
+ # LT_CYGPATH in this case.
+ func_to_host_file_result=`cygpath -m "$1"`
+ fi
+ func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_cygwin_to_w32
+
+
+# func_convert_file_nix_to_w32 ARG
+# Convert file name ARG from *nix to w32 format. Requires a wine environment
+# and a working winepath. Returns result in func_to_host_file_result.
+func_convert_file_nix_to_w32 ()
+{
+ $debug_cmd
+
+ func_to_host_file_result=$1
+ if test -n "$1"; then
+ func_convert_core_file_wine_to_w32 "$1"
+ func_to_host_file_result=$func_convert_core_file_wine_to_w32_result
+ fi
+ func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_nix_to_w32
+
+
+# func_convert_file_msys_to_cygwin ARG
+# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set.
+# Returns result in func_to_host_file_result.
+func_convert_file_msys_to_cygwin ()
+{
+ $debug_cmd
+
+ func_to_host_file_result=$1
+ if test -n "$1"; then
+ func_convert_core_msys_to_w32 "$1"
+ func_cygpath -u "$func_convert_core_msys_to_w32_result"
+ func_to_host_file_result=$func_cygpath_result
+ fi
+ func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_msys_to_cygwin
+
+
+# func_convert_file_nix_to_cygwin ARG
+# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed
+# in a wine environment, working winepath, and LT_CYGPATH set. Returns result
+# in func_to_host_file_result.
+func_convert_file_nix_to_cygwin ()
+{
+ $debug_cmd
+
+ func_to_host_file_result=$1
+ if test -n "$1"; then
+ # convert from *nix to w32, then use cygpath to convert from w32 to cygwin.
+ func_convert_core_file_wine_to_w32 "$1"
+ func_cygpath -u "$func_convert_core_file_wine_to_w32_result"
+ func_to_host_file_result=$func_cygpath_result
+ fi
+ func_convert_file_check "$1" "$func_to_host_file_result"
+}
+# end func_convert_file_nix_to_cygwin
+
+
+#############################################
+# $build to $host PATH CONVERSION FUNCTIONS #
+#############################################
+# invoked via '$to_host_path_cmd ARG'
+#
+# In each case, ARG is the path to be converted from $build to $host format.
+# The result will be available in $func_to_host_path_result.
+#
+# Path separators are also converted from $build format to $host format. If
+# ARG begins or ends with a path separator character, it is preserved (but
+# converted to $host format) on output.
+#
+# All path conversion functions are named using the following convention:
+# file name conversion function : func_convert_file_X_to_Y ()
+# path conversion function : func_convert_path_X_to_Y ()
+# where, for any given $build/$host combination the 'X_to_Y' value is the
+# same. If conversion functions are added for new $build/$host combinations,
+# the two new functions must follow this pattern, or func_init_to_host_path_cmd
+# will break.
+
+
+# func_init_to_host_path_cmd
+# Ensures that function "pointer" variable $to_host_path_cmd is set to the
+# appropriate value, based on the value of $to_host_file_cmd.
+to_host_path_cmd=
+func_init_to_host_path_cmd ()
+{
+ $debug_cmd
+
+ if test -z "$to_host_path_cmd"; then
+ func_stripname 'func_convert_file_' '' "$to_host_file_cmd"
+ to_host_path_cmd=func_convert_path_$func_stripname_result
+ fi
+}
+
+
+# func_to_host_path ARG
+# Converts the path ARG from $build format to $host format. Return result
+# in func_to_host_path_result.
+func_to_host_path ()
+{
+ $debug_cmd
+
+ func_init_to_host_path_cmd
+ $to_host_path_cmd "$1"
+}
+# end func_to_host_path
+
+
+# func_convert_path_noop ARG
+# Copy ARG to func_to_host_path_result.
+func_convert_path_noop ()
+{
+ func_to_host_path_result=$1
+}
+# end func_convert_path_noop
+
+
+# func_convert_path_msys_to_w32 ARG
+# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic
+# conversion to w32 is not available inside the cwrapper. Returns result in
+# func_to_host_path_result.
+func_convert_path_msys_to_w32 ()
+{
+ $debug_cmd
+
+ func_to_host_path_result=$1
+ if test -n "$1"; then
+ # Remove leading and trailing path separator characters from ARG. MSYS
+ # behavior is inconsistent here; cygpath turns them into '.;' and ';.';
+ # and winepath ignores them completely.
+ func_stripname : : "$1"
+ func_to_host_path_tmp1=$func_stripname_result
+ func_convert_core_msys_to_w32 "$func_to_host_path_tmp1"
+ func_to_host_path_result=$func_convert_core_msys_to_w32_result
+ func_convert_path_check : ";" \
+ "$func_to_host_path_tmp1" "$func_to_host_path_result"
+ func_convert_path_front_back_pathsep ":*" "*:" ";" "$1"
+ fi
+}
+# end func_convert_path_msys_to_w32
+
+
+# func_convert_path_cygwin_to_w32 ARG
+# Convert path ARG from Cygwin to w32 format. Returns result in
+# func_to_host_file_result.
+func_convert_path_cygwin_to_w32 ()
+{
+ $debug_cmd
+
+ func_to_host_path_result=$1
+ if test -n "$1"; then
+ # See func_convert_path_msys_to_w32:
+ func_stripname : : "$1"
+ func_to_host_path_tmp1=$func_stripname_result
+ func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"`
+ func_convert_path_check : ";" \
+ "$func_to_host_path_tmp1" "$func_to_host_path_result"
+ func_convert_path_front_back_pathsep ":*" "*:" ";" "$1"
+ fi
+}
+# end func_convert_path_cygwin_to_w32
+
+
+# func_convert_path_nix_to_w32 ARG
+# Convert path ARG from *nix to w32 format. Requires a wine environment and
+# a working winepath. Returns result in func_to_host_file_result.
+func_convert_path_nix_to_w32 ()
+{
+ $debug_cmd
+
+ func_to_host_path_result=$1
+ if test -n "$1"; then
+ # See func_convert_path_msys_to_w32:
+ func_stripname : : "$1"
+ func_to_host_path_tmp1=$func_stripname_result
+ func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1"
+ func_to_host_path_result=$func_convert_core_path_wine_to_w32_result
+ func_convert_path_check : ";" \
+ "$func_to_host_path_tmp1" "$func_to_host_path_result"
+ func_convert_path_front_back_pathsep ":*" "*:" ";" "$1"
+ fi
+}
+# end func_convert_path_nix_to_w32
+
+
+# func_convert_path_msys_to_cygwin ARG
+# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set.
+# Returns result in func_to_host_file_result.
+func_convert_path_msys_to_cygwin ()
+{
+ $debug_cmd
+
+ func_to_host_path_result=$1
+ if test -n "$1"; then
+ # See func_convert_path_msys_to_w32:
+ func_stripname : : "$1"
+ func_to_host_path_tmp1=$func_stripname_result
+ func_convert_core_msys_to_w32 "$func_to_host_path_tmp1"
+ func_cygpath -u -p "$func_convert_core_msys_to_w32_result"
+ func_to_host_path_result=$func_cygpath_result
+ func_convert_path_check : : \
+ "$func_to_host_path_tmp1" "$func_to_host_path_result"
+ func_convert_path_front_back_pathsep ":*" "*:" : "$1"
+ fi
+}
+# end func_convert_path_msys_to_cygwin
+
+
+# func_convert_path_nix_to_cygwin ARG
+# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a
+# a wine environment, working winepath, and LT_CYGPATH set. Returns result in
+# func_to_host_file_result.
+func_convert_path_nix_to_cygwin ()
+{
+ $debug_cmd
+
+ func_to_host_path_result=$1
+ if test -n "$1"; then
+ # Remove leading and trailing path separator characters from
+ # ARG. msys behavior is inconsistent here, cygpath turns them
+ # into '.;' and ';.', and winepath ignores them completely.
+ func_stripname : : "$1"
+ func_to_host_path_tmp1=$func_stripname_result
+ func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1"
+ func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result"
+ func_to_host_path_result=$func_cygpath_result
+ func_convert_path_check : : \
+ "$func_to_host_path_tmp1" "$func_to_host_path_result"
+ func_convert_path_front_back_pathsep ":*" "*:" : "$1"
+ fi
+}
+# end func_convert_path_nix_to_cygwin
+
+
+# func_dll_def_p FILE
+# True iff FILE is a Windows DLL '.def' file.
+# Keep in sync with _LT_DLL_DEF_P in libtool.m4
+func_dll_def_p ()
+{
+ $debug_cmd
+
+ func_dll_def_p_tmp=`$SED -n \
+ -e 's/^[ ]*//' \
+ -e '/^\(;.*\)*$/d' \
+ -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \
+ -e q \
+ "$1"`
+ test DEF = "$func_dll_def_p_tmp"
+}
+
+
+# func_mode_compile arg...
+func_mode_compile ()
+{
+ $debug_cmd
+
+ # Get the compilation command and the source file.
+ base_compile=
+ srcfile=$nonopt # always keep a non-empty value in "srcfile"
+ suppress_opt=yes
+ suppress_output=
+ arg_mode=normal
+ libobj=
+ later=
+ pie_flag=
+
+ for arg
+ do
+ case $arg_mode in
+ arg )
+ # do not "continue". Instead, add this to base_compile
+ lastarg=$arg
+ arg_mode=normal
+ ;;
+
+ target )
+ libobj=$arg
+ arg_mode=normal
+ continue
+ ;;
+
+ normal )
+ # Accept any command-line options.
+ case $arg in
+ -o)
+ test -n "$libobj" && \
+ func_fatal_error "you cannot specify '-o' more than once"
+ arg_mode=target
+ continue
+ ;;
+
+ -pie | -fpie | -fPIE)
+ func_append pie_flag " $arg"
+ continue
+ ;;
+
+ -shared | -static | -prefer-pic | -prefer-non-pic)
+ func_append later " $arg"
+ continue
+ ;;
+
+ -no-suppress)
+ suppress_opt=no
+ continue
+ ;;
+
+ -Xcompiler)
+ arg_mode=arg # the next one goes into the "base_compile" arg list
+ continue # The current "srcfile" will either be retained or
+ ;; # replaced later. I would guess that would be a bug.
+
+ -Wc,*)
+ func_stripname '-Wc,' '' "$arg"
+ args=$func_stripname_result
+ lastarg=
+ save_ifs=$IFS; IFS=,
+ for arg in $args; do
+ IFS=$save_ifs
+ func_append_quoted lastarg "$arg"
+ done
+ IFS=$save_ifs
+ func_stripname ' ' '' "$lastarg"
+ lastarg=$func_stripname_result
+
+ # Add the arguments to base_compile.
+ func_append base_compile " $lastarg"
+ continue
+ ;;
+
+ *)
+ # Accept the current argument as the source file.
+ # The previous "srcfile" becomes the current argument.
+ #
+ lastarg=$srcfile
+ srcfile=$arg
+ ;;
+ esac # case $arg
+ ;;
+ esac # case $arg_mode
+
+ # Aesthetically quote the previous argument.
+ func_append_quoted base_compile "$lastarg"
+ done # for arg
+
+ case $arg_mode in
+ arg)
+ func_fatal_error "you must specify an argument for -Xcompile"
+ ;;
+ target)
+ func_fatal_error "you must specify a target with '-o'"
+ ;;
+ *)
+ # Get the name of the library object.
+ test -z "$libobj" && {
+ func_basename "$srcfile"
+ libobj=$func_basename_result
+ }
+ ;;
+ esac
+
+ # Recognize several different file suffixes.
+ # If the user specifies -o file.o, it is replaced with file.lo
+ case $libobj in
+ *.[cCFSifmso] | \
+ *.ada | *.adb | *.ads | *.asm | \
+ *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \
+ *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup)
+ func_xform "$libobj"
+ libobj=$func_xform_result
+ ;;
+ esac
+
+ case $libobj in
+ *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;;
+ *)
+ func_fatal_error "cannot determine name of library object from '$libobj'"
+ ;;
+ esac
+
+ func_infer_tag $base_compile
+
+ for arg in $later; do
+ case $arg in
+ -shared)
+ test yes = "$build_libtool_libs" \
+ || func_fatal_configuration "cannot build a shared library"
+ build_old_libs=no
+ continue
+ ;;
+
+ -static)
+ build_libtool_libs=no
+ build_old_libs=yes
+ continue
+ ;;
+
+ -prefer-pic)
+ pic_mode=yes
+ continue
+ ;;
+
+ -prefer-non-pic)
+ pic_mode=no
+ continue
+ ;;
+ esac
+ done
+
+ func_quote_for_eval "$libobj"
+ test "X$libobj" != "X$func_quote_for_eval_result" \
+ && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \
+ && func_warning "libobj name '$libobj' may not contain shell special characters."
+ func_dirname_and_basename "$obj" "/" ""
+ objname=$func_basename_result
+ xdir=$func_dirname_result
+ lobj=$xdir$objdir/$objname
+
+ test -z "$base_compile" && \
+ func_fatal_help "you must specify a compilation command"
+
+ # Delete any leftover library objects.
+ if test yes = "$build_old_libs"; then
+ removelist="$obj $lobj $libobj ${libobj}T"
+ else
+ removelist="$lobj $libobj ${libobj}T"
+ fi
+
+ # On Cygwin there's no "real" PIC flag so we must build both object types
+ case $host_os in
+ cygwin* | mingw* | pw32* | os2* | cegcc*)
+ pic_mode=default
+ ;;
+ esac
+ if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then
+ # non-PIC code in shared libraries is not supported
+ pic_mode=default
+ fi
+
+ # Calculate the filename of the output object if compiler does
+ # not support -o with -c
+ if test no = "$compiler_c_o"; then
+ output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext
+ lockfile=$output_obj.lock
+ else
+ output_obj=
+ need_locks=no
+ lockfile=
+ fi
+
+ # Lock this critical section if it is needed
+ # We use this script file to make the link, it avoids creating a new file
+ if test yes = "$need_locks"; then
+ until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do
+ func_echo "Waiting for $lockfile to be removed"
+ sleep 2
+ done
+ elif test warn = "$need_locks"; then
+ if test -f "$lockfile"; then
+ $ECHO "\
+*** ERROR, $lockfile exists and contains:
+`cat $lockfile 2>/dev/null`
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support '-c' and '-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $opt_dry_run || $RM $removelist
+ exit $EXIT_FAILURE
+ fi
+ func_append removelist " $output_obj"
+ $ECHO "$srcfile" > "$lockfile"
+ fi
+
+ $opt_dry_run || $RM $removelist
+ func_append removelist " $lockfile"
+ trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15
+
+ func_to_tool_file "$srcfile" func_convert_file_msys_to_w32
+ srcfile=$func_to_tool_file_result
+ func_quote_for_eval "$srcfile"
+ qsrcfile=$func_quote_for_eval_result
+
+ # Only build a PIC object if we are building libtool libraries.
+ if test yes = "$build_libtool_libs"; then
+ # Without this assignment, base_compile gets emptied.
+ fbsd_hideous_sh_bug=$base_compile
+
+ if test no != "$pic_mode"; then
+ command="$base_compile $qsrcfile $pic_flag"
+ else
+ # Don't build PIC code
+ command="$base_compile $qsrcfile"
+ fi
+
+ func_mkdir_p "$xdir$objdir"
+
+ if test -z "$output_obj"; then
+ # Place PIC objects in $objdir
+ func_append command " -o $lobj"
+ fi
+
+ func_show_eval_locale "$command" \
+ 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE'
+
+ if test warn = "$need_locks" &&
+ test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+ $ECHO "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support '-c' and '-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $opt_dry_run || $RM $removelist
+ exit $EXIT_FAILURE
+ fi
+
+ # Just move the object if needed, then go on to compile the next one
+ if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then
+ func_show_eval '$MV "$output_obj" "$lobj"' \
+ 'error=$?; $opt_dry_run || $RM $removelist; exit $error'
+ fi
+
+ # Allow error messages only from the first compilation.
+ if test yes = "$suppress_opt"; then
+ suppress_output=' >/dev/null 2>&1'
+ fi
+ fi
+
+ # Only build a position-dependent object if we build old libraries.
+ if test yes = "$build_old_libs"; then
+ if test yes != "$pic_mode"; then
+ # Don't build PIC code
+ command="$base_compile $qsrcfile$pie_flag"
+ else
+ command="$base_compile $qsrcfile $pic_flag"
+ fi
+ if test yes = "$compiler_c_o"; then
+ func_append command " -o $obj"
+ fi
+
+ # Suppress compiler output if we already did a PIC compilation.
+ func_append command "$suppress_output"
+ func_show_eval_locale "$command" \
+ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE'
+
+ if test warn = "$need_locks" &&
+ test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then
+ $ECHO "\
+*** ERROR, $lockfile contains:
+`cat $lockfile 2>/dev/null`
+
+but it should contain:
+$srcfile
+
+This indicates that another process is trying to use the same
+temporary object file, and libtool could not work around it because
+your compiler does not support '-c' and '-o' together. If you
+repeat this compilation, it may succeed, by chance, but you had better
+avoid parallel builds (make -j) in this platform, or get a better
+compiler."
+
+ $opt_dry_run || $RM $removelist
+ exit $EXIT_FAILURE
+ fi
+
+ # Just move the object if needed
+ if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then
+ func_show_eval '$MV "$output_obj" "$obj"' \
+ 'error=$?; $opt_dry_run || $RM $removelist; exit $error'
+ fi
+ fi
+
+ $opt_dry_run || {
+ func_write_libtool_object "$libobj" "$objdir/$objname" "$objname"
+
+ # Unlock the critical section if it was locked
+ if test no != "$need_locks"; then
+ removelist=$lockfile
+ $RM "$lockfile"
+ fi
+ }
+
+ exit $EXIT_SUCCESS
+}
+
+$opt_help || {
+ test compile = "$opt_mode" && func_mode_compile ${1+"$@"}
+}
+
+func_mode_help ()
+{
+ # We need to display help for each of the modes.
+ case $opt_mode in
+ "")
+ # Generic help is extracted from the usage comments
+ # at the start of this file.
+ func_help
+ ;;
+
+ clean)
+ $ECHO \
+"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE...
+
+Remove files from the build directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed
+to RM.
+
+If FILE is a libtool library, object or program, all the files associated
+with it are deleted. Otherwise, only FILE itself is deleted using RM."
+ ;;
+
+ compile)
+ $ECHO \
+"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE
+
+Compile a source file into a libtool library object.
+
+This mode accepts the following additional options:
+
+ -o OUTPUT-FILE set the output file name to OUTPUT-FILE
+ -no-suppress do not suppress compiler output for multiple passes
+ -prefer-pic try to build PIC objects only
+ -prefer-non-pic try to build non-PIC objects only
+ -shared do not build a '.o' file suitable for static linking
+ -static only build a '.o' file suitable for static linking
+ -Wc,FLAG pass FLAG directly to the compiler
+
+COMPILE-COMMAND is a command to be used in creating a 'standard' object file
+from the given SOURCEFILE.
+
+The output file name is determined by removing the directory component from
+SOURCEFILE, then substituting the C source code suffix '.c' with the
+library object suffix, '.lo'."
+ ;;
+
+ execute)
+ $ECHO \
+"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]...
+
+Automatically set library path, then run a program.
+
+This mode accepts the following additional options:
+
+ -dlopen FILE add the directory containing FILE to the library path
+
+This mode sets the library path environment variable according to '-dlopen'
+flags.
+
+If any of the ARGS are libtool executable wrappers, then they are translated
+into their corresponding uninstalled binary, and any of their required library
+directories are added to the library path.
+
+Then, COMMAND is executed, with ARGS as arguments."
+ ;;
+
+ finish)
+ $ECHO \
+"Usage: $progname [OPTION]... --mode=finish [LIBDIR]...
+
+Complete the installation of libtool libraries.
+
+Each LIBDIR is a directory that contains libtool libraries.
+
+The commands that this mode executes may require superuser privileges. Use
+the '--dry-run' option if you just want to see what would be executed."
+ ;;
+
+ install)
+ $ECHO \
+"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND...
+
+Install executables or libraries.
+
+INSTALL-COMMAND is the installation command. The first component should be
+either the 'install' or 'cp' program.
+
+The following components of INSTALL-COMMAND are treated specially:
+
+ -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation
+
+The rest of the components are interpreted as arguments to that command (only
+BSD-compatible install options are recognized)."
+ ;;
+
+ link)
+ $ECHO \
+"Usage: $progname [OPTION]... --mode=link LINK-COMMAND...
+
+Link object files or libraries together to form another library, or to
+create an executable program.
+
+LINK-COMMAND is a command using the C compiler that you would use to create
+a program from several object files.
+
+The following components of LINK-COMMAND are treated specially:
+
+ -all-static do not do any dynamic linking at all
+ -avoid-version do not add a version suffix if possible
+ -bindir BINDIR specify path to binaries directory (for systems where
+ libraries must be found in the PATH setting at runtime)
+ -dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime
+ -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols
+ -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
+ -export-symbols SYMFILE
+ try to export only the symbols listed in SYMFILE
+ -export-symbols-regex REGEX
+ try to export only the symbols matching REGEX
+ -LLIBDIR search LIBDIR for required installed libraries
+ -lNAME OUTPUT-FILE requires the installed library libNAME
+ -module build a library that can dlopened
+ -no-fast-install disable the fast-install mode
+ -no-install link a not-installable executable
+ -no-undefined declare that a library does not refer to external symbols
+ -o OUTPUT-FILE create OUTPUT-FILE from the specified objects
+ -objectlist FILE use a list of object files found in FILE to specify objects
+ -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes)
+ -precious-files-regex REGEX
+ don't remove output files matching REGEX
+ -release RELEASE specify package release information
+ -rpath LIBDIR the created library will eventually be installed in LIBDIR
+ -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries
+ -shared only do dynamic linking of libtool libraries
+ -shrext SUFFIX override the standard shared library file extension
+ -static do not do any dynamic linking of uninstalled libtool libraries
+ -static-libtool-libs
+ do not do any dynamic linking of libtool libraries
+ -version-info CURRENT[:REVISION[:AGE]]
+ specify library version info [each variable defaults to 0]
+ -weak LIBNAME declare that the target provides the LIBNAME interface
+ -Wc,FLAG
+ -Xcompiler FLAG pass linker-specific FLAG directly to the compiler
+ -Wl,FLAG
+ -Xlinker FLAG pass linker-specific FLAG directly to the linker
+ -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC)
+
+All other options (arguments beginning with '-') are ignored.
+
+Every other argument is treated as a filename. Files ending in '.la' are
+treated as uninstalled libtool libraries, other files are standard or library
+object files.
+
+If the OUTPUT-FILE ends in '.la', then a libtool library is created,
+only library objects ('.lo' files) may be specified, and '-rpath' is
+required, except when creating a convenience library.
+
+If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created
+using 'ar' and 'ranlib', or on Windows using 'lib'.
+
+If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file
+is created, otherwise an executable program is created."
+ ;;
+
+ uninstall)
+ $ECHO \
+"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE...
+
+Remove libraries from an installation directory.
+
+RM is the name of the program to use to delete files associated with each FILE
+(typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed
+to RM.
+
+If FILE is a libtool library, all the files associated with it are deleted.
+Otherwise, only FILE itself is deleted using RM."
+ ;;
+
+ *)
+ func_fatal_help "invalid operation mode '$opt_mode'"
+ ;;
+ esac
+
+ echo
+ $ECHO "Try '$progname --help' for more information about other modes."
+}
+
+# Now that we've collected a possible --mode arg, show help if necessary
+if $opt_help; then
+ if test : = "$opt_help"; then
+ func_mode_help
+ else
+ {
+ func_help noexit
+ for opt_mode in compile link execute install finish uninstall clean; do
+ func_mode_help
+ done
+ } | $SED -n '1p; 2,$s/^Usage:/ or: /p'
+ {
+ func_help noexit
+ for opt_mode in compile link execute install finish uninstall clean; do
+ echo
+ func_mode_help
+ done
+ } |
+ $SED '1d
+ /^When reporting/,/^Report/{
+ H
+ d
+ }
+ $x
+ /information about other modes/d
+ /more detailed .*MODE/d
+ s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/'
+ fi
+ exit $?
+fi
+
+
+# func_mode_execute arg...
+func_mode_execute ()
+{
+ $debug_cmd
+
+ # The first argument is the command name.
+ cmd=$nonopt
+ test -z "$cmd" && \
+ func_fatal_help "you must specify a COMMAND"
+
+ # Handle -dlopen flags immediately.
+ for file in $opt_dlopen; do
+ test -f "$file" \
+ || func_fatal_help "'$file' is not a file"
+
+ dir=
+ case $file in
+ *.la)
+ func_resolve_sysroot "$file"
+ file=$func_resolve_sysroot_result
+
+ # Check to see that this really is a libtool archive.
+ func_lalib_unsafe_p "$file" \
+ || func_fatal_help "'$lib' is not a valid libtool archive"
+
+ # Read the libtool library.
+ dlname=
+ library_names=
+ func_source "$file"
+
+ # Skip this library if it cannot be dlopened.
+ if test -z "$dlname"; then
+ # Warn if it was a shared library.
+ test -n "$library_names" && \
+ func_warning "'$file' was not linked with '-export-dynamic'"
+ continue
+ fi
+
+ func_dirname "$file" "" "."
+ dir=$func_dirname_result
+
+ if test -f "$dir/$objdir/$dlname"; then
+ func_append dir "/$objdir"
+ else
+ if test ! -f "$dir/$dlname"; then
+ func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'"
+ fi
+ fi
+ ;;
+
+ *.lo)
+ # Just add the directory containing the .lo file.
+ func_dirname "$file" "" "."
+ dir=$func_dirname_result
+ ;;
+
+ *)
+ func_warning "'-dlopen' is ignored for non-libtool libraries and objects"
+ continue
+ ;;
+ esac
+
+ # Get the absolute pathname.
+ absdir=`cd "$dir" && pwd`
+ test -n "$absdir" && dir=$absdir
+
+ # Now add the directory to shlibpath_var.
+ if eval "test -z \"\$$shlibpath_var\""; then
+ eval "$shlibpath_var=\"\$dir\""
+ else
+ eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\""
+ fi
+ done
+
+ # This variable tells wrapper scripts just to set shlibpath_var
+ # rather than running their programs.
+ libtool_execute_magic=$magic
+
+ # Check if any of the arguments is a wrapper script.
+ args=
+ for file
+ do
+ case $file in
+ -* | *.la | *.lo ) ;;
+ *)
+ # Do a test to see if this is really a libtool program.
+ if func_ltwrapper_script_p "$file"; then
+ func_source "$file"
+ # Transform arg to wrapped name.
+ file=$progdir/$program
+ elif func_ltwrapper_executable_p "$file"; then
+ func_ltwrapper_scriptname "$file"
+ func_source "$func_ltwrapper_scriptname_result"
+ # Transform arg to wrapped name.
+ file=$progdir/$program
+ fi
+ ;;
+ esac
+ # Quote arguments (to preserve shell metacharacters).
+ func_append_quoted args "$file"
+ done
+
+ if $opt_dry_run; then
+ # Display what would be done.
+ if test -n "$shlibpath_var"; then
+ eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\""
+ echo "export $shlibpath_var"
+ fi
+ $ECHO "$cmd$args"
+ exit $EXIT_SUCCESS
+ else
+ if test -n "$shlibpath_var"; then
+ # Export the shlibpath_var.
+ eval "export $shlibpath_var"
+ fi
+
+ # Restore saved environment variables
+ for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+ do
+ eval "if test \"\${save_$lt_var+set}\" = set; then
+ $lt_var=\$save_$lt_var; export $lt_var
+ else
+ $lt_unset $lt_var
+ fi"
+ done
+
+ # Now prepare to actually exec the command.
+ exec_cmd=\$cmd$args
+ fi
+}
+
+test execute = "$opt_mode" && func_mode_execute ${1+"$@"}
+
+
+# func_mode_finish arg...
+func_mode_finish ()
+{
+ $debug_cmd
+
+ libs=
+ libdirs=
+ admincmds=
+
+ for opt in "$nonopt" ${1+"$@"}
+ do
+ if test -d "$opt"; then
+ func_append libdirs " $opt"
+
+ elif test -f "$opt"; then
+ if func_lalib_unsafe_p "$opt"; then
+ func_append libs " $opt"
+ else
+ func_warning "'$opt' is not a valid libtool archive"
+ fi
+
+ else
+ func_fatal_error "invalid argument '$opt'"
+ fi
+ done
+
+ if test -n "$libs"; then
+ if test -n "$lt_sysroot"; then
+ sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"`
+ sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;"
+ else
+ sysroot_cmd=
+ fi
+
+ # Remove sysroot references
+ if $opt_dry_run; then
+ for lib in $libs; do
+ echo "removing references to $lt_sysroot and '=' prefixes from $lib"
+ done
+ else
+ tmpdir=`func_mktempdir`
+ for lib in $libs; do
+ $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \
+ > $tmpdir/tmp-la
+ mv -f $tmpdir/tmp-la $lib
+ done
+ ${RM}r "$tmpdir"
+ fi
+ fi
+
+ if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+ for libdir in $libdirs; do
+ if test -n "$finish_cmds"; then
+ # Do each command in the finish commands.
+ func_execute_cmds "$finish_cmds" 'admincmds="$admincmds
+'"$cmd"'"'
+ fi
+ if test -n "$finish_eval"; then
+ # Do the single finish_eval.
+ eval cmds=\"$finish_eval\"
+ $opt_dry_run || eval "$cmds" || func_append admincmds "
+ $cmds"
+ fi
+ done
+ fi
+
+ # Exit here if they wanted silent mode.
+ $opt_quiet && exit $EXIT_SUCCESS
+
+ if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then
+ echo "----------------------------------------------------------------------"
+ echo "Libraries have been installed in:"
+ for libdir in $libdirs; do
+ $ECHO " $libdir"
+ done
+ echo
+ echo "If you ever happen to want to link against installed libraries"
+ echo "in a given directory, LIBDIR, you must either use libtool, and"
+ echo "specify the full pathname of the library, or use the '-LLIBDIR'"
+ echo "flag during linking and do at least one of the following:"
+ if test -n "$shlibpath_var"; then
+ echo " - add LIBDIR to the '$shlibpath_var' environment variable"
+ echo " during execution"
+ fi
+ if test -n "$runpath_var"; then
+ echo " - add LIBDIR to the '$runpath_var' environment variable"
+ echo " during linking"
+ fi
+ if test -n "$hardcode_libdir_flag_spec"; then
+ libdir=LIBDIR
+ eval flag=\"$hardcode_libdir_flag_spec\"
+
+ $ECHO " - use the '$flag' linker flag"
+ fi
+ if test -n "$admincmds"; then
+ $ECHO " - have your system administrator run these commands:$admincmds"
+ fi
+ if test -f /etc/ld.so.conf; then
+ echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'"
+ fi
+ echo
+
+ echo "See any operating system documentation about shared libraries for"
+ case $host in
+ solaris2.[6789]|solaris2.1[0-9])
+ echo "more information, such as the ld(1), crle(1) and ld.so(8) manual"
+ echo "pages."
+ ;;
+ *)
+ echo "more information, such as the ld(1) and ld.so(8) manual pages."
+ ;;
+ esac
+ echo "----------------------------------------------------------------------"
+ fi
+ exit $EXIT_SUCCESS
+}
+
+test finish = "$opt_mode" && func_mode_finish ${1+"$@"}
+
+
+# func_mode_install arg...
+func_mode_install ()
+{
+ $debug_cmd
+
+ # There may be an optional sh(1) argument at the beginning of
+ # install_prog (especially on Windows NT).
+ if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" ||
+ # Allow the use of GNU shtool's install command.
+ case $nonopt in *shtool*) :;; *) false;; esac
+ then
+ # Aesthetically quote it.
+ func_quote_for_eval "$nonopt"
+ install_prog="$func_quote_for_eval_result "
+ arg=$1
+ shift
+ else
+ install_prog=
+ arg=$nonopt
+ fi
+
+ # The real first argument should be the name of the installation program.
+ # Aesthetically quote it.
+ func_quote_for_eval "$arg"
+ func_append install_prog "$func_quote_for_eval_result"
+ install_shared_prog=$install_prog
+ case " $install_prog " in
+ *[\\\ /]cp\ *) install_cp=: ;;
+ *) install_cp=false ;;
+ esac
+
+ # We need to accept at least all the BSD install flags.
+ dest=
+ files=
+ opts=
+ prev=
+ install_type=
+ isdir=false
+ stripme=
+ no_mode=:
+ for arg
+ do
+ arg2=
+ if test -n "$dest"; then
+ func_append files " $dest"
+ dest=$arg
+ continue
+ fi
+
+ case $arg in
+ -d) isdir=: ;;
+ -f)
+ if $install_cp; then :; else
+ prev=$arg
+ fi
+ ;;
+ -g | -m | -o)
+ prev=$arg
+ ;;
+ -s)
+ stripme=" -s"
+ continue
+ ;;
+ -*)
+ ;;
+ *)
+ # If the previous option needed an argument, then skip it.
+ if test -n "$prev"; then
+ if test X-m = "X$prev" && test -n "$install_override_mode"; then
+ arg2=$install_override_mode
+ no_mode=false
+ fi
+ prev=
+ else
+ dest=$arg
+ continue
+ fi
+ ;;
+ esac
+
+ # Aesthetically quote the argument.
+ func_quote_for_eval "$arg"
+ func_append install_prog " $func_quote_for_eval_result"
+ if test -n "$arg2"; then
+ func_quote_for_eval "$arg2"
+ fi
+ func_append install_shared_prog " $func_quote_for_eval_result"
+ done
+
+ test -z "$install_prog" && \
+ func_fatal_help "you must specify an install program"
+
+ test -n "$prev" && \
+ func_fatal_help "the '$prev' option requires an argument"
+
+ if test -n "$install_override_mode" && $no_mode; then
+ if $install_cp; then :; else
+ func_quote_for_eval "$install_override_mode"
+ func_append install_shared_prog " -m $func_quote_for_eval_result"
+ fi
+ fi
+
+ if test -z "$files"; then
+ if test -z "$dest"; then
+ func_fatal_help "no file or destination specified"
+ else
+ func_fatal_help "you must specify a destination"
+ fi
+ fi
+
+ # Strip any trailing slash from the destination.
+ func_stripname '' '/' "$dest"
+ dest=$func_stripname_result
+
+ # Check to see that the destination is a directory.
+ test -d "$dest" && isdir=:
+ if $isdir; then
+ destdir=$dest
+ destname=
+ else
+ func_dirname_and_basename "$dest" "" "."
+ destdir=$func_dirname_result
+ destname=$func_basename_result
+
+ # Not a directory, so check to see that there is only one file specified.
+ set dummy $files; shift
+ test "$#" -gt 1 && \
+ func_fatal_help "'$dest' is not a directory"
+ fi
+ case $destdir in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ for file in $files; do
+ case $file in
+ *.lo) ;;
+ *)
+ func_fatal_help "'$destdir' must be an absolute directory name"
+ ;;
+ esac
+ done
+ ;;
+ esac
+
+ # This variable tells wrapper scripts just to set variables rather
+ # than running their programs.
+ libtool_install_magic=$magic
+
+ staticlibs=
+ future_libdirs=
+ current_libdirs=
+ for file in $files; do
+
+ # Do each installation.
+ case $file in
+ *.$libext)
+ # Do the static libraries later.
+ func_append staticlibs " $file"
+ ;;
+
+ *.la)
+ func_resolve_sysroot "$file"
+ file=$func_resolve_sysroot_result
+
+ # Check to see that this really is a libtool archive.
+ func_lalib_unsafe_p "$file" \
+ || func_fatal_help "'$file' is not a valid libtool archive"
+
+ library_names=
+ old_library=
+ relink_command=
+ func_source "$file"
+
+ # Add the libdir to current_libdirs if it is the destination.
+ if test "X$destdir" = "X$libdir"; then
+ case "$current_libdirs " in
+ *" $libdir "*) ;;
+ *) func_append current_libdirs " $libdir" ;;
+ esac
+ else
+ # Note the libdir as a future libdir.
+ case "$future_libdirs " in
+ *" $libdir "*) ;;
+ *) func_append future_libdirs " $libdir" ;;
+ esac
+ fi
+
+ func_dirname "$file" "/" ""
+ dir=$func_dirname_result
+ func_append dir "$objdir"
+
+ if test -n "$relink_command"; then
+ # Determine the prefix the user has applied to our future dir.
+ inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"`
+
+ # Don't allow the user to place us outside of our expected
+ # location b/c this prevents finding dependent libraries that
+ # are installed to the same prefix.
+ # At present, this check doesn't affect windows .dll's that
+ # are installed into $libdir/../bin (currently, that works fine)
+ # but it's something to keep an eye on.
+ test "$inst_prefix_dir" = "$destdir" && \
+ func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir"
+
+ if test -n "$inst_prefix_dir"; then
+ # Stick the inst_prefix_dir data into the link command.
+ relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
+ else
+ relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"`
+ fi
+
+ func_warning "relinking '$file'"
+ func_show_eval "$relink_command" \
+ 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"'
+ fi
+
+ # See the names of the shared library.
+ set dummy $library_names; shift
+ if test -n "$1"; then
+ realname=$1
+ shift
+
+ srcname=$realname
+ test -n "$relink_command" && srcname=${realname}T
+
+ # Install the shared library and build the symlinks.
+ func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \
+ 'exit $?'
+ tstripme=$stripme
+ case $host_os in
+ cygwin* | mingw* | pw32* | cegcc*)
+ case $realname in
+ *.dll.a)
+ tstripme=
+ ;;
+ esac
+ ;;
+ os2*)
+ case $realname in
+ *_dll.a)
+ tstripme=
+ ;;
+ esac
+ ;;
+ esac
+ if test -n "$tstripme" && test -n "$striplib"; then
+ func_show_eval "$striplib $destdir/$realname" 'exit $?'
+ fi
+
+ if test "$#" -gt 0; then
+ # Delete the old symlinks, and create new ones.
+ # Try 'ln -sf' first, because the 'ln' binary might depend on
+ # the symlink we replace! Solaris /bin/ln does not understand -f,
+ # so we also need to try rm && ln -s.
+ for linkname
+ do
+ test "$linkname" != "$realname" \
+ && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })"
+ done
+ fi
+
+ # Do each command in the postinstall commands.
+ lib=$destdir/$realname
+ func_execute_cmds "$postinstall_cmds" 'exit $?'
+ fi
+
+ # Install the pseudo-library for information purposes.
+ func_basename "$file"
+ name=$func_basename_result
+ instname=$dir/${name}i
+ func_show_eval "$install_prog $instname $destdir/$name" 'exit $?'
+
+ # Maybe install the static library, too.
+ test -n "$old_library" && func_append staticlibs " $dir/$old_library"
+ ;;
+
+ *.lo)
+ # Install (i.e. copy) a libtool object.
+
+ # Figure out destination file name, if it wasn't already specified.
+ if test -n "$destname"; then
+ destfile=$destdir/$destname
+ else
+ func_basename "$file"
+ destfile=$func_basename_result
+ destfile=$destdir/$destfile
+ fi
+
+ # Deduce the name of the destination old-style object file.
+ case $destfile in
+ *.lo)
+ func_lo2o "$destfile"
+ staticdest=$func_lo2o_result
+ ;;
+ *.$objext)
+ staticdest=$destfile
+ destfile=
+ ;;
+ *)
+ func_fatal_help "cannot copy a libtool object to '$destfile'"
+ ;;
+ esac
+
+ # Install the libtool object if requested.
+ test -n "$destfile" && \
+ func_show_eval "$install_prog $file $destfile" 'exit $?'
+
+ # Install the old object if enabled.
+ if test yes = "$build_old_libs"; then
+ # Deduce the name of the old-style object file.
+ func_lo2o "$file"
+ staticobj=$func_lo2o_result
+ func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?'
+ fi
+ exit $EXIT_SUCCESS
+ ;;
+
+ *)
+ # Figure out destination file name, if it wasn't already specified.
+ if test -n "$destname"; then
+ destfile=$destdir/$destname
+ else
+ func_basename "$file"
+ destfile=$func_basename_result
+ destfile=$destdir/$destfile
+ fi
+
+ # If the file is missing, and there is a .exe on the end, strip it
+ # because it is most likely a libtool script we actually want to
+ # install
+ stripped_ext=
+ case $file in
+ *.exe)
+ if test ! -f "$file"; then
+ func_stripname '' '.exe' "$file"
+ file=$func_stripname_result
+ stripped_ext=.exe
+ fi
+ ;;
+ esac
+
+ # Do a test to see if this is really a libtool program.
+ case $host in
+ *cygwin* | *mingw*)
+ if func_ltwrapper_executable_p "$file"; then
+ func_ltwrapper_scriptname "$file"
+ wrapper=$func_ltwrapper_scriptname_result
+ else
+ func_stripname '' '.exe' "$file"
+ wrapper=$func_stripname_result
+ fi
+ ;;
+ *)
+ wrapper=$file
+ ;;
+ esac
+ if func_ltwrapper_script_p "$wrapper"; then
+ notinst_deplibs=
+ relink_command=
+
+ func_source "$wrapper"
+
+ # Check the variables that should have been set.
+ test -z "$generated_by_libtool_version" && \
+ func_fatal_error "invalid libtool wrapper script '$wrapper'"
+
+ finalize=:
+ for lib in $notinst_deplibs; do
+ # Check to see that each library is installed.
+ libdir=
+ if test -f "$lib"; then
+ func_source "$lib"
+ fi
+ libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'`
+ if test -n "$libdir" && test ! -f "$libfile"; then
+ func_warning "'$lib' has not been installed in '$libdir'"
+ finalize=false
+ fi
+ done
+
+ relink_command=
+ func_source "$wrapper"
+
+ outputname=
+ if test no = "$fast_install" && test -n "$relink_command"; then
+ $opt_dry_run || {
+ if $finalize; then
+ tmpdir=`func_mktempdir`
+ func_basename "$file$stripped_ext"
+ file=$func_basename_result
+ outputname=$tmpdir/$file
+ # Replace the output file specification.
+ relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'`
+
+ $opt_quiet || {
+ func_quote_for_expand "$relink_command"
+ eval "func_echo $func_quote_for_expand_result"
+ }
+ if eval "$relink_command"; then :
+ else
+ func_error "error: relink '$file' with the above command before installing it"
+ $opt_dry_run || ${RM}r "$tmpdir"
+ continue
+ fi
+ file=$outputname
+ else
+ func_warning "cannot relink '$file'"
+ fi
+ }
+ else
+ # Install the binary that we compiled earlier.
+ file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"`
+ fi
+ fi
+
+ # remove .exe since cygwin /usr/bin/install will append another
+ # one anyway
+ case $install_prog,$host in
+ */usr/bin/install*,*cygwin*)
+ case $file:$destfile in
+ *.exe:*.exe)
+ # this is ok
+ ;;
+ *.exe:*)
+ destfile=$destfile.exe
+ ;;
+ *:*.exe)
+ func_stripname '' '.exe' "$destfile"
+ destfile=$func_stripname_result
+ ;;
+ esac
+ ;;
+ esac
+ func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?'
+ $opt_dry_run || if test -n "$outputname"; then
+ ${RM}r "$tmpdir"
+ fi
+ ;;
+ esac
+ done
+
+ for file in $staticlibs; do
+ func_basename "$file"
+ name=$func_basename_result
+
+ # Set up the ranlib parameters.
+ oldlib=$destdir/$name
+ func_to_tool_file "$oldlib" func_convert_file_msys_to_w32
+ tool_oldlib=$func_to_tool_file_result
+
+ func_show_eval "$install_prog \$file \$oldlib" 'exit $?'
+
+ if test -n "$stripme" && test -n "$old_striplib"; then
+ func_show_eval "$old_striplib $tool_oldlib" 'exit $?'
+ fi
+
+ # Do each command in the postinstall commands.
+ func_execute_cmds "$old_postinstall_cmds" 'exit $?'
+ done
+
+ test -n "$future_libdirs" && \
+ func_warning "remember to run '$progname --finish$future_libdirs'"
+
+ if test -n "$current_libdirs"; then
+ # Maybe just do a dry run.
+ $opt_dry_run && current_libdirs=" -n$current_libdirs"
+ exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs'
+ else
+ exit $EXIT_SUCCESS
+ fi
+}
+
+test install = "$opt_mode" && func_mode_install ${1+"$@"}
+
+
+# func_generate_dlsyms outputname originator pic_p
+# Extract symbols from dlprefiles and create ${outputname}S.o with
+# a dlpreopen symbol table.
+func_generate_dlsyms ()
+{
+ $debug_cmd
+
+ my_outputname=$1
+ my_originator=$2
+ my_pic_p=${3-false}
+ my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'`
+ my_dlsyms=
+
+ if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then
+ if test -n "$NM" && test -n "$global_symbol_pipe"; then
+ my_dlsyms=${my_outputname}S.c
+ else
+ func_error "not configured to extract global symbols from dlpreopened files"
+ fi
+ fi
+
+ if test -n "$my_dlsyms"; then
+ case $my_dlsyms in
+ "") ;;
+ *.c)
+ # Discover the nlist of each of the dlfiles.
+ nlist=$output_objdir/$my_outputname.nm
+
+ func_show_eval "$RM $nlist ${nlist}S ${nlist}T"
+
+ # Parse the name list into a source file.
+ func_verbose "creating $output_objdir/$my_dlsyms"
+
+ $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\
+/* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */
+/* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */
+
+#ifdef __cplusplus
+extern \"C\" {
+#endif
+
+#if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4))
+#pragma GCC diagnostic ignored \"-Wstrict-prototypes\"
+#endif
+
+/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */
+#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE
+/* DATA imports from DLLs on WIN32 can't be const, because runtime
+ relocations are performed -- see ld's documentation on pseudo-relocs. */
+# define LT_DLSYM_CONST
+#elif defined __osf__
+/* This system does not cope well with relocations in const data. */
+# define LT_DLSYM_CONST
+#else
+# define LT_DLSYM_CONST const
+#endif
+
+#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0)
+
+/* External symbol declarations for the compiler. */\
+"
+
+ if test yes = "$dlself"; then
+ func_verbose "generating symbol list for '$output'"
+
+ $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist"
+
+ # Add our own program objects to the symbol list.
+ progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP`
+ for progfile in $progfiles; do
+ func_to_tool_file "$progfile" func_convert_file_msys_to_w32
+ func_verbose "extracting global C symbols from '$func_to_tool_file_result'"
+ $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'"
+ done
+
+ if test -n "$exclude_expsyms"; then
+ $opt_dry_run || {
+ eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T'
+ eval '$MV "$nlist"T "$nlist"'
+ }
+ fi
+
+ if test -n "$export_symbols_regex"; then
+ $opt_dry_run || {
+ eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T'
+ eval '$MV "$nlist"T "$nlist"'
+ }
+ fi
+
+ # Prepare the list of exported symbols
+ if test -z "$export_symbols"; then
+ export_symbols=$output_objdir/$outputname.exp
+ $opt_dry_run || {
+ $RM $export_symbols
+ eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
+ case $host in
+ *cygwin* | *mingw* | *cegcc* )
+ eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+ eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"'
+ ;;
+ esac
+ }
+ else
+ $opt_dry_run || {
+ eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"'
+ eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T'
+ eval '$MV "$nlist"T "$nlist"'
+ case $host in
+ *cygwin* | *mingw* | *cegcc* )
+ eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+ eval 'cat "$nlist" >> "$output_objdir/$outputname.def"'
+ ;;
+ esac
+ }
+ fi
+ fi
+
+ for dlprefile in $dlprefiles; do
+ func_verbose "extracting global C symbols from '$dlprefile'"
+ func_basename "$dlprefile"
+ name=$func_basename_result
+ case $host in
+ *cygwin* | *mingw* | *cegcc* )
+ # if an import library, we need to obtain dlname
+ if func_win32_import_lib_p "$dlprefile"; then
+ func_tr_sh "$dlprefile"
+ eval "curr_lafile=\$libfile_$func_tr_sh_result"
+ dlprefile_dlbasename=
+ if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then
+ # Use subshell, to avoid clobbering current variable values
+ dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"`
+ if test -n "$dlprefile_dlname"; then
+ func_basename "$dlprefile_dlname"
+ dlprefile_dlbasename=$func_basename_result
+ else
+ # no lafile. user explicitly requested -dlpreopen <import library>.
+ $sharedlib_from_linklib_cmd "$dlprefile"
+ dlprefile_dlbasename=$sharedlib_from_linklib_result
+ fi
+ fi
+ $opt_dry_run || {
+ if test -n "$dlprefile_dlbasename"; then
+ eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"'
+ else
+ func_warning "Could not compute DLL name from $name"
+ eval '$ECHO ": $name " >> "$nlist"'
+ fi
+ func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32
+ eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe |
+ $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'"
+ }
+ else # not an import lib
+ $opt_dry_run || {
+ eval '$ECHO ": $name " >> "$nlist"'
+ func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32
+ eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'"
+ }
+ fi
+ ;;
+ *)
+ $opt_dry_run || {
+ eval '$ECHO ": $name " >> "$nlist"'
+ func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32
+ eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'"
+ }
+ ;;
+ esac
+ done
+
+ $opt_dry_run || {
+ # Make sure we have at least an empty file.
+ test -f "$nlist" || : > "$nlist"
+
+ if test -n "$exclude_expsyms"; then
+ $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T
+ $MV "$nlist"T "$nlist"
+ fi
+
+ # Try sorting and uniquifying the output.
+ if $GREP -v "^: " < "$nlist" |
+ if sort -k 3 </dev/null >/dev/null 2>&1; then
+ sort -k 3
+ else
+ sort +2
+ fi |
+ uniq > "$nlist"S; then
+ :
+ else
+ $GREP -v "^: " < "$nlist" > "$nlist"S
+ fi
+
+ if test -f "$nlist"S; then
+ eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"'
+ else
+ echo '/* NONE */' >> "$output_objdir/$my_dlsyms"
+ fi
+
+ func_show_eval '$RM "${nlist}I"'
+ if test -n "$global_symbol_to_import"; then
+ eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I'
+ fi
+
+ echo >> "$output_objdir/$my_dlsyms" "\
+
+/* The mapping between symbol names and symbols. */
+typedef struct {
+ const char *name;
+ void *address;
+} lt_dlsymlist;
+extern LT_DLSYM_CONST lt_dlsymlist
+lt_${my_prefix}_LTX_preloaded_symbols[];\
+"
+
+ if test -s "$nlist"I; then
+ echo >> "$output_objdir/$my_dlsyms" "\
+static void lt_syminit(void)
+{
+ LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols;
+ for (; symbol->name; ++symbol)
+ {"
+ $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms"
+ echo >> "$output_objdir/$my_dlsyms" "\
+ }
+}"
+ fi
+ echo >> "$output_objdir/$my_dlsyms" "\
+LT_DLSYM_CONST lt_dlsymlist
+lt_${my_prefix}_LTX_preloaded_symbols[] =
+{ {\"$my_originator\", (void *) 0},"
+
+ if test -s "$nlist"I; then
+ echo >> "$output_objdir/$my_dlsyms" "\
+ {\"@INIT@\", (void *) <_syminit},"
+ fi
+
+ case $need_lib_prefix in
+ no)
+ eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms"
+ ;;
+ *)
+ eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms"
+ ;;
+ esac
+ echo >> "$output_objdir/$my_dlsyms" "\
+ {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+ return lt_${my_prefix}_LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif\
+"
+ } # !$opt_dry_run
+
+ pic_flag_for_symtable=
+ case "$compile_command " in
+ *" -static "*) ;;
+ *)
+ case $host in
+ # compiling the symbol table file with pic_flag works around
+ # a FreeBSD bug that causes programs to crash when -lm is
+ # linked before any other PIC object. But we must not use
+ # pic_flag when linking with -static. The problem exists in
+ # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1.
+ *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*)
+ pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;;
+ *-*-hpux*)
+ pic_flag_for_symtable=" $pic_flag" ;;
+ *)
+ $my_pic_p && pic_flag_for_symtable=" $pic_flag"
+ ;;
+ esac
+ ;;
+ esac
+ symtab_cflags=
+ for arg in $LTCFLAGS; do
+ case $arg in
+ -pie | -fpie | -fPIE) ;;
+ *) func_append symtab_cflags " $arg" ;;
+ esac
+ done
+
+ # Now compile the dynamic symbol file.
+ func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?'
+
+ # Clean up the generated files.
+ func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"'
+
+ # Transform the symbol file into the correct name.
+ symfileobj=$output_objdir/${my_outputname}S.$objext
+ case $host in
+ *cygwin* | *mingw* | *cegcc* )
+ if test -f "$output_objdir/$my_outputname.def"; then
+ compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
+ finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"`
+ else
+ compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+ finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+ fi
+ ;;
+ *)
+ compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+ finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"`
+ ;;
+ esac
+ ;;
+ *)
+ func_fatal_error "unknown suffix for '$my_dlsyms'"
+ ;;
+ esac
+ else
+ # We keep going just in case the user didn't refer to
+ # lt_preloaded_symbols. The linker will fail if global_symbol_pipe
+ # really was required.
+
+ # Nullify the symbol file.
+ compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"`
+ finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"`
+ fi
+}
+
+# func_cygming_gnu_implib_p ARG
+# This predicate returns with zero status (TRUE) if
+# ARG is a GNU/binutils-style import library. Returns
+# with nonzero status (FALSE) otherwise.
+func_cygming_gnu_implib_p ()
+{
+ $debug_cmd
+
+ func_to_tool_file "$1" func_convert_file_msys_to_w32
+ func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'`
+ test -n "$func_cygming_gnu_implib_tmp"
+}
+
+# func_cygming_ms_implib_p ARG
+# This predicate returns with zero status (TRUE) if
+# ARG is an MS-style import library. Returns
+# with nonzero status (FALSE) otherwise.
+func_cygming_ms_implib_p ()
+{
+ $debug_cmd
+
+ func_to_tool_file "$1" func_convert_file_msys_to_w32
+ func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'`
+ test -n "$func_cygming_ms_implib_tmp"
+}
+
+# func_win32_libid arg
+# return the library type of file 'arg'
+#
+# Need a lot of goo to handle *both* DLLs and import libs
+# Has to be a shell function in order to 'eat' the argument
+# that is supplied when $file_magic_command is called.
+# Despite the name, also deal with 64 bit binaries.
+func_win32_libid ()
+{
+ $debug_cmd
+
+ win32_libid_type=unknown
+ win32_fileres=`file -L $1 2>/dev/null`
+ case $win32_fileres in
+ *ar\ archive\ import\ library*) # definitely import
+ win32_libid_type="x86 archive import"
+ ;;
+ *ar\ archive*) # could be an import, or static
+ # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD.
+ if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null |
+ $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then
+ case $nm_interface in
+ "MS dumpbin")
+ if func_cygming_ms_implib_p "$1" ||
+ func_cygming_gnu_implib_p "$1"
+ then
+ win32_nmres=import
+ else
+ win32_nmres=
+ fi
+ ;;
+ *)
+ func_to_tool_file "$1" func_convert_file_msys_to_w32
+ win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" |
+ $SED -n -e '
+ 1,100{
+ / I /{
+ s|.*|import|
+ p
+ q
+ }
+ }'`
+ ;;
+ esac
+ case $win32_nmres in
+ import*) win32_libid_type="x86 archive import";;
+ *) win32_libid_type="x86 archive static";;
+ esac
+ fi
+ ;;
+ *DLL*)
+ win32_libid_type="x86 DLL"
+ ;;
+ *executable*) # but shell scripts are "executable" too...
+ case $win32_fileres in
+ *MS\ Windows\ PE\ Intel*)
+ win32_libid_type="x86 DLL"
+ ;;
+ esac
+ ;;
+ esac
+ $ECHO "$win32_libid_type"
+}
+
+# func_cygming_dll_for_implib ARG
+#
+# Platform-specific function to extract the
+# name of the DLL associated with the specified
+# import library ARG.
+# Invoked by eval'ing the libtool variable
+# $sharedlib_from_linklib_cmd
+# Result is available in the variable
+# $sharedlib_from_linklib_result
+func_cygming_dll_for_implib ()
+{
+ $debug_cmd
+
+ sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"`
+}
+
+# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs
+#
+# The is the core of a fallback implementation of a
+# platform-specific function to extract the name of the
+# DLL associated with the specified import library LIBNAME.
+#
+# SECTION_NAME is either .idata$6 or .idata$7, depending
+# on the platform and compiler that created the implib.
+#
+# Echos the name of the DLL associated with the
+# specified import library.
+func_cygming_dll_for_implib_fallback_core ()
+{
+ $debug_cmd
+
+ match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"`
+ $OBJDUMP -s --section "$1" "$2" 2>/dev/null |
+ $SED '/^Contents of section '"$match_literal"':/{
+ # Place marker at beginning of archive member dllname section
+ s/.*/====MARK====/
+ p
+ d
+ }
+ # These lines can sometimes be longer than 43 characters, but
+ # are always uninteresting
+ /:[ ]*file format pe[i]\{,1\}-/d
+ /^In archive [^:]*:/d
+ # Ensure marker is printed
+ /^====MARK====/p
+ # Remove all lines with less than 43 characters
+ /^.\{43\}/!d
+ # From remaining lines, remove first 43 characters
+ s/^.\{43\}//' |
+ $SED -n '
+ # Join marker and all lines until next marker into a single line
+ /^====MARK====/ b para
+ H
+ $ b para
+ b
+ :para
+ x
+ s/\n//g
+ # Remove the marker
+ s/^====MARK====//
+ # Remove trailing dots and whitespace
+ s/[\. \t]*$//
+ # Print
+ /./p' |
+ # we now have a list, one entry per line, of the stringified
+ # contents of the appropriate section of all members of the
+ # archive that possess that section. Heuristic: eliminate
+ # all those that have a first or second character that is
+ # a '.' (that is, objdump's representation of an unprintable
+ # character.) This should work for all archives with less than
+ # 0x302f exports -- but will fail for DLLs whose name actually
+ # begins with a literal '.' or a single character followed by
+ # a '.'.
+ #
+ # Of those that remain, print the first one.
+ $SED -e '/^\./d;/^.\./d;q'
+}
+
+# func_cygming_dll_for_implib_fallback ARG
+# Platform-specific function to extract the
+# name of the DLL associated with the specified
+# import library ARG.
+#
+# This fallback implementation is for use when $DLLTOOL
+# does not support the --identify-strict option.
+# Invoked by eval'ing the libtool variable
+# $sharedlib_from_linklib_cmd
+# Result is available in the variable
+# $sharedlib_from_linklib_result
+func_cygming_dll_for_implib_fallback ()
+{
+ $debug_cmd
+
+ if func_cygming_gnu_implib_p "$1"; then
+ # binutils import library
+ sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"`
+ elif func_cygming_ms_implib_p "$1"; then
+ # ms-generated import library
+ sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"`
+ else
+ # unknown
+ sharedlib_from_linklib_result=
+ fi
+}
+
+
+# func_extract_an_archive dir oldlib
+func_extract_an_archive ()
+{
+ $debug_cmd
+
+ f_ex_an_ar_dir=$1; shift
+ f_ex_an_ar_oldlib=$1
+ if test yes = "$lock_old_archive_extraction"; then
+ lockfile=$f_ex_an_ar_oldlib.lock
+ until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do
+ func_echo "Waiting for $lockfile to be removed"
+ sleep 2
+ done
+ fi
+ func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \
+ 'stat=$?; rm -f "$lockfile"; exit $stat'
+ if test yes = "$lock_old_archive_extraction"; then
+ $opt_dry_run || rm -f "$lockfile"
+ fi
+ if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then
+ :
+ else
+ func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib"
+ fi
+}
+
+
+# func_extract_archives gentop oldlib ...
+func_extract_archives ()
+{
+ $debug_cmd
+
+ my_gentop=$1; shift
+ my_oldlibs=${1+"$@"}
+ my_oldobjs=
+ my_xlib=
+ my_xabs=
+ my_xdir=
+
+ for my_xlib in $my_oldlibs; do
+ # Extract the objects.
+ case $my_xlib in
+ [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;;
+ *) my_xabs=`pwd`"/$my_xlib" ;;
+ esac
+ func_basename "$my_xlib"
+ my_xlib=$func_basename_result
+ my_xlib_u=$my_xlib
+ while :; do
+ case " $extracted_archives " in
+ *" $my_xlib_u "*)
+ func_arith $extracted_serial + 1
+ extracted_serial=$func_arith_result
+ my_xlib_u=lt$extracted_serial-$my_xlib ;;
+ *) break ;;
+ esac
+ done
+ extracted_archives="$extracted_archives $my_xlib_u"
+ my_xdir=$my_gentop/$my_xlib_u
+
+ func_mkdir_p "$my_xdir"
+
+ case $host in
+ *-darwin*)
+ func_verbose "Extracting $my_xabs"
+ # Do not bother doing anything if just a dry run
+ $opt_dry_run || {
+ darwin_orig_dir=`pwd`
+ cd $my_xdir || exit $?
+ darwin_archive=$my_xabs
+ darwin_curdir=`pwd`
+ func_basename "$darwin_archive"
+ darwin_base_archive=$func_basename_result
+ darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true`
+ if test -n "$darwin_arches"; then
+ darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'`
+ darwin_arch=
+ func_verbose "$darwin_base_archive has multiple architectures $darwin_arches"
+ for darwin_arch in $darwin_arches; do
+ func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch"
+ $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive"
+ cd "unfat-$$/$darwin_base_archive-$darwin_arch"
+ func_extract_an_archive "`pwd`" "$darwin_base_archive"
+ cd "$darwin_curdir"
+ $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive"
+ done # $darwin_arches
+ ## Okay now we've a bunch of thin objects, gotta fatten them up :)
+ darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u`
+ darwin_file=
+ darwin_files=
+ for darwin_file in $darwin_filelist; do
+ darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP`
+ $LIPO -create -output "$darwin_file" $darwin_files
+ done # $darwin_filelist
+ $RM -rf unfat-$$
+ cd "$darwin_orig_dir"
+ else
+ cd $darwin_orig_dir
+ func_extract_an_archive "$my_xdir" "$my_xabs"
+ fi # $darwin_arches
+ } # !$opt_dry_run
+ ;;
+ *)
+ func_extract_an_archive "$my_xdir" "$my_xabs"
+ ;;
+ esac
+ my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP`
+ done
+
+ func_extract_archives_result=$my_oldobjs
+}
+
+
+# func_emit_wrapper [arg=no]
+#
+# Emit a libtool wrapper script on stdout.
+# Don't directly open a file because we may want to
+# incorporate the script contents within a cygwin/mingw
+# wrapper executable. Must ONLY be called from within
+# func_mode_link because it depends on a number of variables
+# set therein.
+#
+# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR
+# variable will take. If 'yes', then the emitted script
+# will assume that the directory where it is stored is
+# the $objdir directory. This is a cygwin/mingw-specific
+# behavior.
+func_emit_wrapper ()
+{
+ func_emit_wrapper_arg1=${1-no}
+
+ $ECHO "\
+#! $SHELL
+
+# $output - temporary wrapper script for $objdir/$outputname
+# Generated by $PROGRAM (GNU $PACKAGE) $VERSION
+#
+# The $output program cannot be directly executed until all the libtool
+# libraries that it depends on are installed.
+#
+# This wrapper script should never be moved out of the build directory.
+# If it is, it will not operate correctly.
+
+# Sed substitution that helps us do robust quoting. It backslashifies
+# metacharacters that are still active within double-quoted strings.
+sed_quote_subst='$sed_quote_subst'
+
+# Be Bourne compatible
+if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac
+fi
+BIN_SH=xpg4; export BIN_SH # for Tru64
+DUALCASE=1; export DUALCASE # for MKS sh
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+relink_command=\"$relink_command\"
+
+# This environment variable determines our operation mode.
+if test \"\$libtool_install_magic\" = \"$magic\"; then
+ # install mode needs the following variables:
+ generated_by_libtool_version='$macro_version'
+ notinst_deplibs='$notinst_deplibs'
+else
+ # When we are sourced in execute mode, \$file and \$ECHO are already set.
+ if test \"\$libtool_execute_magic\" != \"$magic\"; then
+ file=\"\$0\""
+
+ qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"`
+ $ECHO "\
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+ eval 'cat <<_LTECHO_EOF
+\$1
+_LTECHO_EOF'
+}
+ ECHO=\"$qECHO\"
+ fi
+
+# Very basic option parsing. These options are (a) specific to
+# the libtool wrapper, (b) are identical between the wrapper
+# /script/ and the wrapper /executable/ that is used only on
+# windows platforms, and (c) all begin with the string "--lt-"
+# (application programs are unlikely to have options that match
+# this pattern).
+#
+# There are only two supported options: --lt-debug and
+# --lt-dump-script. There is, deliberately, no --lt-help.
+#
+# The first argument to this parsing function should be the
+# script's $0 value, followed by "$@".
+lt_option_debug=
+func_parse_lt_options ()
+{
+ lt_script_arg0=\$0
+ shift
+ for lt_opt
+ do
+ case \"\$lt_opt\" in
+ --lt-debug) lt_option_debug=1 ;;
+ --lt-dump-script)
+ lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\`
+ test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=.
+ lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\`
+ cat \"\$lt_dump_D/\$lt_dump_F\"
+ exit 0
+ ;;
+ --lt-*)
+ \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2
+ exit 1
+ ;;
+ esac
+ done
+
+ # Print the debug banner immediately:
+ if test -n \"\$lt_option_debug\"; then
+ echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2
+ fi
+}
+
+# Used when --lt-debug. Prints its arguments to stdout
+# (redirection is the responsibility of the caller)
+func_lt_dump_args ()
+{
+ lt_dump_args_N=1;
+ for lt_arg
+ do
+ \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\"
+ lt_dump_args_N=\`expr \$lt_dump_args_N + 1\`
+ done
+}
+
+# Core function for launching the target application
+func_exec_program_core ()
+{
+"
+ case $host in
+ # Backslashes separate directories on plain windows
+ *-*-mingw | *-*-os2* | *-cegcc*)
+ $ECHO "\
+ if test -n \"\$lt_option_debug\"; then
+ \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2
+ func_lt_dump_args \${1+\"\$@\"} 1>&2
+ fi
+ exec \"\$progdir\\\\\$program\" \${1+\"\$@\"}
+"
+ ;;
+
+ *)
+ $ECHO "\
+ if test -n \"\$lt_option_debug\"; then
+ \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2
+ func_lt_dump_args \${1+\"\$@\"} 1>&2
+ fi
+ exec \"\$progdir/\$program\" \${1+\"\$@\"}
+"
+ ;;
+ esac
+ $ECHO "\
+ \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2
+ exit 1
+}
+
+# A function to encapsulate launching the target application
+# Strips options in the --lt-* namespace from \$@ and
+# launches target application with the remaining arguments.
+func_exec_program ()
+{
+ case \" \$* \" in
+ *\\ --lt-*)
+ for lt_wr_arg
+ do
+ case \$lt_wr_arg in
+ --lt-*) ;;
+ *) set x \"\$@\" \"\$lt_wr_arg\"; shift;;
+ esac
+ shift
+ done ;;
+ esac
+ func_exec_program_core \${1+\"\$@\"}
+}
+
+ # Parse options
+ func_parse_lt_options \"\$0\" \${1+\"\$@\"}
+
+ # Find the directory that this script lives in.
+ thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\`
+ test \"x\$thisdir\" = \"x\$file\" && thisdir=.
+
+ # Follow symbolic links until we get to the real thisdir.
+ file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\`
+ while test -n \"\$file\"; do
+ destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\`
+
+ # If there was a directory component, then change thisdir.
+ if test \"x\$destdir\" != \"x\$file\"; then
+ case \"\$destdir\" in
+ [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;;
+ *) thisdir=\"\$thisdir/\$destdir\" ;;
+ esac
+ fi
+
+ file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\`
+ file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\`
+ done
+
+ # Usually 'no', except on cygwin/mingw when embedded into
+ # the cwrapper.
+ WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1
+ if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then
+ # special case for '.'
+ if test \"\$thisdir\" = \".\"; then
+ thisdir=\`pwd\`
+ fi
+ # remove .libs from thisdir
+ case \"\$thisdir\" in
+ *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;;
+ $objdir ) thisdir=. ;;
+ esac
+ fi
+
+ # Try to get the absolute directory name.
+ absdir=\`cd \"\$thisdir\" && pwd\`
+ test -n \"\$absdir\" && thisdir=\"\$absdir\"
+"
+
+ if test yes = "$fast_install"; then
+ $ECHO "\
+ program=lt-'$outputname'$exeext
+ progdir=\"\$thisdir/$objdir\"
+
+ if test ! -f \"\$progdir/\$program\" ||
+ { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\
+ test \"X\$file\" != \"X\$progdir/\$program\"; }; then
+
+ file=\"\$\$-\$program\"
+
+ if test ! -d \"\$progdir\"; then
+ $MKDIR \"\$progdir\"
+ else
+ $RM \"\$progdir/\$file\"
+ fi"
+
+ $ECHO "\
+
+ # relink executable if necessary
+ if test -n \"\$relink_command\"; then
+ if relink_command_output=\`eval \$relink_command 2>&1\`; then :
+ else
+ \$ECHO \"\$relink_command_output\" >&2
+ $RM \"\$progdir/\$file\"
+ exit 1
+ fi
+ fi
+
+ $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null ||
+ { $RM \"\$progdir/\$program\";
+ $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; }
+ $RM \"\$progdir/\$file\"
+ fi"
+ else
+ $ECHO "\
+ program='$outputname'
+ progdir=\"\$thisdir/$objdir\"
+"
+ fi
+
+ $ECHO "\
+
+ if test -f \"\$progdir/\$program\"; then"
+
+ # fixup the dll searchpath if we need to.
+ #
+ # Fix the DLL searchpath if we need to. Do this before prepending
+ # to shlibpath, because on Windows, both are PATH and uninstalled
+ # libraries must come first.
+ if test -n "$dllsearchpath"; then
+ $ECHO "\
+ # Add the dll search path components to the executable PATH
+ PATH=$dllsearchpath:\$PATH
+"
+ fi
+
+ # Export our shlibpath_var if we have one.
+ if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+ $ECHO "\
+ # Add our own library path to $shlibpath_var
+ $shlibpath_var=\"$temp_rpath\$$shlibpath_var\"
+
+ # Some systems cannot cope with colon-terminated $shlibpath_var
+ # The second colon is a workaround for a bug in BeOS R4 sed
+ $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\`
+
+ export $shlibpath_var
+"
+ fi
+
+ $ECHO "\
+ if test \"\$libtool_execute_magic\" != \"$magic\"; then
+ # Run the actual program with our arguments.
+ func_exec_program \${1+\"\$@\"}
+ fi
+ else
+ # The program doesn't exist.
+ \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2
+ \$ECHO \"This script is just a wrapper for \$program.\" 1>&2
+ \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2
+ exit 1
+ fi
+fi\
+"
+}
+
+
+# func_emit_cwrapperexe_src
+# emit the source code for a wrapper executable on stdout
+# Must ONLY be called from within func_mode_link because
+# it depends on a number of variable set therein.
+func_emit_cwrapperexe_src ()
+{
+ cat <<EOF
+
+/* $cwrappersource - temporary wrapper executable for $objdir/$outputname
+ Generated by $PROGRAM (GNU $PACKAGE) $VERSION
+
+ The $output program cannot be directly executed until all the libtool
+ libraries that it depends on are installed.
+
+ This wrapper executable should never be moved out of the build directory.
+ If it is, it will not operate correctly.
+*/
+EOF
+ cat <<"EOF"
+#ifdef _MSC_VER
+# define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef _MSC_VER
+# include <direct.h>
+# include <process.h>
+# include <io.h>
+#else
+# include <unistd.h>
+# include <stdint.h>
+# ifdef __CYGWIN__
+# include <io.h>
+# endif
+#endif
+#include <malloc.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0)
+
+/* declarations of non-ANSI functions */
+#if defined __MINGW32__
+# ifdef __STRICT_ANSI__
+int _putenv (const char *);
+# endif
+#elif defined __CYGWIN__
+# ifdef __STRICT_ANSI__
+char *realpath (const char *, char *);
+int putenv (char *);
+int setenv (const char *, const char *, int);
+# endif
+/* #elif defined other_platform || defined ... */
+#endif
+
+/* portability defines, excluding path handling macros */
+#if defined _MSC_VER
+# define setmode _setmode
+# define stat _stat
+# define chmod _chmod
+# define getcwd _getcwd
+# define putenv _putenv
+# define S_IXUSR _S_IEXEC
+#elif defined __MINGW32__
+# define setmode _setmode
+# define stat _stat
+# define chmod _chmod
+# define getcwd _getcwd
+# define putenv _putenv
+#elif defined __CYGWIN__
+# define HAVE_SETENV
+# define FOPEN_WB "wb"
+/* #elif defined other platforms ... */
+#endif
+
+#if defined PATH_MAX
+# define LT_PATHMAX PATH_MAX
+#elif defined MAXPATHLEN
+# define LT_PATHMAX MAXPATHLEN
+#else
+# define LT_PATHMAX 1024
+#endif
+
+#ifndef S_IXOTH
+# define S_IXOTH 0
+#endif
+#ifndef S_IXGRP
+# define S_IXGRP 0
+#endif
+
+/* path handling portability macros */
+#ifndef DIR_SEPARATOR
+# define DIR_SEPARATOR '/'
+# define PATH_SEPARATOR ':'
+#endif
+
+#if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \
+ defined __OS2__
+# define HAVE_DOS_BASED_FILE_SYSTEM
+# define FOPEN_WB "wb"
+# ifndef DIR_SEPARATOR_2
+# define DIR_SEPARATOR_2 '\\'
+# endif
+# ifndef PATH_SEPARATOR_2
+# define PATH_SEPARATOR_2 ';'
+# endif
+#endif
+
+#ifndef DIR_SEPARATOR_2
+# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
+#else /* DIR_SEPARATOR_2 */
+# define IS_DIR_SEPARATOR(ch) \
+ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
+#endif /* DIR_SEPARATOR_2 */
+
+#ifndef PATH_SEPARATOR_2
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR)
+#else /* PATH_SEPARATOR_2 */
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2)
+#endif /* PATH_SEPARATOR_2 */
+
+#ifndef FOPEN_WB
+# define FOPEN_WB "w"
+#endif
+#ifndef _O_BINARY
+# define _O_BINARY 0
+#endif
+
+#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type)))
+#define XFREE(stale) do { \
+ if (stale) { free (stale); stale = 0; } \
+} while (0)
+
+#if defined LT_DEBUGWRAPPER
+static int lt_debug = 1;
+#else
+static int lt_debug = 0;
+#endif
+
+const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */
+
+void *xmalloc (size_t num);
+char *xstrdup (const char *string);
+const char *base_name (const char *name);
+char *find_executable (const char *wrapper);
+char *chase_symlinks (const char *pathspec);
+int make_executable (const char *path);
+int check_executable (const char *path);
+char *strendzap (char *str, const char *pat);
+void lt_debugprintf (const char *file, int line, const char *fmt, ...);
+void lt_fatal (const char *file, int line, const char *message, ...);
+static const char *nonnull (const char *s);
+static const char *nonempty (const char *s);
+void lt_setenv (const char *name, const char *value);
+char *lt_extend_str (const char *orig_value, const char *add, int to_end);
+void lt_update_exe_path (const char *name, const char *value);
+void lt_update_lib_path (const char *name, const char *value);
+char **prepare_spawn (char **argv);
+void lt_dump_script (FILE *f);
+EOF
+
+ cat <<EOF
+#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 5)
+# define externally_visible volatile
+#else
+# define externally_visible __attribute__((externally_visible)) volatile
+#endif
+externally_visible const char * MAGIC_EXE = "$magic_exe";
+const char * LIB_PATH_VARNAME = "$shlibpath_var";
+EOF
+
+ if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then
+ func_to_host_path "$temp_rpath"
+ cat <<EOF
+const char * LIB_PATH_VALUE = "$func_to_host_path_result";
+EOF
+ else
+ cat <<"EOF"
+const char * LIB_PATH_VALUE = "";
+EOF
+ fi
+
+ if test -n "$dllsearchpath"; then
+ func_to_host_path "$dllsearchpath:"
+ cat <<EOF
+const char * EXE_PATH_VARNAME = "PATH";
+const char * EXE_PATH_VALUE = "$func_to_host_path_result";
+EOF
+ else
+ cat <<"EOF"
+const char * EXE_PATH_VARNAME = "";
+const char * EXE_PATH_VALUE = "";
+EOF
+ fi
+
+ if test yes = "$fast_install"; then
+ cat <<EOF
+const char * TARGET_PROGRAM_NAME = "lt-$outputname"; /* hopefully, no .exe */
+EOF
+ else
+ cat <<EOF
+const char * TARGET_PROGRAM_NAME = "$outputname"; /* hopefully, no .exe */
+EOF
+ fi
+
+
+ cat <<"EOF"
+
+#define LTWRAPPER_OPTION_PREFIX "--lt-"
+
+static const char *ltwrapper_option_prefix = LTWRAPPER_OPTION_PREFIX;
+static const char *dumpscript_opt = LTWRAPPER_OPTION_PREFIX "dump-script";
+static const char *debug_opt = LTWRAPPER_OPTION_PREFIX "debug";
+
+int
+main (int argc, char *argv[])
+{
+ char **newargz;
+ int newargc;
+ char *tmp_pathspec;
+ char *actual_cwrapper_path;
+ char *actual_cwrapper_name;
+ char *target_name;
+ char *lt_argv_zero;
+ int rval = 127;
+
+ int i;
+
+ program_name = (char *) xstrdup (base_name (argv[0]));
+ newargz = XMALLOC (char *, (size_t) argc + 1);
+
+ /* very simple arg parsing; don't want to rely on getopt
+ * also, copy all non cwrapper options to newargz, except
+ * argz[0], which is handled differently
+ */
+ newargc=0;
+ for (i = 1; i < argc; i++)
+ {
+ if (STREQ (argv[i], dumpscript_opt))
+ {
+EOF
+ case $host in
+ *mingw* | *cygwin* )
+ # make stdout use "unix" line endings
+ echo " setmode(1,_O_BINARY);"
+ ;;
+ esac
+
+ cat <<"EOF"
+ lt_dump_script (stdout);
+ return 0;
+ }
+ if (STREQ (argv[i], debug_opt))
+ {
+ lt_debug = 1;
+ continue;
+ }
+ if (STREQ (argv[i], ltwrapper_option_prefix))
+ {
+ /* however, if there is an option in the LTWRAPPER_OPTION_PREFIX
+ namespace, but it is not one of the ones we know about and
+ have already dealt with, above (inluding dump-script), then
+ report an error. Otherwise, targets might begin to believe
+ they are allowed to use options in the LTWRAPPER_OPTION_PREFIX
+ namespace. The first time any user complains about this, we'll
+ need to make LTWRAPPER_OPTION_PREFIX a configure-time option
+ or a configure.ac-settable value.
+ */
+ lt_fatal (__FILE__, __LINE__,
+ "unrecognized %s option: '%s'",
+ ltwrapper_option_prefix, argv[i]);
+ }
+ /* otherwise ... */
+ newargz[++newargc] = xstrdup (argv[i]);
+ }
+ newargz[++newargc] = NULL;
+
+EOF
+ cat <<EOF
+ /* The GNU banner must be the first non-error debug message */
+ lt_debugprintf (__FILE__, __LINE__, "libtool wrapper (GNU $PACKAGE) $VERSION\n");
+EOF
+ cat <<"EOF"
+ lt_debugprintf (__FILE__, __LINE__, "(main) argv[0]: %s\n", argv[0]);
+ lt_debugprintf (__FILE__, __LINE__, "(main) program_name: %s\n", program_name);
+
+ tmp_pathspec = find_executable (argv[0]);
+ if (tmp_pathspec == NULL)
+ lt_fatal (__FILE__, __LINE__, "couldn't find %s", argv[0]);
+ lt_debugprintf (__FILE__, __LINE__,
+ "(main) found exe (before symlink chase) at: %s\n",
+ tmp_pathspec);
+
+ actual_cwrapper_path = chase_symlinks (tmp_pathspec);
+ lt_debugprintf (__FILE__, __LINE__,
+ "(main) found exe (after symlink chase) at: %s\n",
+ actual_cwrapper_path);
+ XFREE (tmp_pathspec);
+
+ actual_cwrapper_name = xstrdup (base_name (actual_cwrapper_path));
+ strendzap (actual_cwrapper_path, actual_cwrapper_name);
+
+ /* wrapper name transforms */
+ strendzap (actual_cwrapper_name, ".exe");
+ tmp_pathspec = lt_extend_str (actual_cwrapper_name, ".exe", 1);
+ XFREE (actual_cwrapper_name);
+ actual_cwrapper_name = tmp_pathspec;
+ tmp_pathspec = 0;
+
+ /* target_name transforms -- use actual target program name; might have lt- prefix */
+ target_name = xstrdup (base_name (TARGET_PROGRAM_NAME));
+ strendzap (target_name, ".exe");
+ tmp_pathspec = lt_extend_str (target_name, ".exe", 1);
+ XFREE (target_name);
+ target_name = tmp_pathspec;
+ tmp_pathspec = 0;
+
+ lt_debugprintf (__FILE__, __LINE__,
+ "(main) libtool target name: %s\n",
+ target_name);
+EOF
+
+ cat <<EOF
+ newargz[0] =
+ XMALLOC (char, (strlen (actual_cwrapper_path) +
+ strlen ("$objdir") + 1 + strlen (actual_cwrapper_name) + 1));
+ strcpy (newargz[0], actual_cwrapper_path);
+ strcat (newargz[0], "$objdir");
+ strcat (newargz[0], "/");
+EOF
+
+ cat <<"EOF"
+ /* stop here, and copy so we don't have to do this twice */
+ tmp_pathspec = xstrdup (newargz[0]);
+
+ /* do NOT want the lt- prefix here, so use actual_cwrapper_name */
+ strcat (newargz[0], actual_cwrapper_name);
+
+ /* DO want the lt- prefix here if it exists, so use target_name */
+ lt_argv_zero = lt_extend_str (tmp_pathspec, target_name, 1);
+ XFREE (tmp_pathspec);
+ tmp_pathspec = NULL;
+EOF
+
+ case $host_os in
+ mingw*)
+ cat <<"EOF"
+ {
+ char* p;
+ while ((p = strchr (newargz[0], '\\')) != NULL)
+ {
+ *p = '/';
+ }
+ while ((p = strchr (lt_argv_zero, '\\')) != NULL)
+ {
+ *p = '/';
+ }
+ }
+EOF
+ ;;
+ esac
+
+ cat <<"EOF"
+ XFREE (target_name);
+ XFREE (actual_cwrapper_path);
+ XFREE (actual_cwrapper_name);
+
+ lt_setenv ("BIN_SH", "xpg4"); /* for Tru64 */
+ lt_setenv ("DUALCASE", "1"); /* for MSK sh */
+ /* Update the DLL searchpath. EXE_PATH_VALUE ($dllsearchpath) must
+ be prepended before (that is, appear after) LIB_PATH_VALUE ($temp_rpath)
+ because on Windows, both *_VARNAMEs are PATH but uninstalled
+ libraries must come first. */
+ lt_update_exe_path (EXE_PATH_VARNAME, EXE_PATH_VALUE);
+ lt_update_lib_path (LIB_PATH_VARNAME, LIB_PATH_VALUE);
+
+ lt_debugprintf (__FILE__, __LINE__, "(main) lt_argv_zero: %s\n",
+ nonnull (lt_argv_zero));
+ for (i = 0; i < newargc; i++)
+ {
+ lt_debugprintf (__FILE__, __LINE__, "(main) newargz[%d]: %s\n",
+ i, nonnull (newargz[i]));
+ }
+
+EOF
+
+ case $host_os in
+ mingw*)
+ cat <<"EOF"
+ /* execv doesn't actually work on mingw as expected on unix */
+ newargz = prepare_spawn (newargz);
+ rval = (int) _spawnv (_P_WAIT, lt_argv_zero, (const char * const *) newargz);
+ if (rval == -1)
+ {
+ /* failed to start process */
+ lt_debugprintf (__FILE__, __LINE__,
+ "(main) failed to launch target \"%s\": %s\n",
+ lt_argv_zero, nonnull (strerror (errno)));
+ return 127;
+ }
+ return rval;
+EOF
+ ;;
+ *)
+ cat <<"EOF"
+ execv (lt_argv_zero, newargz);
+ return rval; /* =127, but avoids unused variable warning */
+EOF
+ ;;
+ esac
+
+ cat <<"EOF"
+}
+
+void *
+xmalloc (size_t num)
+{
+ void *p = (void *) malloc (num);
+ if (!p)
+ lt_fatal (__FILE__, __LINE__, "memory exhausted");
+
+ return p;
+}
+
+char *
+xstrdup (const char *string)
+{
+ return string ? strcpy ((char *) xmalloc (strlen (string) + 1),
+ string) : NULL;
+}
+
+const char *
+base_name (const char *name)
+{
+ const char *base;
+
+#if defined HAVE_DOS_BASED_FILE_SYSTEM
+ /* Skip over the disk name in MSDOS pathnames. */
+ if (isalpha ((unsigned char) name[0]) && name[1] == ':')
+ name += 2;
+#endif
+
+ for (base = name; *name; name++)
+ if (IS_DIR_SEPARATOR (*name))
+ base = name + 1;
+ return base;
+}
+
+int
+check_executable (const char *path)
+{
+ struct stat st;
+
+ lt_debugprintf (__FILE__, __LINE__, "(check_executable): %s\n",
+ nonempty (path));
+ if ((!path) || (!*path))
+ return 0;
+
+ if ((stat (path, &st) >= 0)
+ && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
+ return 1;
+ else
+ return 0;
+}
+
+int
+make_executable (const char *path)
+{
+ int rval = 0;
+ struct stat st;
+
+ lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n",
+ nonempty (path));
+ if ((!path) || (!*path))
+ return 0;
+
+ if (stat (path, &st) >= 0)
+ {
+ rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR);
+ }
+ return rval;
+}
+
+/* Searches for the full path of the wrapper. Returns
+ newly allocated full path name if found, NULL otherwise
+ Does not chase symlinks, even on platforms that support them.
+*/
+char *
+find_executable (const char *wrapper)
+{
+ int has_slash = 0;
+ const char *p;
+ const char *p_next;
+ /* static buffer for getcwd */
+ char tmp[LT_PATHMAX + 1];
+ size_t tmp_len;
+ char *concat_name;
+
+ lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n",
+ nonempty (wrapper));
+
+ if ((wrapper == NULL) || (*wrapper == '\0'))
+ return NULL;
+
+ /* Absolute path? */
+#if defined HAVE_DOS_BASED_FILE_SYSTEM
+ if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':')
+ {
+ concat_name = xstrdup (wrapper);
+ if (check_executable (concat_name))
+ return concat_name;
+ XFREE (concat_name);
+ }
+ else
+ {
+#endif
+ if (IS_DIR_SEPARATOR (wrapper[0]))
+ {
+ concat_name = xstrdup (wrapper);
+ if (check_executable (concat_name))
+ return concat_name;
+ XFREE (concat_name);
+ }
+#if defined HAVE_DOS_BASED_FILE_SYSTEM
+ }
+#endif
+
+ for (p = wrapper; *p; p++)
+ if (*p == '/')
+ {
+ has_slash = 1;
+ break;
+ }
+ if (!has_slash)
+ {
+ /* no slashes; search PATH */
+ const char *path = getenv ("PATH");
+ if (path != NULL)
+ {
+ for (p = path; *p; p = p_next)
+ {
+ const char *q;
+ size_t p_len;
+ for (q = p; *q; q++)
+ if (IS_PATH_SEPARATOR (*q))
+ break;
+ p_len = (size_t) (q - p);
+ p_next = (*q == '\0' ? q : q + 1);
+ if (p_len == 0)
+ {
+ /* empty path: current directory */
+ if (getcwd (tmp, LT_PATHMAX) == NULL)
+ lt_fatal (__FILE__, __LINE__, "getcwd failed: %s",
+ nonnull (strerror (errno)));
+ tmp_len = strlen (tmp);
+ concat_name =
+ XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
+ memcpy (concat_name, tmp, tmp_len);
+ concat_name[tmp_len] = '/';
+ strcpy (concat_name + tmp_len + 1, wrapper);
+ }
+ else
+ {
+ concat_name =
+ XMALLOC (char, p_len + 1 + strlen (wrapper) + 1);
+ memcpy (concat_name, p, p_len);
+ concat_name[p_len] = '/';
+ strcpy (concat_name + p_len + 1, wrapper);
+ }
+ if (check_executable (concat_name))
+ return concat_name;
+ XFREE (concat_name);
+ }
+ }
+ /* not found in PATH; assume curdir */
+ }
+ /* Relative path | not found in path: prepend cwd */
+ if (getcwd (tmp, LT_PATHMAX) == NULL)
+ lt_fatal (__FILE__, __LINE__, "getcwd failed: %s",
+ nonnull (strerror (errno)));
+ tmp_len = strlen (tmp);
+ concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1);
+ memcpy (concat_name, tmp, tmp_len);
+ concat_name[tmp_len] = '/';
+ strcpy (concat_name + tmp_len + 1, wrapper);
+
+ if (check_executable (concat_name))
+ return concat_name;
+ XFREE (concat_name);
+ return NULL;
+}
+
+char *
+chase_symlinks (const char *pathspec)
+{
+#ifndef S_ISLNK
+ return xstrdup (pathspec);
+#else
+ char buf[LT_PATHMAX];
+ struct stat s;
+ char *tmp_pathspec = xstrdup (pathspec);
+ char *p;
+ int has_symlinks = 0;
+ while (strlen (tmp_pathspec) && !has_symlinks)
+ {
+ lt_debugprintf (__FILE__, __LINE__,
+ "checking path component for symlinks: %s\n",
+ tmp_pathspec);
+ if (lstat (tmp_pathspec, &s) == 0)
+ {
+ if (S_ISLNK (s.st_mode) != 0)
+ {
+ has_symlinks = 1;
+ break;
+ }
+
+ /* search backwards for last DIR_SEPARATOR */
+ p = tmp_pathspec + strlen (tmp_pathspec) - 1;
+ while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))
+ p--;
+ if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p)))
+ {
+ /* no more DIR_SEPARATORS left */
+ break;
+ }
+ *p = '\0';
+ }
+ else
+ {
+ lt_fatal (__FILE__, __LINE__,
+ "error accessing file \"%s\": %s",
+ tmp_pathspec, nonnull (strerror (errno)));
+ }
+ }
+ XFREE (tmp_pathspec);
+
+ if (!has_symlinks)
+ {
+ return xstrdup (pathspec);
+ }
+
+ tmp_pathspec = realpath (pathspec, buf);
+ if (tmp_pathspec == 0)
+ {
+ lt_fatal (__FILE__, __LINE__,
+ "could not follow symlinks for %s", pathspec);
+ }
+ return xstrdup (tmp_pathspec);
+#endif
+}
+
+char *
+strendzap (char *str, const char *pat)
+{
+ size_t len, patlen;
+
+ assert (str != NULL);
+ assert (pat != NULL);
+
+ len = strlen (str);
+ patlen = strlen (pat);
+
+ if (patlen <= len)
+ {
+ str += len - patlen;
+ if (STREQ (str, pat))
+ *str = '\0';
+ }
+ return str;
+}
+
+void
+lt_debugprintf (const char *file, int line, const char *fmt, ...)
+{
+ va_list args;
+ if (lt_debug)
+ {
+ (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line);
+ va_start (args, fmt);
+ (void) vfprintf (stderr, fmt, args);
+ va_end (args);
+ }
+}
+
+static void
+lt_error_core (int exit_status, const char *file,
+ int line, const char *mode,
+ const char *message, va_list ap)
+{
+ fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode);
+ vfprintf (stderr, message, ap);
+ fprintf (stderr, ".\n");
+
+ if (exit_status >= 0)
+ exit (exit_status);
+}
+
+void
+lt_fatal (const char *file, int line, const char *message, ...)
+{
+ va_list ap;
+ va_start (ap, message);
+ lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap);
+ va_end (ap);
+}
+
+static const char *
+nonnull (const char *s)
+{
+ return s ? s : "(null)";
+}
+
+static const char *
+nonempty (const char *s)
+{
+ return (s && !*s) ? "(empty)" : nonnull (s);
+}
+
+void
+lt_setenv (const char *name, const char *value)
+{
+ lt_debugprintf (__FILE__, __LINE__,
+ "(lt_setenv) setting '%s' to '%s'\n",
+ nonnull (name), nonnull (value));
+ {
+#ifdef HAVE_SETENV
+ /* always make a copy, for consistency with !HAVE_SETENV */
+ char *str = xstrdup (value);
+ setenv (name, str, 1);
+#else
+ size_t len = strlen (name) + 1 + strlen (value) + 1;
+ char *str = XMALLOC (char, len);
+ sprintf (str, "%s=%s", name, value);
+ if (putenv (str) != EXIT_SUCCESS)
+ {
+ XFREE (str);
+ }
+#endif
+ }
+}
+
+char *
+lt_extend_str (const char *orig_value, const char *add, int to_end)
+{
+ char *new_value;
+ if (orig_value && *orig_value)
+ {
+ size_t orig_value_len = strlen (orig_value);
+ size_t add_len = strlen (add);
+ new_value = XMALLOC (char, add_len + orig_value_len + 1);
+ if (to_end)
+ {
+ strcpy (new_value, orig_value);
+ strcpy (new_value + orig_value_len, add);
+ }
+ else
+ {
+ strcpy (new_value, add);
+ strcpy (new_value + add_len, orig_value);
+ }
+ }
+ else
+ {
+ new_value = xstrdup (add);
+ }
+ return new_value;
+}
+
+void
+lt_update_exe_path (const char *name, const char *value)
+{
+ lt_debugprintf (__FILE__, __LINE__,
+ "(lt_update_exe_path) modifying '%s' by prepending '%s'\n",
+ nonnull (name), nonnull (value));
+
+ if (name && *name && value && *value)
+ {
+ char *new_value = lt_extend_str (getenv (name), value, 0);
+ /* some systems can't cope with a ':'-terminated path #' */
+ size_t len = strlen (new_value);
+ while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1]))
+ {
+ new_value[--len] = '\0';
+ }
+ lt_setenv (name, new_value);
+ XFREE (new_value);
+ }
+}
+
+void
+lt_update_lib_path (const char *name, const char *value)
+{
+ lt_debugprintf (__FILE__, __LINE__,
+ "(lt_update_lib_path) modifying '%s' by prepending '%s'\n",
+ nonnull (name), nonnull (value));
+
+ if (name && *name && value && *value)
+ {
+ char *new_value = lt_extend_str (getenv (name), value, 0);
+ lt_setenv (name, new_value);
+ XFREE (new_value);
+ }
+}
+
+EOF
+ case $host_os in
+ mingw*)
+ cat <<"EOF"
+
+/* Prepares an argument vector before calling spawn().
+ Note that spawn() does not by itself call the command interpreter
+ (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") :
+ ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ GetVersionEx(&v);
+ v.dwPlatformId == VER_PLATFORM_WIN32_NT;
+ }) ? "cmd.exe" : "command.com").
+ Instead it simply concatenates the arguments, separated by ' ', and calls
+ CreateProcess(). We must quote the arguments since Win32 CreateProcess()
+ interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a
+ special way:
+ - Space and tab are interpreted as delimiters. They are not treated as
+ delimiters if they are surrounded by double quotes: "...".
+ - Unescaped double quotes are removed from the input. Their only effect is
+ that within double quotes, space and tab are treated like normal
+ characters.
+ - Backslashes not followed by double quotes are not special.
+ - But 2*n+1 backslashes followed by a double quote become
+ n backslashes followed by a double quote (n >= 0):
+ \" -> "
+ \\\" -> \"
+ \\\\\" -> \\"
+ */
+#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
+#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
+char **
+prepare_spawn (char **argv)
+{
+ size_t argc;
+ char **new_argv;
+ size_t i;
+
+ /* Count number of arguments. */
+ for (argc = 0; argv[argc] != NULL; argc++)
+ ;
+
+ /* Allocate new argument vector. */
+ new_argv = XMALLOC (char *, argc + 1);
+
+ /* Put quoted arguments into the new argument vector. */
+ for (i = 0; i < argc; i++)
+ {
+ const char *string = argv[i];
+
+ if (string[0] == '\0')
+ new_argv[i] = xstrdup ("\"\"");
+ else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL)
+ {
+ int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL);
+ size_t length;
+ unsigned int backslashes;
+ const char *s;
+ char *quoted_string;
+ char *p;
+
+ length = 0;
+ backslashes = 0;
+ if (quote_around)
+ length++;
+ for (s = string; *s != '\0'; s++)
+ {
+ char c = *s;
+ if (c == '"')
+ length += backslashes + 1;
+ length++;
+ if (c == '\\')
+ backslashes++;
+ else
+ backslashes = 0;
+ }
+ if (quote_around)
+ length += backslashes + 1;
+
+ quoted_string = XMALLOC (char, length + 1);
+
+ p = quoted_string;
+ backslashes = 0;
+ if (quote_around)
+ *p++ = '"';
+ for (s = string; *s != '\0'; s++)
+ {
+ char c = *s;
+ if (c == '"')
+ {
+ unsigned int j;
+ for (j = backslashes + 1; j > 0; j--)
+ *p++ = '\\';
+ }
+ *p++ = c;
+ if (c == '\\')
+ backslashes++;
+ else
+ backslashes = 0;
+ }
+ if (quote_around)
+ {
+ unsigned int j;
+ for (j = backslashes; j > 0; j--)
+ *p++ = '\\';
+ *p++ = '"';
+ }
+ *p = '\0';
+
+ new_argv[i] = quoted_string;
+ }
+ else
+ new_argv[i] = (char *) string;
+ }
+ new_argv[argc] = NULL;
+
+ return new_argv;
+}
+EOF
+ ;;
+ esac
+
+ cat <<"EOF"
+void lt_dump_script (FILE* f)
+{
+EOF
+ func_emit_wrapper yes |
+ $SED -n -e '
+s/^\(.\{79\}\)\(..*\)/\1\
+\2/
+h
+s/\([\\"]\)/\\\1/g
+s/$/\\n/
+s/\([^\n]*\).*/ fputs ("\1", f);/p
+g
+D'
+ cat <<"EOF"
+}
+EOF
+}
+# end: func_emit_cwrapperexe_src
+
+# func_win32_import_lib_p ARG
+# True if ARG is an import lib, as indicated by $file_magic_cmd
+func_win32_import_lib_p ()
+{
+ $debug_cmd
+
+ case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in
+ *import*) : ;;
+ *) false ;;
+ esac
+}
+
+# func_suncc_cstd_abi
+# !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!!
+# Several compiler flags select an ABI that is incompatible with the
+# Cstd library. Avoid specifying it if any are in CXXFLAGS.
+func_suncc_cstd_abi ()
+{
+ $debug_cmd
+
+ case " $compile_command " in
+ *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*)
+ suncc_use_cstd_abi=no
+ ;;
+ *)
+ suncc_use_cstd_abi=yes
+ ;;
+ esac
+}
+
+# func_mode_link arg...
+func_mode_link ()
+{
+ $debug_cmd
+
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+ # It is impossible to link a dll without this setting, and
+ # we shouldn't force the makefile maintainer to figure out
+ # what system we are compiling for in order to pass an extra
+ # flag for every libtool invocation.
+ # allow_undefined=no
+
+ # FIXME: Unfortunately, there are problems with the above when trying
+ # to make a dll that has undefined symbols, in which case not
+ # even a static library is built. For now, we need to specify
+ # -no-undefined on the libtool link line when we can be certain
+ # that all symbols are satisfied, otherwise we get a static library.
+ allow_undefined=yes
+ ;;
+ *)
+ allow_undefined=yes
+ ;;
+ esac
+ libtool_args=$nonopt
+ base_compile="$nonopt $@"
+ compile_command=$nonopt
+ finalize_command=$nonopt
+
+ compile_rpath=
+ finalize_rpath=
+ compile_shlibpath=
+ finalize_shlibpath=
+ convenience=
+ old_convenience=
+ deplibs=
+ old_deplibs=
+ compiler_flags=
+ linker_flags=
+ dllsearchpath=
+ lib_search_path=`pwd`
+ inst_prefix_dir=
+ new_inherited_linker_flags=
+
+ avoid_version=no
+ bindir=
+ dlfiles=
+ dlprefiles=
+ dlself=no
+ export_dynamic=no
+ export_symbols=
+ export_symbols_regex=
+ generated=
+ libobjs=
+ ltlibs=
+ module=no
+ no_install=no
+ objs=
+ os2dllname=
+ non_pic_objects=
+ precious_files_regex=
+ prefer_static_libs=no
+ preload=false
+ prev=
+ prevarg=
+ release=
+ rpath=
+ xrpath=
+ perm_rpath=
+ temp_rpath=
+ thread_safe=no
+ vinfo=
+ vinfo_number=no
+ weak_libs=
+ single_module=$wl-single_module
+ func_infer_tag $base_compile
+
+ # We need to know -static, to get the right output filenames.
+ for arg
+ do
+ case $arg in
+ -shared)
+ test yes != "$build_libtool_libs" \
+ && func_fatal_configuration "cannot build a shared library"
+ build_old_libs=no
+ break
+ ;;
+ -all-static | -static | -static-libtool-libs)
+ case $arg in
+ -all-static)
+ if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then
+ func_warning "complete static linking is impossible in this configuration"
+ fi
+ if test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ prefer_static_libs=yes
+ ;;
+ -static)
+ if test -z "$pic_flag" && test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ prefer_static_libs=built
+ ;;
+ -static-libtool-libs)
+ if test -z "$pic_flag" && test -n "$link_static_flag"; then
+ dlopen_self=$dlopen_self_static
+ fi
+ prefer_static_libs=yes
+ ;;
+ esac
+ build_libtool_libs=no
+ build_old_libs=yes
+ break
+ ;;
+ esac
+ done
+
+ # See if our shared archives depend on static archives.
+ test -n "$old_archive_from_new_cmds" && build_old_libs=yes
+
+ # Go through the arguments, transforming them on the way.
+ while test "$#" -gt 0; do
+ arg=$1
+ shift
+ func_quote_for_eval "$arg"
+ qarg=$func_quote_for_eval_unquoted_result
+ func_append libtool_args " $func_quote_for_eval_result"
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$prev"; then
+ case $prev in
+ output)
+ func_append compile_command " @OUTPUT@"
+ func_append finalize_command " @OUTPUT@"
+ ;;
+ esac
+
+ case $prev in
+ bindir)
+ bindir=$arg
+ prev=
+ continue
+ ;;
+ dlfiles|dlprefiles)
+ $preload || {
+ # Add the symbol object into the linking commands.
+ func_append compile_command " @SYMFILE@"
+ func_append finalize_command " @SYMFILE@"
+ preload=:
+ }
+ case $arg in
+ *.la | *.lo) ;; # We handle these cases below.
+ force)
+ if test no = "$dlself"; then
+ dlself=needless
+ export_dynamic=yes
+ fi
+ prev=
+ continue
+ ;;
+ self)
+ if test dlprefiles = "$prev"; then
+ dlself=yes
+ elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then
+ dlself=yes
+ else
+ dlself=needless
+ export_dynamic=yes
+ fi
+ prev=
+ continue
+ ;;
+ *)
+ if test dlfiles = "$prev"; then
+ func_append dlfiles " $arg"
+ else
+ func_append dlprefiles " $arg"
+ fi
+ prev=
+ continue
+ ;;
+ esac
+ ;;
+ expsyms)
+ export_symbols=$arg
+ test -f "$arg" \
+ || func_fatal_error "symbol file '$arg' does not exist"
+ prev=
+ continue
+ ;;
+ expsyms_regex)
+ export_symbols_regex=$arg
+ prev=
+ continue
+ ;;
+ framework)
+ case $host in
+ *-*-darwin*)
+ case "$deplibs " in
+ *" $qarg.ltframework "*) ;;
+ *) func_append deplibs " $qarg.ltframework" # this is fixed later
+ ;;
+ esac
+ ;;
+ esac
+ prev=
+ continue
+ ;;
+ inst_prefix)
+ inst_prefix_dir=$arg
+ prev=
+ continue
+ ;;
+ mllvm)
+ # Clang does not use LLVM to link, so we can simply discard any
+ # '-mllvm $arg' options when doing the link step.
+ prev=
+ continue
+ ;;
+ objectlist)
+ if test -f "$arg"; then
+ save_arg=$arg
+ moreargs=
+ for fil in `cat "$save_arg"`
+ do
+# func_append moreargs " $fil"
+ arg=$fil
+ # A libtool-controlled object.
+
+ # Check to see that this really is a libtool object.
+ if func_lalib_unsafe_p "$arg"; then
+ pic_object=
+ non_pic_object=
+
+ # Read the .lo file
+ func_source "$arg"
+
+ if test -z "$pic_object" ||
+ test -z "$non_pic_object" ||
+ test none = "$pic_object" &&
+ test none = "$non_pic_object"; then
+ func_fatal_error "cannot find name of object for '$arg'"
+ fi
+
+ # Extract subdirectory from the argument.
+ func_dirname "$arg" "/" ""
+ xdir=$func_dirname_result
+
+ if test none != "$pic_object"; then
+ # Prepend the subdirectory the object is found in.
+ pic_object=$xdir$pic_object
+
+ if test dlfiles = "$prev"; then
+ if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then
+ func_append dlfiles " $pic_object"
+ prev=
+ continue
+ else
+ # If libtool objects are unsupported, then we need to preload.
+ prev=dlprefiles
+ fi
+ fi
+
+ # CHECK ME: I think I busted this. -Ossama
+ if test dlprefiles = "$prev"; then
+ # Preload the old-style object.
+ func_append dlprefiles " $pic_object"
+ prev=
+ fi
+
+ # A PIC object.
+ func_append libobjs " $pic_object"
+ arg=$pic_object
+ fi
+
+ # Non-PIC object.
+ if test none != "$non_pic_object"; then
+ # Prepend the subdirectory the object is found in.
+ non_pic_object=$xdir$non_pic_object
+
+ # A standard non-PIC object
+ func_append non_pic_objects " $non_pic_object"
+ if test -z "$pic_object" || test none = "$pic_object"; then
+ arg=$non_pic_object
+ fi
+ else
+ # If the PIC object exists, use it instead.
+ # $xdir was prepended to $pic_object above.
+ non_pic_object=$pic_object
+ func_append non_pic_objects " $non_pic_object"
+ fi
+ else
+ # Only an error if not doing a dry-run.
+ if $opt_dry_run; then
+ # Extract subdirectory from the argument.
+ func_dirname "$arg" "/" ""
+ xdir=$func_dirname_result
+
+ func_lo2o "$arg"
+ pic_object=$xdir$objdir/$func_lo2o_result
+ non_pic_object=$xdir$func_lo2o_result
+ func_append libobjs " $pic_object"
+ func_append non_pic_objects " $non_pic_object"
+ else
+ func_fatal_error "'$arg' is not a valid libtool object"
+ fi
+ fi
+ done
+ else
+ func_fatal_error "link input file '$arg' does not exist"
+ fi
+ arg=$save_arg
+ prev=
+ continue
+ ;;
+ os2dllname)
+ os2dllname=$arg
+ prev=
+ continue
+ ;;
+ precious_regex)
+ precious_files_regex=$arg
+ prev=
+ continue
+ ;;
+ release)
+ release=-$arg
+ prev=
+ continue
+ ;;
+ rpath | xrpath)
+ # We need an absolute path.
+ case $arg in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ func_fatal_error "only absolute run-paths are allowed"
+ ;;
+ esac
+ if test rpath = "$prev"; then
+ case "$rpath " in
+ *" $arg "*) ;;
+ *) func_append rpath " $arg" ;;
+ esac
+ else
+ case "$xrpath " in
+ *" $arg "*) ;;
+ *) func_append xrpath " $arg" ;;
+ esac
+ fi
+ prev=
+ continue
+ ;;
+ shrext)
+ shrext_cmds=$arg
+ prev=
+ continue
+ ;;
+ weak)
+ func_append weak_libs " $arg"
+ prev=
+ continue
+ ;;
+ xcclinker)
+ func_append linker_flags " $qarg"
+ func_append compiler_flags " $qarg"
+ prev=
+ func_append compile_command " $qarg"
+ func_append finalize_command " $qarg"
+ continue
+ ;;
+ xcompiler)
+ func_append compiler_flags " $qarg"
+ prev=
+ func_append compile_command " $qarg"
+ func_append finalize_command " $qarg"
+ continue
+ ;;
+ xlinker)
+ func_append linker_flags " $qarg"
+ func_append compiler_flags " $wl$qarg"
+ prev=
+ func_append compile_command " $wl$qarg"
+ func_append finalize_command " $wl$qarg"
+ continue
+ ;;
+ *)
+ eval "$prev=\"\$arg\""
+ prev=
+ continue
+ ;;
+ esac
+ fi # test -n "$prev"
+
+ prevarg=$arg
+
+ case $arg in
+ -all-static)
+ if test -n "$link_static_flag"; then
+ # See comment for -static flag below, for more details.
+ func_append compile_command " $link_static_flag"
+ func_append finalize_command " $link_static_flag"
+ fi
+ continue
+ ;;
+
+ -allow-undefined)
+ # FIXME: remove this flag sometime in the future.
+ func_fatal_error "'-allow-undefined' must not be used because it is the default"
+ ;;
+
+ -avoid-version)
+ avoid_version=yes
+ continue
+ ;;
+
+ -bindir)
+ prev=bindir
+ continue
+ ;;
+
+ -dlopen)
+ prev=dlfiles
+ continue
+ ;;
+
+ -dlpreopen)
+ prev=dlprefiles
+ continue
+ ;;
+
+ -export-dynamic)
+ export_dynamic=yes
+ continue
+ ;;
+
+ -export-symbols | -export-symbols-regex)
+ if test -n "$export_symbols" || test -n "$export_symbols_regex"; then
+ func_fatal_error "more than one -exported-symbols argument is not allowed"
+ fi
+ if test X-export-symbols = "X$arg"; then
+ prev=expsyms
+ else
+ prev=expsyms_regex
+ fi
+ continue
+ ;;
+
+ -framework)
+ prev=framework
+ continue
+ ;;
+
+ -inst-prefix-dir)
+ prev=inst_prefix
+ continue
+ ;;
+
+ # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:*
+ # so, if we see these flags be careful not to treat them like -L
+ -L[A-Z][A-Z]*:*)
+ case $with_gcc/$host in
+ no/*-*-irix* | /*-*-irix*)
+ func_append compile_command " $arg"
+ func_append finalize_command " $arg"
+ ;;
+ esac
+ continue
+ ;;
+
+ -L*)
+ func_stripname "-L" '' "$arg"
+ if test -z "$func_stripname_result"; then
+ if test "$#" -gt 0; then
+ func_fatal_error "require no space between '-L' and '$1'"
+ else
+ func_fatal_error "need path for '-L' option"
+ fi
+ fi
+ func_resolve_sysroot "$func_stripname_result"
+ dir=$func_resolve_sysroot_result
+ # We need an absolute path.
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ *)
+ absdir=`cd "$dir" && pwd`
+ test -z "$absdir" && \
+ func_fatal_error "cannot determine absolute directory name of '$dir'"
+ dir=$absdir
+ ;;
+ esac
+ case "$deplibs " in
+ *" -L$dir "* | *" $arg "*)
+ # Will only happen for absolute or sysroot arguments
+ ;;
+ *)
+ # Preserve sysroot, but never include relative directories
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;;
+ *) func_append deplibs " -L$dir" ;;
+ esac
+ func_append lib_search_path " $dir"
+ ;;
+ esac
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+ testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'`
+ case :$dllsearchpath: in
+ *":$dir:"*) ;;
+ ::) dllsearchpath=$dir;;
+ *) func_append dllsearchpath ":$dir";;
+ esac
+ case :$dllsearchpath: in
+ *":$testbindir:"*) ;;
+ ::) dllsearchpath=$testbindir;;
+ *) func_append dllsearchpath ":$testbindir";;
+ esac
+ ;;
+ esac
+ continue
+ ;;
+
+ -l*)
+ if test X-lc = "X$arg" || test X-lm = "X$arg"; then
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*)
+ # These systems don't actually have a C or math library (as such)
+ continue
+ ;;
+ *-*-os2*)
+ # These systems don't actually have a C library (as such)
+ test X-lc = "X$arg" && continue
+ ;;
+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*)
+ # Do not include libc due to us having libc/libc_r.
+ test X-lc = "X$arg" && continue
+ ;;
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # Rhapsody C and math libraries are in the System framework
+ func_append deplibs " System.ltframework"
+ continue
+ ;;
+ *-*-sco3.2v5* | *-*-sco5v6*)
+ # Causes problems with __ctype
+ test X-lc = "X$arg" && continue
+ ;;
+ *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+ # Compiler inserts libc in the correct place for threads to work
+ test X-lc = "X$arg" && continue
+ ;;
+ esac
+ elif test X-lc_r = "X$arg"; then
+ case $host in
+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*)
+ # Do not include libc_r directly, use -pthread flag.
+ continue
+ ;;
+ esac
+ fi
+ func_append deplibs " $arg"
+ continue
+ ;;
+
+ -mllvm)
+ prev=mllvm
+ continue
+ ;;
+
+ -module)
+ module=yes
+ continue
+ ;;
+
+ # Tru64 UNIX uses -model [arg] to determine the layout of C++
+ # classes, name mangling, and exception handling.
+ # Darwin uses the -arch flag to determine output architecture.
+ -model|-arch|-isysroot|--sysroot)
+ func_append compiler_flags " $arg"
+ func_append compile_command " $arg"
+ func_append finalize_command " $arg"
+ prev=xcompiler
+ continue
+ ;;
+
+ -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \
+ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*)
+ func_append compiler_flags " $arg"
+ func_append compile_command " $arg"
+ func_append finalize_command " $arg"
+ case "$new_inherited_linker_flags " in
+ *" $arg "*) ;;
+ * ) func_append new_inherited_linker_flags " $arg" ;;
+ esac
+ continue
+ ;;
+
+ -multi_module)
+ single_module=$wl-multi_module
+ continue
+ ;;
+
+ -no-fast-install)
+ fast_install=no
+ continue
+ ;;
+
+ -no-install)
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*)
+ # The PATH hackery in wrapper scripts is required on Windows
+ # and Darwin in order for the loader to find any dlls it needs.
+ func_warning "'-no-install' is ignored for $host"
+ func_warning "assuming '-no-fast-install' instead"
+ fast_install=no
+ ;;
+ *) no_install=yes ;;
+ esac
+ continue
+ ;;
+
+ -no-undefined)
+ allow_undefined=no
+ continue
+ ;;
+
+ -objectlist)
+ prev=objectlist
+ continue
+ ;;
+
+ -os2dllname)
+ prev=os2dllname
+ continue
+ ;;
+
+ -o) prev=output ;;
+
+ -precious-files-regex)
+ prev=precious_regex
+ continue
+ ;;
+
+ -release)
+ prev=release
+ continue
+ ;;
+
+ -rpath)
+ prev=rpath
+ continue
+ ;;
+
+ -R)
+ prev=xrpath
+ continue
+ ;;
+
+ -R*)
+ func_stripname '-R' '' "$arg"
+ dir=$func_stripname_result
+ # We need an absolute path.
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*) ;;
+ =*)
+ func_stripname '=' '' "$dir"
+ dir=$lt_sysroot$func_stripname_result
+ ;;
+ *)
+ func_fatal_error "only absolute run-paths are allowed"
+ ;;
+ esac
+ case "$xrpath " in
+ *" $dir "*) ;;
+ *) func_append xrpath " $dir" ;;
+ esac
+ continue
+ ;;
+
+ -shared)
+ # The effects of -shared are defined in a previous loop.
+ continue
+ ;;
+
+ -shrext)
+ prev=shrext
+ continue
+ ;;
+
+ -static | -static-libtool-libs)
+ # The effects of -static are defined in a previous loop.
+ # We used to do the same as -all-static on platforms that
+ # didn't have a PIC flag, but the assumption that the effects
+ # would be equivalent was wrong. It would break on at least
+ # Digital Unix and AIX.
+ continue
+ ;;
+
+ -thread-safe)
+ thread_safe=yes
+ continue
+ ;;
+
+ -version-info)
+ prev=vinfo
+ continue
+ ;;
+
+ -version-number)
+ prev=vinfo
+ vinfo_number=yes
+ continue
+ ;;
+
+ -weak)
+ prev=weak
+ continue
+ ;;
+
+ -Wc,*)
+ func_stripname '-Wc,' '' "$arg"
+ args=$func_stripname_result
+ arg=
+ save_ifs=$IFS; IFS=,
+ for flag in $args; do
+ IFS=$save_ifs
+ func_quote_for_eval "$flag"
+ func_append arg " $func_quote_for_eval_result"
+ func_append compiler_flags " $func_quote_for_eval_result"
+ done
+ IFS=$save_ifs
+ func_stripname ' ' '' "$arg"
+ arg=$func_stripname_result
+ ;;
+
+ -Wl,*)
+ func_stripname '-Wl,' '' "$arg"
+ args=$func_stripname_result
+ arg=
+ save_ifs=$IFS; IFS=,
+ for flag in $args; do
+ IFS=$save_ifs
+ func_quote_for_eval "$flag"
+ func_append arg " $wl$func_quote_for_eval_result"
+ func_append compiler_flags " $wl$func_quote_for_eval_result"
+ func_append linker_flags " $func_quote_for_eval_result"
+ done
+ IFS=$save_ifs
+ func_stripname ' ' '' "$arg"
+ arg=$func_stripname_result
+ ;;
+
+ -Xcompiler)
+ prev=xcompiler
+ continue
+ ;;
+
+ -Xlinker)
+ prev=xlinker
+ continue
+ ;;
+
+ -XCClinker)
+ prev=xcclinker
+ continue
+ ;;
+
+ # -msg_* for osf cc
+ -msg_*)
+ func_quote_for_eval "$arg"
+ arg=$func_quote_for_eval_result
+ ;;
+
+ # Flags to be passed through unchanged, with rationale:
+ # -64, -mips[0-9] enable 64-bit mode for the SGI compiler
+ # -r[0-9][0-9]* specify processor for the SGI compiler
+ # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler
+ # +DA*, +DD* enable 64-bit mode for the HP compiler
+ # -q* compiler args for the IBM compiler
+ # -m*, -t[45]*, -txscale* architecture-specific flags for GCC
+ # -F/path path to uninstalled frameworks, gcc on darwin
+ # -p, -pg, --coverage, -fprofile-* profiling flags for GCC
+ # -fstack-protector* stack protector flags for GCC
+ # @file GCC response files
+ # -tp=* Portland pgcc target processor selection
+ # --sysroot=* for sysroot support
+ # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization
+ # -specs=* GCC specs files
+ # -stdlib=* select c++ std lib with clang
+ -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \
+ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \
+ -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \
+ -specs=*)
+ func_quote_for_eval "$arg"
+ arg=$func_quote_for_eval_result
+ func_append compile_command " $arg"
+ func_append finalize_command " $arg"
+ func_append compiler_flags " $arg"
+ continue
+ ;;
+
+ -Z*)
+ if test os2 = "`expr $host : '.*\(os2\)'`"; then
+ # OS/2 uses -Zxxx to specify OS/2-specific options
+ compiler_flags="$compiler_flags $arg"
+ func_append compile_command " $arg"
+ func_append finalize_command " $arg"
+ case $arg in
+ -Zlinker | -Zstack)
+ prev=xcompiler
+ ;;
+ esac
+ continue
+ else
+ # Otherwise treat like 'Some other compiler flag' below
+ func_quote_for_eval "$arg"
+ arg=$func_quote_for_eval_result
+ fi
+ ;;
+
+ # Some other compiler flag.
+ -* | +*)
+ func_quote_for_eval "$arg"
+ arg=$func_quote_for_eval_result
+ ;;
+
+ *.$objext)
+ # A standard object.
+ func_append objs " $arg"
+ ;;
+
+ *.lo)
+ # A libtool-controlled object.
+
+ # Check to see that this really is a libtool object.
+ if func_lalib_unsafe_p "$arg"; then
+ pic_object=
+ non_pic_object=
+
+ # Read the .lo file
+ func_source "$arg"
+
+ if test -z "$pic_object" ||
+ test -z "$non_pic_object" ||
+ test none = "$pic_object" &&
+ test none = "$non_pic_object"; then
+ func_fatal_error "cannot find name of object for '$arg'"
+ fi
+
+ # Extract subdirectory from the argument.
+ func_dirname "$arg" "/" ""
+ xdir=$func_dirname_result
+
+ test none = "$pic_object" || {
+ # Prepend the subdirectory the object is found in.
+ pic_object=$xdir$pic_object
+
+ if test dlfiles = "$prev"; then
+ if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then
+ func_append dlfiles " $pic_object"
+ prev=
+ continue
+ else
+ # If libtool objects are unsupported, then we need to preload.
+ prev=dlprefiles
+ fi
+ fi
+
+ # CHECK ME: I think I busted this. -Ossama
+ if test dlprefiles = "$prev"; then
+ # Preload the old-style object.
+ func_append dlprefiles " $pic_object"
+ prev=
+ fi
+
+ # A PIC object.
+ func_append libobjs " $pic_object"
+ arg=$pic_object
+ }
+
+ # Non-PIC object.
+ if test none != "$non_pic_object"; then
+ # Prepend the subdirectory the object is found in.
+ non_pic_object=$xdir$non_pic_object
+
+ # A standard non-PIC object
+ func_append non_pic_objects " $non_pic_object"
+ if test -z "$pic_object" || test none = "$pic_object"; then
+ arg=$non_pic_object
+ fi
+ else
+ # If the PIC object exists, use it instead.
+ # $xdir was prepended to $pic_object above.
+ non_pic_object=$pic_object
+ func_append non_pic_objects " $non_pic_object"
+ fi
+ else
+ # Only an error if not doing a dry-run.
+ if $opt_dry_run; then
+ # Extract subdirectory from the argument.
+ func_dirname "$arg" "/" ""
+ xdir=$func_dirname_result
+
+ func_lo2o "$arg"
+ pic_object=$xdir$objdir/$func_lo2o_result
+ non_pic_object=$xdir$func_lo2o_result
+ func_append libobjs " $pic_object"
+ func_append non_pic_objects " $non_pic_object"
+ else
+ func_fatal_error "'$arg' is not a valid libtool object"
+ fi
+ fi
+ ;;
+
+ *.$libext)
+ # An archive.
+ func_append deplibs " $arg"
+ func_append old_deplibs " $arg"
+ continue
+ ;;
+
+ *.la)
+ # A libtool-controlled library.
+
+ func_resolve_sysroot "$arg"
+ if test dlfiles = "$prev"; then
+ # This library was specified with -dlopen.
+ func_append dlfiles " $func_resolve_sysroot_result"
+ prev=
+ elif test dlprefiles = "$prev"; then
+ # The library was specified with -dlpreopen.
+ func_append dlprefiles " $func_resolve_sysroot_result"
+ prev=
+ else
+ func_append deplibs " $func_resolve_sysroot_result"
+ fi
+ continue
+ ;;
+
+ # Some other compiler argument.
+ *)
+ # Unknown arguments in both finalize_command and compile_command need
+ # to be aesthetically quoted because they are evaled later.
+ func_quote_for_eval "$arg"
+ arg=$func_quote_for_eval_result
+ ;;
+ esac # arg
+
+ # Now actually substitute the argument into the commands.
+ if test -n "$arg"; then
+ func_append compile_command " $arg"
+ func_append finalize_command " $arg"
+ fi
+ done # argument parsing loop
+
+ test -n "$prev" && \
+ func_fatal_help "the '$prevarg' option requires an argument"
+
+ if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then
+ eval arg=\"$export_dynamic_flag_spec\"
+ func_append compile_command " $arg"
+ func_append finalize_command " $arg"
+ fi
+
+ oldlibs=
+ # calculate the name of the file, without its directory
+ func_basename "$output"
+ outputname=$func_basename_result
+ libobjs_save=$libobjs
+
+ if test -n "$shlibpath_var"; then
+ # get the directories listed in $shlibpath_var
+ eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\`
+ else
+ shlib_search_path=
+ fi
+ eval sys_lib_search_path=\"$sys_lib_search_path_spec\"
+ eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\"
+
+ # Definition is injected by LT_CONFIG during libtool generation.
+ func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH"
+
+ func_dirname "$output" "/" ""
+ output_objdir=$func_dirname_result$objdir
+ func_to_tool_file "$output_objdir/"
+ tool_output_objdir=$func_to_tool_file_result
+ # Create the object directory.
+ func_mkdir_p "$output_objdir"
+
+ # Determine the type of output
+ case $output in
+ "")
+ func_fatal_help "you must specify an output file"
+ ;;
+ *.$libext) linkmode=oldlib ;;
+ *.lo | *.$objext) linkmode=obj ;;
+ *.la) linkmode=lib ;;
+ *) linkmode=prog ;; # Anything else should be a program.
+ esac
+
+ specialdeplibs=
+
+ libs=
+ # Find all interdependent deplibs by searching for libraries
+ # that are linked more than once (e.g. -la -lb -la)
+ for deplib in $deplibs; do
+ if $opt_preserve_dup_deps; then
+ case "$libs " in
+ *" $deplib "*) func_append specialdeplibs " $deplib" ;;
+ esac
+ fi
+ func_append libs " $deplib"
+ done
+
+ if test lib = "$linkmode"; then
+ libs="$predeps $libs $compiler_lib_search_path $postdeps"
+
+ # Compute libraries that are listed more than once in $predeps
+ # $postdeps and mark them as special (i.e., whose duplicates are
+ # not to be eliminated).
+ pre_post_deps=
+ if $opt_duplicate_compiler_generated_deps; then
+ for pre_post_dep in $predeps $postdeps; do
+ case "$pre_post_deps " in
+ *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;;
+ esac
+ func_append pre_post_deps " $pre_post_dep"
+ done
+ fi
+ pre_post_deps=
+ fi
+
+ deplibs=
+ newdependency_libs=
+ newlib_search_path=
+ need_relink=no # whether we're linking any uninstalled libtool libraries
+ notinst_deplibs= # not-installed libtool libraries
+ notinst_path= # paths that contain not-installed libtool libraries
+
+ case $linkmode in
+ lib)
+ passes="conv dlpreopen link"
+ for file in $dlfiles $dlprefiles; do
+ case $file in
+ *.la) ;;
+ *)
+ func_fatal_help "libraries can '-dlopen' only libtool libraries: $file"
+ ;;
+ esac
+ done
+ ;;
+ prog)
+ compile_deplibs=
+ finalize_deplibs=
+ alldeplibs=false
+ newdlfiles=
+ newdlprefiles=
+ passes="conv scan dlopen dlpreopen link"
+ ;;
+ *) passes="conv"
+ ;;
+ esac
+
+ for pass in $passes; do
+ # The preopen pass in lib mode reverses $deplibs; put it back here
+ # so that -L comes before libs that need it for instance...
+ if test lib,link = "$linkmode,$pass"; then
+ ## FIXME: Find the place where the list is rebuilt in the wrong
+ ## order, and fix it there properly
+ tmp_deplibs=
+ for deplib in $deplibs; do
+ tmp_deplibs="$deplib $tmp_deplibs"
+ done
+ deplibs=$tmp_deplibs
+ fi
+
+ if test lib,link = "$linkmode,$pass" ||
+ test prog,scan = "$linkmode,$pass"; then
+ libs=$deplibs
+ deplibs=
+ fi
+ if test prog = "$linkmode"; then
+ case $pass in
+ dlopen) libs=$dlfiles ;;
+ dlpreopen) libs=$dlprefiles ;;
+ link) libs="$deplibs %DEPLIBS% $dependency_libs" ;;
+ esac
+ fi
+ if test lib,dlpreopen = "$linkmode,$pass"; then
+ # Collect and forward deplibs of preopened libtool libs
+ for lib in $dlprefiles; do
+ # Ignore non-libtool-libs
+ dependency_libs=
+ func_resolve_sysroot "$lib"
+ case $lib in
+ *.la) func_source "$func_resolve_sysroot_result" ;;
+ esac
+
+ # Collect preopened libtool deplibs, except any this library
+ # has declared as weak libs
+ for deplib in $dependency_libs; do
+ func_basename "$deplib"
+ deplib_base=$func_basename_result
+ case " $weak_libs " in
+ *" $deplib_base "*) ;;
+ *) func_append deplibs " $deplib" ;;
+ esac
+ done
+ done
+ libs=$dlprefiles
+ fi
+ if test dlopen = "$pass"; then
+ # Collect dlpreopened libraries
+ save_deplibs=$deplibs
+ deplibs=
+ fi
+
+ for deplib in $libs; do
+ lib=
+ found=false
+ case $deplib in
+ -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \
+ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*)
+ if test prog,link = "$linkmode,$pass"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ func_append compiler_flags " $deplib"
+ if test lib = "$linkmode"; then
+ case "$new_inherited_linker_flags " in
+ *" $deplib "*) ;;
+ * ) func_append new_inherited_linker_flags " $deplib" ;;
+ esac
+ fi
+ fi
+ continue
+ ;;
+ -l*)
+ if test lib != "$linkmode" && test prog != "$linkmode"; then
+ func_warning "'-l' is ignored for archives/objects"
+ continue
+ fi
+ func_stripname '-l' '' "$deplib"
+ name=$func_stripname_result
+ if test lib = "$linkmode"; then
+ searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path"
+ else
+ searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path"
+ fi
+ for searchdir in $searchdirs; do
+ for search_ext in .la $std_shrext .so .a; do
+ # Search the libtool library
+ lib=$searchdir/lib$name$search_ext
+ if test -f "$lib"; then
+ if test .la = "$search_ext"; then
+ found=:
+ else
+ found=false
+ fi
+ break 2
+ fi
+ done
+ done
+ if $found; then
+ # deplib is a libtool library
+ # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib,
+ # We need to do some special things here, and not later.
+ if test yes = "$allow_libtool_libs_with_static_runtimes"; then
+ case " $predeps $postdeps " in
+ *" $deplib "*)
+ if func_lalib_p "$lib"; then
+ library_names=
+ old_library=
+ func_source "$lib"
+ for l in $old_library $library_names; do
+ ll=$l
+ done
+ if test "X$ll" = "X$old_library"; then # only static version available
+ found=false
+ func_dirname "$lib" "" "."
+ ladir=$func_dirname_result
+ lib=$ladir/$old_library
+ if test prog,link = "$linkmode,$pass"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ deplibs="$deplib $deplibs"
+ test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs"
+ fi
+ continue
+ fi
+ fi
+ ;;
+ *) ;;
+ esac
+ fi
+ else
+ # deplib doesn't seem to be a libtool library
+ if test prog,link = "$linkmode,$pass"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ deplibs="$deplib $deplibs"
+ test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs"
+ fi
+ continue
+ fi
+ ;; # -l
+ *.ltframework)
+ if test prog,link = "$linkmode,$pass"; then
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ deplibs="$deplib $deplibs"
+ if test lib = "$linkmode"; then
+ case "$new_inherited_linker_flags " in
+ *" $deplib "*) ;;
+ * ) func_append new_inherited_linker_flags " $deplib" ;;
+ esac
+ fi
+ fi
+ continue
+ ;;
+ -L*)
+ case $linkmode in
+ lib)
+ deplibs="$deplib $deplibs"
+ test conv = "$pass" && continue
+ newdependency_libs="$deplib $newdependency_libs"
+ func_stripname '-L' '' "$deplib"
+ func_resolve_sysroot "$func_stripname_result"
+ func_append newlib_search_path " $func_resolve_sysroot_result"
+ ;;
+ prog)
+ if test conv = "$pass"; then
+ deplibs="$deplib $deplibs"
+ continue
+ fi
+ if test scan = "$pass"; then
+ deplibs="$deplib $deplibs"
+ else
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ fi
+ func_stripname '-L' '' "$deplib"
+ func_resolve_sysroot "$func_stripname_result"
+ func_append newlib_search_path " $func_resolve_sysroot_result"
+ ;;
+ *)
+ func_warning "'-L' is ignored for archives/objects"
+ ;;
+ esac # linkmode
+ continue
+ ;; # -L
+ -R*)
+ if test link = "$pass"; then
+ func_stripname '-R' '' "$deplib"
+ func_resolve_sysroot "$func_stripname_result"
+ dir=$func_resolve_sysroot_result
+ # Make sure the xrpath contains only unique directories.
+ case "$xrpath " in
+ *" $dir "*) ;;
+ *) func_append xrpath " $dir" ;;
+ esac
+ fi
+ deplibs="$deplib $deplibs"
+ continue
+ ;;
+ *.la)
+ func_resolve_sysroot "$deplib"
+ lib=$func_resolve_sysroot_result
+ ;;
+ *.$libext)
+ if test conv = "$pass"; then
+ deplibs="$deplib $deplibs"
+ continue
+ fi
+ case $linkmode in
+ lib)
+ # Linking convenience modules into shared libraries is allowed,
+ # but linking other static libraries is non-portable.
+ case " $dlpreconveniencelibs " in
+ *" $deplib "*) ;;
+ *)
+ valid_a_lib=false
+ case $deplibs_check_method in
+ match_pattern*)
+ set dummy $deplibs_check_method; shift
+ match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+ if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \
+ | $EGREP "$match_pattern_regex" > /dev/null; then
+ valid_a_lib=:
+ fi
+ ;;
+ pass_all)
+ valid_a_lib=:
+ ;;
+ esac
+ if $valid_a_lib; then
+ echo
+ $ECHO "*** Warning: Linking the shared library $output against the"
+ $ECHO "*** static library $deplib is not portable!"
+ deplibs="$deplib $deplibs"
+ else
+ echo
+ $ECHO "*** Warning: Trying to link with static lib archive $deplib."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which you do not appear to have"
+ echo "*** because the file extensions .$libext of this argument makes me believe"
+ echo "*** that it is just a static archive that I should not use here."
+ fi
+ ;;
+ esac
+ continue
+ ;;
+ prog)
+ if test link != "$pass"; then
+ deplibs="$deplib $deplibs"
+ else
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ fi
+ continue
+ ;;
+ esac # linkmode
+ ;; # *.$libext
+ *.lo | *.$objext)
+ if test conv = "$pass"; then
+ deplibs="$deplib $deplibs"
+ elif test prog = "$linkmode"; then
+ if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then
+ # If there is no dlopen support or we're linking statically,
+ # we need to preload.
+ func_append newdlprefiles " $deplib"
+ compile_deplibs="$deplib $compile_deplibs"
+ finalize_deplibs="$deplib $finalize_deplibs"
+ else
+ func_append newdlfiles " $deplib"
+ fi
+ fi
+ continue
+ ;;
+ %DEPLIBS%)
+ alldeplibs=:
+ continue
+ ;;
+ esac # case $deplib
+
+ $found || test -f "$lib" \
+ || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'"
+
+ # Check to see that this really is a libtool archive.
+ func_lalib_unsafe_p "$lib" \
+ || func_fatal_error "'$lib' is not a valid libtool archive"
+
+ func_dirname "$lib" "" "."
+ ladir=$func_dirname_result
+
+ dlname=
+ dlopen=
+ dlpreopen=
+ libdir=
+ library_names=
+ old_library=
+ inherited_linker_flags=
+ # If the library was installed with an old release of libtool,
+ # it will not redefine variables installed, or shouldnotlink
+ installed=yes
+ shouldnotlink=no
+ avoidtemprpath=
+
+
+ # Read the .la file
+ func_source "$lib"
+
+ # Convert "-framework foo" to "foo.ltframework"
+ if test -n "$inherited_linker_flags"; then
+ tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'`
+ for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do
+ case " $new_inherited_linker_flags " in
+ *" $tmp_inherited_linker_flag "*) ;;
+ *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";;
+ esac
+ done
+ fi
+ dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+ if test lib,link = "$linkmode,$pass" ||
+ test prog,scan = "$linkmode,$pass" ||
+ { test prog != "$linkmode" && test lib != "$linkmode"; }; then
+ test -n "$dlopen" && func_append dlfiles " $dlopen"
+ test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen"
+ fi
+
+ if test conv = "$pass"; then
+ # Only check for convenience libraries
+ deplibs="$lib $deplibs"
+ if test -z "$libdir"; then
+ if test -z "$old_library"; then
+ func_fatal_error "cannot find name of link library for '$lib'"
+ fi
+ # It is a libtool convenience library, so add in its objects.
+ func_append convenience " $ladir/$objdir/$old_library"
+ func_append old_convenience " $ladir/$objdir/$old_library"
+ elif test prog != "$linkmode" && test lib != "$linkmode"; then
+ func_fatal_error "'$lib' is not a convenience library"
+ fi
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ deplibs="$deplib $deplibs"
+ if $opt_preserve_dup_deps; then
+ case "$tmp_libs " in
+ *" $deplib "*) func_append specialdeplibs " $deplib" ;;
+ esac
+ fi
+ func_append tmp_libs " $deplib"
+ done
+ continue
+ fi # $pass = conv
+
+
+ # Get the name of the library we link against.
+ linklib=
+ if test -n "$old_library" &&
+ { test yes = "$prefer_static_libs" ||
+ test built,no = "$prefer_static_libs,$installed"; }; then
+ linklib=$old_library
+ else
+ for l in $old_library $library_names; do
+ linklib=$l
+ done
+ fi
+ if test -z "$linklib"; then
+ func_fatal_error "cannot find name of link library for '$lib'"
+ fi
+
+ # This library was specified with -dlopen.
+ if test dlopen = "$pass"; then
+ test -z "$libdir" \
+ && func_fatal_error "cannot -dlopen a convenience library: '$lib'"
+ if test -z "$dlname" ||
+ test yes != "$dlopen_support" ||
+ test no = "$build_libtool_libs"
+ then
+ # If there is no dlname, no dlopen support or we're linking
+ # statically, we need to preload. We also need to preload any
+ # dependent libraries so libltdl's deplib preloader doesn't
+ # bomb out in the load deplibs phase.
+ func_append dlprefiles " $lib $dependency_libs"
+ else
+ func_append newdlfiles " $lib"
+ fi
+ continue
+ fi # $pass = dlopen
+
+ # We need an absolute path.
+ case $ladir in
+ [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;;
+ *)
+ abs_ladir=`cd "$ladir" && pwd`
+ if test -z "$abs_ladir"; then
+ func_warning "cannot determine absolute directory name of '$ladir'"
+ func_warning "passing it literally to the linker, although it might fail"
+ abs_ladir=$ladir
+ fi
+ ;;
+ esac
+ func_basename "$lib"
+ laname=$func_basename_result
+
+ # Find the relevant object directory and library name.
+ if test yes = "$installed"; then
+ if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+ func_warning "library '$lib' was moved."
+ dir=$ladir
+ absdir=$abs_ladir
+ libdir=$abs_ladir
+ else
+ dir=$lt_sysroot$libdir
+ absdir=$lt_sysroot$libdir
+ fi
+ test yes = "$hardcode_automatic" && avoidtemprpath=yes
+ else
+ if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+ dir=$ladir
+ absdir=$abs_ladir
+ # Remove this search path later
+ func_append notinst_path " $abs_ladir"
+ else
+ dir=$ladir/$objdir
+ absdir=$abs_ladir/$objdir
+ # Remove this search path later
+ func_append notinst_path " $abs_ladir"
+ fi
+ fi # $installed = yes
+ func_stripname 'lib' '.la' "$laname"
+ name=$func_stripname_result
+
+ # This library was specified with -dlpreopen.
+ if test dlpreopen = "$pass"; then
+ if test -z "$libdir" && test prog = "$linkmode"; then
+ func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'"
+ fi
+ case $host in
+ # special handling for platforms with PE-DLLs.
+ *cygwin* | *mingw* | *cegcc* )
+ # Linker will automatically link against shared library if both
+ # static and shared are present. Therefore, ensure we extract
+ # symbols from the import library if a shared library is present
+ # (otherwise, the dlopen module name will be incorrect). We do
+ # this by putting the import library name into $newdlprefiles.
+ # We recover the dlopen module name by 'saving' the la file
+ # name in a special purpose variable, and (later) extracting the
+ # dlname from the la file.
+ if test -n "$dlname"; then
+ func_tr_sh "$dir/$linklib"
+ eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname"
+ func_append newdlprefiles " $dir/$linklib"
+ else
+ func_append newdlprefiles " $dir/$old_library"
+ # Keep a list of preopened convenience libraries to check
+ # that they are being used correctly in the link pass.
+ test -z "$libdir" && \
+ func_append dlpreconveniencelibs " $dir/$old_library"
+ fi
+ ;;
+ * )
+ # Prefer using a static library (so that no silly _DYNAMIC symbols
+ # are required to link).
+ if test -n "$old_library"; then
+ func_append newdlprefiles " $dir/$old_library"
+ # Keep a list of preopened convenience libraries to check
+ # that they are being used correctly in the link pass.
+ test -z "$libdir" && \
+ func_append dlpreconveniencelibs " $dir/$old_library"
+ # Otherwise, use the dlname, so that lt_dlopen finds it.
+ elif test -n "$dlname"; then
+ func_append newdlprefiles " $dir/$dlname"
+ else
+ func_append newdlprefiles " $dir/$linklib"
+ fi
+ ;;
+ esac
+ fi # $pass = dlpreopen
+
+ if test -z "$libdir"; then
+ # Link the convenience library
+ if test lib = "$linkmode"; then
+ deplibs="$dir/$old_library $deplibs"
+ elif test prog,link = "$linkmode,$pass"; then
+ compile_deplibs="$dir/$old_library $compile_deplibs"
+ finalize_deplibs="$dir/$old_library $finalize_deplibs"
+ else
+ deplibs="$lib $deplibs" # used for prog,scan pass
+ fi
+ continue
+ fi
+
+
+ if test prog = "$linkmode" && test link != "$pass"; then
+ func_append newlib_search_path " $ladir"
+ deplibs="$lib $deplibs"
+
+ linkalldeplibs=false
+ if test no != "$link_all_deplibs" || test -z "$library_names" ||
+ test no = "$build_libtool_libs"; then
+ linkalldeplibs=:
+ fi
+
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ case $deplib in
+ -L*) func_stripname '-L' '' "$deplib"
+ func_resolve_sysroot "$func_stripname_result"
+ func_append newlib_search_path " $func_resolve_sysroot_result"
+ ;;
+ esac
+ # Need to link against all dependency_libs?
+ if $linkalldeplibs; then
+ deplibs="$deplib $deplibs"
+ else
+ # Need to hardcode shared library paths
+ # or/and link against static libraries
+ newdependency_libs="$deplib $newdependency_libs"
+ fi
+ if $opt_preserve_dup_deps; then
+ case "$tmp_libs " in
+ *" $deplib "*) func_append specialdeplibs " $deplib" ;;
+ esac
+ fi
+ func_append tmp_libs " $deplib"
+ done # for deplib
+ continue
+ fi # $linkmode = prog...
+
+ if test prog,link = "$linkmode,$pass"; then
+ if test -n "$library_names" &&
+ { { test no = "$prefer_static_libs" ||
+ test built,yes = "$prefer_static_libs,$installed"; } ||
+ test -z "$old_library"; }; then
+ # We need to hardcode the library path
+ if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then
+ # Make sure the rpath contains only unique directories.
+ case $temp_rpath: in
+ *"$absdir:"*) ;;
+ *) func_append temp_rpath "$absdir:" ;;
+ esac
+ fi
+
+ # Hardcode the library path.
+ # Skip directories that are in the system default run-time
+ # search path.
+ case " $sys_lib_dlsearch_path " in
+ *" $absdir "*) ;;
+ *)
+ case "$compile_rpath " in
+ *" $absdir "*) ;;
+ *) func_append compile_rpath " $absdir" ;;
+ esac
+ ;;
+ esac
+ case " $sys_lib_dlsearch_path " in
+ *" $libdir "*) ;;
+ *)
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) func_append finalize_rpath " $libdir" ;;
+ esac
+ ;;
+ esac
+ fi # $linkmode,$pass = prog,link...
+
+ if $alldeplibs &&
+ { test pass_all = "$deplibs_check_method" ||
+ { test yes = "$build_libtool_libs" &&
+ test -n "$library_names"; }; }; then
+ # We only need to search for static libraries
+ continue
+ fi
+ fi
+
+ link_static=no # Whether the deplib will be linked statically
+ use_static_libs=$prefer_static_libs
+ if test built = "$use_static_libs" && test yes = "$installed"; then
+ use_static_libs=no
+ fi
+ if test -n "$library_names" &&
+ { test no = "$use_static_libs" || test -z "$old_library"; }; then
+ case $host in
+ *cygwin* | *mingw* | *cegcc* | *os2*)
+ # No point in relinking DLLs because paths are not encoded
+ func_append notinst_deplibs " $lib"
+ need_relink=no
+ ;;
+ *)
+ if test no = "$installed"; then
+ func_append notinst_deplibs " $lib"
+ need_relink=yes
+ fi
+ ;;
+ esac
+ # This is a shared library
+
+ # Warn about portability, can't link against -module's on some
+ # systems (darwin). Don't bleat about dlopened modules though!
+ dlopenmodule=
+ for dlpremoduletest in $dlprefiles; do
+ if test "X$dlpremoduletest" = "X$lib"; then
+ dlopenmodule=$dlpremoduletest
+ break
+ fi
+ done
+ if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then
+ echo
+ if test prog = "$linkmode"; then
+ $ECHO "*** Warning: Linking the executable $output against the loadable module"
+ else
+ $ECHO "*** Warning: Linking the shared library $output against the loadable module"
+ fi
+ $ECHO "*** $linklib is not portable!"
+ fi
+ if test lib = "$linkmode" &&
+ test yes = "$hardcode_into_libs"; then
+ # Hardcode the library path.
+ # Skip directories that are in the system default run-time
+ # search path.
+ case " $sys_lib_dlsearch_path " in
+ *" $absdir "*) ;;
+ *)
+ case "$compile_rpath " in
+ *" $absdir "*) ;;
+ *) func_append compile_rpath " $absdir" ;;
+ esac
+ ;;
+ esac
+ case " $sys_lib_dlsearch_path " in
+ *" $libdir "*) ;;
+ *)
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) func_append finalize_rpath " $libdir" ;;
+ esac
+ ;;
+ esac
+ fi
+
+ if test -n "$old_archive_from_expsyms_cmds"; then
+ # figure out the soname
+ set dummy $library_names
+ shift
+ realname=$1
+ shift
+ libname=`eval "\\$ECHO \"$libname_spec\""`
+ # use dlname if we got it. it's perfectly good, no?
+ if test -n "$dlname"; then
+ soname=$dlname
+ elif test -n "$soname_spec"; then
+ # bleh windows
+ case $host in
+ *cygwin* | mingw* | *cegcc* | *os2*)
+ func_arith $current - $age
+ major=$func_arith_result
+ versuffix=-$major
+ ;;
+ esac
+ eval soname=\"$soname_spec\"
+ else
+ soname=$realname
+ fi
+
+ # Make a new name for the extract_expsyms_cmds to use
+ soroot=$soname
+ func_basename "$soroot"
+ soname=$func_basename_result
+ func_stripname 'lib' '.dll' "$soname"
+ newlib=libimp-$func_stripname_result.a
+
+ # If the library has no export list, then create one now
+ if test -f "$output_objdir/$soname-def"; then :
+ else
+ func_verbose "extracting exported symbol list from '$soname'"
+ func_execute_cmds "$extract_expsyms_cmds" 'exit $?'
+ fi
+
+ # Create $newlib
+ if test -f "$output_objdir/$newlib"; then :; else
+ func_verbose "generating import library for '$soname'"
+ func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?'
+ fi
+ # make sure the library variables are pointing to the new library
+ dir=$output_objdir
+ linklib=$newlib
+ fi # test -n "$old_archive_from_expsyms_cmds"
+
+ if test prog = "$linkmode" || test relink != "$opt_mode"; then
+ add_shlibpath=
+ add_dir=
+ add=
+ lib_linked=yes
+ case $hardcode_action in
+ immediate | unsupported)
+ if test no = "$hardcode_direct"; then
+ add=$dir/$linklib
+ case $host in
+ *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;;
+ *-*-sysv4*uw2*) add_dir=-L$dir ;;
+ *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \
+ *-*-unixware7*) add_dir=-L$dir ;;
+ *-*-darwin* )
+ # if the lib is a (non-dlopened) module then we cannot
+ # link against it, someone is ignoring the earlier warnings
+ if /usr/bin/file -L $add 2> /dev/null |
+ $GREP ": [^:]* bundle" >/dev/null; then
+ if test "X$dlopenmodule" != "X$lib"; then
+ $ECHO "*** Warning: lib $linklib is a module, not a shared library"
+ if test -z "$old_library"; then
+ echo
+ echo "*** And there doesn't seem to be a static archive available"
+ echo "*** The link will probably fail, sorry"
+ else
+ add=$dir/$old_library
+ fi
+ elif test -n "$old_library"; then
+ add=$dir/$old_library
+ fi
+ fi
+ esac
+ elif test no = "$hardcode_minus_L"; then
+ case $host in
+ *-*-sunos*) add_shlibpath=$dir ;;
+ esac
+ add_dir=-L$dir
+ add=-l$name
+ elif test no = "$hardcode_shlibpath_var"; then
+ add_shlibpath=$dir
+ add=-l$name
+ else
+ lib_linked=no
+ fi
+ ;;
+ relink)
+ if test yes = "$hardcode_direct" &&
+ test no = "$hardcode_direct_absolute"; then
+ add=$dir/$linklib
+ elif test yes = "$hardcode_minus_L"; then
+ add_dir=-L$absdir
+ # Try looking first in the location we're being installed to.
+ if test -n "$inst_prefix_dir"; then
+ case $libdir in
+ [\\/]*)
+ func_append add_dir " -L$inst_prefix_dir$libdir"
+ ;;
+ esac
+ fi
+ add=-l$name
+ elif test yes = "$hardcode_shlibpath_var"; then
+ add_shlibpath=$dir
+ add=-l$name
+ else
+ lib_linked=no
+ fi
+ ;;
+ *) lib_linked=no ;;
+ esac
+
+ if test yes != "$lib_linked"; then
+ func_fatal_configuration "unsupported hardcode properties"
+ fi
+
+ if test -n "$add_shlibpath"; then
+ case :$compile_shlibpath: in
+ *":$add_shlibpath:"*) ;;
+ *) func_append compile_shlibpath "$add_shlibpath:" ;;
+ esac
+ fi
+ if test prog = "$linkmode"; then
+ test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs"
+ test -n "$add" && compile_deplibs="$add $compile_deplibs"
+ else
+ test -n "$add_dir" && deplibs="$add_dir $deplibs"
+ test -n "$add" && deplibs="$add $deplibs"
+ if test yes != "$hardcode_direct" &&
+ test yes != "$hardcode_minus_L" &&
+ test yes = "$hardcode_shlibpath_var"; then
+ case :$finalize_shlibpath: in
+ *":$libdir:"*) ;;
+ *) func_append finalize_shlibpath "$libdir:" ;;
+ esac
+ fi
+ fi
+ fi
+
+ if test prog = "$linkmode" || test relink = "$opt_mode"; then
+ add_shlibpath=
+ add_dir=
+ add=
+ # Finalize command for both is simple: just hardcode it.
+ if test yes = "$hardcode_direct" &&
+ test no = "$hardcode_direct_absolute"; then
+ add=$libdir/$linklib
+ elif test yes = "$hardcode_minus_L"; then
+ add_dir=-L$libdir
+ add=-l$name
+ elif test yes = "$hardcode_shlibpath_var"; then
+ case :$finalize_shlibpath: in
+ *":$libdir:"*) ;;
+ *) func_append finalize_shlibpath "$libdir:" ;;
+ esac
+ add=-l$name
+ elif test yes = "$hardcode_automatic"; then
+ if test -n "$inst_prefix_dir" &&
+ test -f "$inst_prefix_dir$libdir/$linklib"; then
+ add=$inst_prefix_dir$libdir/$linklib
+ else
+ add=$libdir/$linklib
+ fi
+ else
+ # We cannot seem to hardcode it, guess we'll fake it.
+ add_dir=-L$libdir
+ # Try looking first in the location we're being installed to.
+ if test -n "$inst_prefix_dir"; then
+ case $libdir in
+ [\\/]*)
+ func_append add_dir " -L$inst_prefix_dir$libdir"
+ ;;
+ esac
+ fi
+ add=-l$name
+ fi
+
+ if test prog = "$linkmode"; then
+ test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs"
+ test -n "$add" && finalize_deplibs="$add $finalize_deplibs"
+ else
+ test -n "$add_dir" && deplibs="$add_dir $deplibs"
+ test -n "$add" && deplibs="$add $deplibs"
+ fi
+ fi
+ elif test prog = "$linkmode"; then
+ # Here we assume that one of hardcode_direct or hardcode_minus_L
+ # is not unsupported. This is valid on all known static and
+ # shared platforms.
+ if test unsupported != "$hardcode_direct"; then
+ test -n "$old_library" && linklib=$old_library
+ compile_deplibs="$dir/$linklib $compile_deplibs"
+ finalize_deplibs="$dir/$linklib $finalize_deplibs"
+ else
+ compile_deplibs="-l$name -L$dir $compile_deplibs"
+ finalize_deplibs="-l$name -L$dir $finalize_deplibs"
+ fi
+ elif test yes = "$build_libtool_libs"; then
+ # Not a shared library
+ if test pass_all != "$deplibs_check_method"; then
+ # We're trying link a shared library against a static one
+ # but the system doesn't support it.
+
+ # Just print a warning and add the library to dependency_libs so
+ # that the program can be linked against the static library.
+ echo
+ $ECHO "*** Warning: This system cannot link to static lib archive $lib."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which you do not appear to have."
+ if test yes = "$module"; then
+ echo "*** But as you try to build a module library, libtool will still create "
+ echo "*** a static module, that should work as long as the dlopening application"
+ echo "*** is linked with the -dlopen flag to resolve symbols at runtime."
+ if test -z "$global_symbol_pipe"; then
+ echo
+ echo "*** However, this would only work if libtool was able to extract symbol"
+ echo "*** lists from a program, using 'nm' or equivalent, but libtool could"
+ echo "*** not find such a program. So, this module is probably useless."
+ echo "*** 'nm' from GNU binutils and a full rebuild may help."
+ fi
+ if test no = "$build_old_libs"; then
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ fi
+ else
+ deplibs="$dir/$old_library $deplibs"
+ link_static=yes
+ fi
+ fi # link shared/static library?
+
+ if test lib = "$linkmode"; then
+ if test -n "$dependency_libs" &&
+ { test yes != "$hardcode_into_libs" ||
+ test yes = "$build_old_libs" ||
+ test yes = "$link_static"; }; then
+ # Extract -R from dependency_libs
+ temp_deplibs=
+ for libdir in $dependency_libs; do
+ case $libdir in
+ -R*) func_stripname '-R' '' "$libdir"
+ temp_xrpath=$func_stripname_result
+ case " $xrpath " in
+ *" $temp_xrpath "*) ;;
+ *) func_append xrpath " $temp_xrpath";;
+ esac;;
+ *) func_append temp_deplibs " $libdir";;
+ esac
+ done
+ dependency_libs=$temp_deplibs
+ fi
+
+ func_append newlib_search_path " $absdir"
+ # Link against this library
+ test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs"
+ # ... and its dependency_libs
+ tmp_libs=
+ for deplib in $dependency_libs; do
+ newdependency_libs="$deplib $newdependency_libs"
+ case $deplib in
+ -L*) func_stripname '-L' '' "$deplib"
+ func_resolve_sysroot "$func_stripname_result";;
+ *) func_resolve_sysroot "$deplib" ;;
+ esac
+ if $opt_preserve_dup_deps; then
+ case "$tmp_libs " in
+ *" $func_resolve_sysroot_result "*)
+ func_append specialdeplibs " $func_resolve_sysroot_result" ;;
+ esac
+ fi
+ func_append tmp_libs " $func_resolve_sysroot_result"
+ done
+
+ if test no != "$link_all_deplibs"; then
+ # Add the search paths of all dependency libraries
+ for deplib in $dependency_libs; do
+ path=
+ case $deplib in
+ -L*) path=$deplib ;;
+ *.la)
+ func_resolve_sysroot "$deplib"
+ deplib=$func_resolve_sysroot_result
+ func_dirname "$deplib" "" "."
+ dir=$func_dirname_result
+ # We need an absolute path.
+ case $dir in
+ [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;;
+ *)
+ absdir=`cd "$dir" && pwd`
+ if test -z "$absdir"; then
+ func_warning "cannot determine absolute directory name of '$dir'"
+ absdir=$dir
+ fi
+ ;;
+ esac
+ if $GREP "^installed=no" $deplib > /dev/null; then
+ case $host in
+ *-*-darwin*)
+ depdepl=
+ eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib`
+ if test -n "$deplibrary_names"; then
+ for tmp in $deplibrary_names; do
+ depdepl=$tmp
+ done
+ if test -f "$absdir/$objdir/$depdepl"; then
+ depdepl=$absdir/$objdir/$depdepl
+ darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'`
+ if test -z "$darwin_install_name"; then
+ darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'`
+ fi
+ func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl"
+ func_append linker_flags " -dylib_file $darwin_install_name:$depdepl"
+ path=
+ fi
+ fi
+ ;;
+ *)
+ path=-L$absdir/$objdir
+ ;;
+ esac
+ else
+ eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib`
+ test -z "$libdir" && \
+ func_fatal_error "'$deplib' is not a valid libtool archive"
+ test "$absdir" != "$libdir" && \
+ func_warning "'$deplib' seems to be moved"
+
+ path=-L$absdir
+ fi
+ ;;
+ esac
+ case " $deplibs " in
+ *" $path "*) ;;
+ *) deplibs="$path $deplibs" ;;
+ esac
+ done
+ fi # link_all_deplibs != no
+ fi # linkmode = lib
+ done # for deplib in $libs
+ if test link = "$pass"; then
+ if test prog = "$linkmode"; then
+ compile_deplibs="$new_inherited_linker_flags $compile_deplibs"
+ finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs"
+ else
+ compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+ fi
+ fi
+ dependency_libs=$newdependency_libs
+ if test dlpreopen = "$pass"; then
+ # Link the dlpreopened libraries before other libraries
+ for deplib in $save_deplibs; do
+ deplibs="$deplib $deplibs"
+ done
+ fi
+ if test dlopen != "$pass"; then
+ test conv = "$pass" || {
+ # Make sure lib_search_path contains only unique directories.
+ lib_search_path=
+ for dir in $newlib_search_path; do
+ case "$lib_search_path " in
+ *" $dir "*) ;;
+ *) func_append lib_search_path " $dir" ;;
+ esac
+ done
+ newlib_search_path=
+ }
+
+ if test prog,link = "$linkmode,$pass"; then
+ vars="compile_deplibs finalize_deplibs"
+ else
+ vars=deplibs
+ fi
+ for var in $vars dependency_libs; do
+ # Add libraries to $var in reverse order
+ eval tmp_libs=\"\$$var\"
+ new_libs=
+ for deplib in $tmp_libs; do
+ # FIXME: Pedantically, this is the right thing to do, so
+ # that some nasty dependency loop isn't accidentally
+ # broken:
+ #new_libs="$deplib $new_libs"
+ # Pragmatically, this seems to cause very few problems in
+ # practice:
+ case $deplib in
+ -L*) new_libs="$deplib $new_libs" ;;
+ -R*) ;;
+ *)
+ # And here is the reason: when a library appears more
+ # than once as an explicit dependence of a library, or
+ # is implicitly linked in more than once by the
+ # compiler, it is considered special, and multiple
+ # occurrences thereof are not removed. Compare this
+ # with having the same library being listed as a
+ # dependency of multiple other libraries: in this case,
+ # we know (pedantically, we assume) the library does not
+ # need to be listed more than once, so we keep only the
+ # last copy. This is not always right, but it is rare
+ # enough that we require users that really mean to play
+ # such unportable linking tricks to link the library
+ # using -Wl,-lname, so that libtool does not consider it
+ # for duplicate removal.
+ case " $specialdeplibs " in
+ *" $deplib "*) new_libs="$deplib $new_libs" ;;
+ *)
+ case " $new_libs " in
+ *" $deplib "*) ;;
+ *) new_libs="$deplib $new_libs" ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ done
+ tmp_libs=
+ for deplib in $new_libs; do
+ case $deplib in
+ -L*)
+ case " $tmp_libs " in
+ *" $deplib "*) ;;
+ *) func_append tmp_libs " $deplib" ;;
+ esac
+ ;;
+ *) func_append tmp_libs " $deplib" ;;
+ esac
+ done
+ eval $var=\"$tmp_libs\"
+ done # for var
+ fi
+
+ # Add Sun CC postdeps if required:
+ test CXX = "$tagname" && {
+ case $host_os in
+ linux*)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*) # Sun C++ 5.9
+ func_suncc_cstd_abi
+
+ if test no != "$suncc_use_cstd_abi"; then
+ func_append postdeps ' -library=Cstd -library=Crun'
+ fi
+ ;;
+ esac
+ ;;
+
+ solaris*)
+ func_cc_basename "$CC"
+ case $func_cc_basename_result in
+ CC* | sunCC*)
+ func_suncc_cstd_abi
+
+ if test no != "$suncc_use_cstd_abi"; then
+ func_append postdeps ' -library=Cstd -library=Crun'
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ }
+
+ # Last step: remove runtime libs from dependency_libs
+ # (they stay in deplibs)
+ tmp_libs=
+ for i in $dependency_libs; do
+ case " $predeps $postdeps $compiler_lib_search_path " in
+ *" $i "*)
+ i=
+ ;;
+ esac
+ if test -n "$i"; then
+ func_append tmp_libs " $i"
+ fi
+ done
+ dependency_libs=$tmp_libs
+ done # for pass
+ if test prog = "$linkmode"; then
+ dlfiles=$newdlfiles
+ fi
+ if test prog = "$linkmode" || test lib = "$linkmode"; then
+ dlprefiles=$newdlprefiles
+ fi
+
+ case $linkmode in
+ oldlib)
+ if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then
+ func_warning "'-dlopen' is ignored for archives"
+ fi
+
+ case " $deplibs" in
+ *\ -l* | *\ -L*)
+ func_warning "'-l' and '-L' are ignored for archives" ;;
+ esac
+
+ test -n "$rpath" && \
+ func_warning "'-rpath' is ignored for archives"
+
+ test -n "$xrpath" && \
+ func_warning "'-R' is ignored for archives"
+
+ test -n "$vinfo" && \
+ func_warning "'-version-info/-version-number' is ignored for archives"
+
+ test -n "$release" && \
+ func_warning "'-release' is ignored for archives"
+
+ test -n "$export_symbols$export_symbols_regex" && \
+ func_warning "'-export-symbols' is ignored for archives"
+
+ # Now set the variables for building old libraries.
+ build_libtool_libs=no
+ oldlibs=$output
+ func_append objs "$old_deplibs"
+ ;;
+
+ lib)
+ # Make sure we only generate libraries of the form 'libNAME.la'.
+ case $outputname in
+ lib*)
+ func_stripname 'lib' '.la' "$outputname"
+ name=$func_stripname_result
+ eval shared_ext=\"$shrext_cmds\"
+ eval libname=\"$libname_spec\"
+ ;;
+ *)
+ test no = "$module" \
+ && func_fatal_help "libtool library '$output' must begin with 'lib'"
+
+ if test no != "$need_lib_prefix"; then
+ # Add the "lib" prefix for modules if required
+ func_stripname '' '.la' "$outputname"
+ name=$func_stripname_result
+ eval shared_ext=\"$shrext_cmds\"
+ eval libname=\"$libname_spec\"
+ else
+ func_stripname '' '.la' "$outputname"
+ libname=$func_stripname_result
+ fi
+ ;;
+ esac
+
+ if test -n "$objs"; then
+ if test pass_all != "$deplibs_check_method"; then
+ func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs"
+ else
+ echo
+ $ECHO "*** Warning: Linking the shared library $output against the non-libtool"
+ $ECHO "*** objects $objs is not portable!"
+ func_append libobjs " $objs"
+ fi
+ fi
+
+ test no = "$dlself" \
+ || func_warning "'-dlopen self' is ignored for libtool libraries"
+
+ set dummy $rpath
+ shift
+ test 1 -lt "$#" \
+ && func_warning "ignoring multiple '-rpath's for a libtool library"
+
+ install_libdir=$1
+
+ oldlibs=
+ if test -z "$rpath"; then
+ if test yes = "$build_libtool_libs"; then
+ # Building a libtool convenience library.
+ # Some compilers have problems with a '.al' extension so
+ # convenience libraries should have the same extension an
+ # archive normally would.
+ oldlibs="$output_objdir/$libname.$libext $oldlibs"
+ build_libtool_libs=convenience
+ build_old_libs=yes
+ fi
+
+ test -n "$vinfo" && \
+ func_warning "'-version-info/-version-number' is ignored for convenience libraries"
+
+ test -n "$release" && \
+ func_warning "'-release' is ignored for convenience libraries"
+ else
+
+ # Parse the version information argument.
+ save_ifs=$IFS; IFS=:
+ set dummy $vinfo 0 0 0
+ shift
+ IFS=$save_ifs
+
+ test -n "$7" && \
+ func_fatal_help "too many parameters to '-version-info'"
+
+ # convert absolute version numbers to libtool ages
+ # this retains compatibility with .la files and attempts
+ # to make the code below a bit more comprehensible
+
+ case $vinfo_number in
+ yes)
+ number_major=$1
+ number_minor=$2
+ number_revision=$3
+ #
+ # There are really only two kinds -- those that
+ # use the current revision as the major version
+ # and those that subtract age and use age as
+ # a minor version. But, then there is irix
+ # that has an extra 1 added just for fun
+ #
+ case $version_type in
+ # correct linux to gnu/linux during the next big refactor
+ darwin|freebsd-elf|linux|osf|windows|none)
+ func_arith $number_major + $number_minor
+ current=$func_arith_result
+ age=$number_minor
+ revision=$number_revision
+ ;;
+ freebsd-aout|qnx|sunos)
+ current=$number_major
+ revision=$number_minor
+ age=0
+ ;;
+ irix|nonstopux)
+ func_arith $number_major + $number_minor
+ current=$func_arith_result
+ age=$number_minor
+ revision=$number_minor
+ lt_irix_increment=no
+ ;;
+ esac
+ ;;
+ no)
+ current=$1
+ revision=$2
+ age=$3
+ ;;
+ esac
+
+ # Check that each of the things are valid numbers.
+ case $current in
+ 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+ *)
+ func_error "CURRENT '$current' must be a nonnegative integer"
+ func_fatal_error "'$vinfo' is not valid version information"
+ ;;
+ esac
+
+ case $revision in
+ 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+ *)
+ func_error "REVISION '$revision' must be a nonnegative integer"
+ func_fatal_error "'$vinfo' is not valid version information"
+ ;;
+ esac
+
+ case $age in
+ 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
+ *)
+ func_error "AGE '$age' must be a nonnegative integer"
+ func_fatal_error "'$vinfo' is not valid version information"
+ ;;
+ esac
+
+ if test "$age" -gt "$current"; then
+ func_error "AGE '$age' is greater than the current interface number '$current'"
+ func_fatal_error "'$vinfo' is not valid version information"
+ fi
+
+ # Calculate the version variables.
+ major=
+ versuffix=
+ verstring=
+ case $version_type in
+ none) ;;
+
+ darwin)
+ # Like Linux, but with the current version available in
+ # verstring for coding it into the library header
+ func_arith $current - $age
+ major=.$func_arith_result
+ versuffix=$major.$age.$revision
+ # Darwin ld doesn't like 0 for these options...
+ func_arith $current + 1
+ minor_current=$func_arith_result
+ xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision"
+ verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
+ # On Darwin other compilers
+ case $CC in
+ nagfor*)
+ verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision"
+ ;;
+ *)
+ verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
+ ;;
+ esac
+ ;;
+
+ freebsd-aout)
+ major=.$current
+ versuffix=.$current.$revision
+ ;;
+
+ freebsd-elf)
+ func_arith $current - $age
+ major=.$func_arith_result
+ versuffix=$major.$age.$revision
+ ;;
+
+ irix | nonstopux)
+ if test no = "$lt_irix_increment"; then
+ func_arith $current - $age
+ else
+ func_arith $current - $age + 1
+ fi
+ major=$func_arith_result
+
+ case $version_type in
+ nonstopux) verstring_prefix=nonstopux ;;
+ *) verstring_prefix=sgi ;;
+ esac
+ verstring=$verstring_prefix$major.$revision
+
+ # Add in all the interfaces that we are compatible with.
+ loop=$revision
+ while test 0 -ne "$loop"; do
+ func_arith $revision - $loop
+ iface=$func_arith_result
+ func_arith $loop - 1
+ loop=$func_arith_result
+ verstring=$verstring_prefix$major.$iface:$verstring
+ done
+
+ # Before this point, $major must not contain '.'.
+ major=.$major
+ versuffix=$major.$revision
+ ;;
+
+ linux) # correct to gnu/linux during the next big refactor
+ func_arith $current - $age
+ major=.$func_arith_result
+ versuffix=$major.$age.$revision
+ ;;
+
+ osf)
+ func_arith $current - $age
+ major=.$func_arith_result
+ versuffix=.$current.$age.$revision
+ verstring=$current.$age.$revision
+
+ # Add in all the interfaces that we are compatible with.
+ loop=$age
+ while test 0 -ne "$loop"; do
+ func_arith $current - $loop
+ iface=$func_arith_result
+ func_arith $loop - 1
+ loop=$func_arith_result
+ verstring=$verstring:$iface.0
+ done
+
+ # Make executables depend on our current version.
+ func_append verstring ":$current.0"
+ ;;
+
+ qnx)
+ major=.$current
+ versuffix=.$current
+ ;;
+
+ sco)
+ major=.$current
+ versuffix=.$current
+ ;;
+
+ sunos)
+ major=.$current
+ versuffix=.$current.$revision
+ ;;
+
+ windows)
+ # Use '-' rather than '.', since we only want one
+ # extension on DOS 8.3 file systems.
+ func_arith $current - $age
+ major=$func_arith_result
+ versuffix=-$major
+ ;;
+
+ *)
+ func_fatal_configuration "unknown library version type '$version_type'"
+ ;;
+ esac
+
+ # Clear the version info if we defaulted, and they specified a release.
+ if test -z "$vinfo" && test -n "$release"; then
+ major=
+ case $version_type in
+ darwin)
+ # we can't check for "0.0" in archive_cmds due to quoting
+ # problems, so we reset it completely
+ verstring=
+ ;;
+ *)
+ verstring=0.0
+ ;;
+ esac
+ if test no = "$need_version"; then
+ versuffix=
+ else
+ versuffix=.0.0
+ fi
+ fi
+
+ # Remove version info from name if versioning should be avoided
+ if test yes,no = "$avoid_version,$need_version"; then
+ major=
+ versuffix=
+ verstring=
+ fi
+
+ # Check to see if the archive will have undefined symbols.
+ if test yes = "$allow_undefined"; then
+ if test unsupported = "$allow_undefined_flag"; then
+ if test yes = "$build_old_libs"; then
+ func_warning "undefined symbols not allowed in $host shared libraries; building static only"
+ build_libtool_libs=no
+ else
+ func_fatal_error "can't build $host shared library unless -no-undefined is specified"
+ fi
+ fi
+ else
+ # Don't allow undefined symbols.
+ allow_undefined_flag=$no_undefined_flag
+ fi
+
+ fi
+
+ func_generate_dlsyms "$libname" "$libname" :
+ func_append libobjs " $symfileobj"
+ test " " = "$libobjs" && libobjs=
+
+ if test relink != "$opt_mode"; then
+ # Remove our outputs, but don't remove object files since they
+ # may have been created when compiling PIC objects.
+ removelist=
+ tempremovelist=`$ECHO "$output_objdir/*"`
+ for p in $tempremovelist; do
+ case $p in
+ *.$objext | *.gcno)
+ ;;
+ $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*)
+ if test -n "$precious_files_regex"; then
+ if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1
+ then
+ continue
+ fi
+ fi
+ func_append removelist " $p"
+ ;;
+ *) ;;
+ esac
+ done
+ test -n "$removelist" && \
+ func_show_eval "${RM}r \$removelist"
+ fi
+
+ # Now set the variables for building old libraries.
+ if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then
+ func_append oldlibs " $output_objdir/$libname.$libext"
+
+ # Transform .lo files to .o files.
+ oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP`
+ fi
+
+ # Eliminate all temporary directories.
+ #for path in $notinst_path; do
+ # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"`
+ # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"`
+ # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"`
+ #done
+
+ if test -n "$xrpath"; then
+ # If the user specified any rpath flags, then add them.
+ temp_xrpath=
+ for libdir in $xrpath; do
+ func_replace_sysroot "$libdir"
+ func_append temp_xrpath " -R$func_replace_sysroot_result"
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) func_append finalize_rpath " $libdir" ;;
+ esac
+ done
+ if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then
+ dependency_libs="$temp_xrpath $dependency_libs"
+ fi
+ fi
+
+ # Make sure dlfiles contains only unique files that won't be dlpreopened
+ old_dlfiles=$dlfiles
+ dlfiles=
+ for lib in $old_dlfiles; do
+ case " $dlprefiles $dlfiles " in
+ *" $lib "*) ;;
+ *) func_append dlfiles " $lib" ;;
+ esac
+ done
+
+ # Make sure dlprefiles contains only unique files
+ old_dlprefiles=$dlprefiles
+ dlprefiles=
+ for lib in $old_dlprefiles; do
+ case "$dlprefiles " in
+ *" $lib "*) ;;
+ *) func_append dlprefiles " $lib" ;;
+ esac
+ done
+
+ if test yes = "$build_libtool_libs"; then
+ if test -n "$rpath"; then
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*)
+ # these systems don't actually have a c library (as such)!
+ ;;
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # Rhapsody C library is in the System framework
+ func_append deplibs " System.ltframework"
+ ;;
+ *-*-netbsd*)
+ # Don't link with libc until the a.out ld.so is fixed.
+ ;;
+ *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+ # Do not include libc due to us having libc/libc_r.
+ ;;
+ *-*-sco3.2v5* | *-*-sco5v6*)
+ # Causes problems with __ctype
+ ;;
+ *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+ # Compiler inserts libc in the correct place for threads to work
+ ;;
+ *)
+ # Add libc to deplibs on all other systems if necessary.
+ if test yes = "$build_libtool_need_lc"; then
+ func_append deplibs " -lc"
+ fi
+ ;;
+ esac
+ fi
+
+ # Transform deplibs into only deplibs that can be linked in shared.
+ name_save=$name
+ libname_save=$libname
+ release_save=$release
+ versuffix_save=$versuffix
+ major_save=$major
+ # I'm not sure if I'm treating the release correctly. I think
+ # release should show up in the -l (ie -lgmp5) so we don't want to
+ # add it in twice. Is that correct?
+ release=
+ versuffix=
+ major=
+ newdeplibs=
+ droppeddeps=no
+ case $deplibs_check_method in
+ pass_all)
+ # Don't check for shared/static. Everything works.
+ # This might be a little naive. We might want to check
+ # whether the library exists or not. But this is on
+ # osf3 & osf4 and I'm not really sure... Just
+ # implementing what was already the behavior.
+ newdeplibs=$deplibs
+ ;;
+ test_compile)
+ # This code stresses the "libraries are programs" paradigm to its
+ # limits. Maybe even breaks it. We compile a program, linking it
+ # against the deplibs as a proxy for the library. Then we can check
+ # whether they linked in statically or dynamically with ldd.
+ $opt_dry_run || $RM conftest.c
+ cat > conftest.c <<EOF
+ int main() { return 0; }
+EOF
+ $opt_dry_run || $RM conftest
+ if $LTCC $LTCFLAGS -o conftest conftest.c $deplibs; then
+ ldd_output=`ldd conftest`
+ for i in $deplibs; do
+ case $i in
+ -l*)
+ func_stripname -l '' "$i"
+ name=$func_stripname_result
+ if test yes = "$allow_libtool_libs_with_static_runtimes"; then
+ case " $predeps $postdeps " in
+ *" $i "*)
+ func_append newdeplibs " $i"
+ i=
+ ;;
+ esac
+ fi
+ if test -n "$i"; then
+ libname=`eval "\\$ECHO \"$libname_spec\""`
+ deplib_matches=`eval "\\$ECHO \"$library_names_spec\""`
+ set dummy $deplib_matches; shift
+ deplib_match=$1
+ if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0; then
+ func_append newdeplibs " $i"
+ else
+ droppeddeps=yes
+ echo
+ $ECHO "*** Warning: dynamic linker does not accept needed library $i."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which I believe you do not have"
+ echo "*** because a test_compile did reveal that the linker did not use it for"
+ echo "*** its dynamic dependency list that programs get resolved with at runtime."
+ fi
+ fi
+ ;;
+ *)
+ func_append newdeplibs " $i"
+ ;;
+ esac
+ done
+ else
+ # Error occurred in the first compile. Let's try to salvage
+ # the situation: Compile a separate program for each library.
+ for i in $deplibs; do
+ case $i in
+ -l*)
+ func_stripname -l '' "$i"
+ name=$func_stripname_result
+ $opt_dry_run || $RM conftest
+ if $LTCC $LTCFLAGS -o conftest conftest.c $i; then
+ ldd_output=`ldd conftest`
+ if test yes = "$allow_libtool_libs_with_static_runtimes"; then
+ case " $predeps $postdeps " in
+ *" $i "*)
+ func_append newdeplibs " $i"
+ i=
+ ;;
+ esac
+ fi
+ if test -n "$i"; then
+ libname=`eval "\\$ECHO \"$libname_spec\""`
+ deplib_matches=`eval "\\$ECHO \"$library_names_spec\""`
+ set dummy $deplib_matches; shift
+ deplib_match=$1
+ if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0; then
+ func_append newdeplibs " $i"
+ else
+ droppeddeps=yes
+ echo
+ $ECHO "*** Warning: dynamic linker does not accept needed library $i."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which you do not appear to have"
+ echo "*** because a test_compile did reveal that the linker did not use this one"
+ echo "*** as a dynamic dependency that programs can get resolved with at runtime."
+ fi
+ fi
+ else
+ droppeddeps=yes
+ echo
+ $ECHO "*** Warning! Library $i is needed by this library but I was not able to"
+ echo "*** make it link in! You will probably need to install it or some"
+ echo "*** library that it depends on before this library will be fully"
+ echo "*** functional. Installing it before continuing would be even better."
+ fi
+ ;;
+ *)
+ func_append newdeplibs " $i"
+ ;;
+ esac
+ done
+ fi
+ ;;
+ file_magic*)
+ set dummy $deplibs_check_method; shift
+ file_magic_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+ for a_deplib in $deplibs; do
+ case $a_deplib in
+ -l*)
+ func_stripname -l '' "$a_deplib"
+ name=$func_stripname_result
+ if test yes = "$allow_libtool_libs_with_static_runtimes"; then
+ case " $predeps $postdeps " in
+ *" $a_deplib "*)
+ func_append newdeplibs " $a_deplib"
+ a_deplib=
+ ;;
+ esac
+ fi
+ if test -n "$a_deplib"; then
+ libname=`eval "\\$ECHO \"$libname_spec\""`
+ if test -n "$file_magic_glob"; then
+ libnameglob=`func_echo_all "$libname" | $SED -e $file_magic_glob`
+ else
+ libnameglob=$libname
+ fi
+ test yes = "$want_nocaseglob" && nocaseglob=`shopt -p nocaseglob`
+ for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+ if test yes = "$want_nocaseglob"; then
+ shopt -s nocaseglob
+ potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null`
+ $nocaseglob
+ else
+ potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null`
+ fi
+ for potent_lib in $potential_libs; do
+ # Follow soft links.
+ if ls -lLd "$potent_lib" 2>/dev/null |
+ $GREP " -> " >/dev/null; then
+ continue
+ fi
+ # The statement above tries to avoid entering an
+ # endless loop below, in case of cyclic links.
+ # We might still enter an endless loop, since a link
+ # loop can be closed while we follow links,
+ # but so what?
+ potlib=$potent_lib
+ while test -h "$potlib" 2>/dev/null; do
+ potliblink=`ls -ld $potlib | $SED 's/.* -> //'`
+ case $potliblink in
+ [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;;
+ *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";;
+ esac
+ done
+ if eval $file_magic_cmd \"\$potlib\" 2>/dev/null |
+ $SED -e 10q |
+ $EGREP "$file_magic_regex" > /dev/null; then
+ func_append newdeplibs " $a_deplib"
+ a_deplib=
+ break 2
+ fi
+ done
+ done
+ fi
+ if test -n "$a_deplib"; then
+ droppeddeps=yes
+ echo
+ $ECHO "*** Warning: linker path does not have real file for library $a_deplib."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which you do not appear to have"
+ echo "*** because I did check the linker path looking for a file starting"
+ if test -z "$potlib"; then
+ $ECHO "*** with $libname but no candidates were found. (...for file magic test)"
+ else
+ $ECHO "*** with $libname and none of the candidates passed a file format test"
+ $ECHO "*** using a file magic. Last file checked: $potlib"
+ fi
+ fi
+ ;;
+ *)
+ # Add a -L argument.
+ func_append newdeplibs " $a_deplib"
+ ;;
+ esac
+ done # Gone through all deplibs.
+ ;;
+ match_pattern*)
+ set dummy $deplibs_check_method; shift
+ match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"`
+ for a_deplib in $deplibs; do
+ case $a_deplib in
+ -l*)
+ func_stripname -l '' "$a_deplib"
+ name=$func_stripname_result
+ if test yes = "$allow_libtool_libs_with_static_runtimes"; then
+ case " $predeps $postdeps " in
+ *" $a_deplib "*)
+ func_append newdeplibs " $a_deplib"
+ a_deplib=
+ ;;
+ esac
+ fi
+ if test -n "$a_deplib"; then
+ libname=`eval "\\$ECHO \"$libname_spec\""`
+ for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do
+ potential_libs=`ls $i/$libname[.-]* 2>/dev/null`
+ for potent_lib in $potential_libs; do
+ potlib=$potent_lib # see symlink-check above in file_magic test
+ if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \
+ $EGREP "$match_pattern_regex" > /dev/null; then
+ func_append newdeplibs " $a_deplib"
+ a_deplib=
+ break 2
+ fi
+ done
+ done
+ fi
+ if test -n "$a_deplib"; then
+ droppeddeps=yes
+ echo
+ $ECHO "*** Warning: linker path does not have real file for library $a_deplib."
+ echo "*** I have the capability to make that library automatically link in when"
+ echo "*** you link to this library. But I can only do this if you have a"
+ echo "*** shared version of the library, which you do not appear to have"
+ echo "*** because I did check the linker path looking for a file starting"
+ if test -z "$potlib"; then
+ $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)"
+ else
+ $ECHO "*** with $libname and none of the candidates passed a file format test"
+ $ECHO "*** using a regex pattern. Last file checked: $potlib"
+ fi
+ fi
+ ;;
+ *)
+ # Add a -L argument.
+ func_append newdeplibs " $a_deplib"
+ ;;
+ esac
+ done # Gone through all deplibs.
+ ;;
+ none | unknown | *)
+ newdeplibs=
+ tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'`
+ if test yes = "$allow_libtool_libs_with_static_runtimes"; then
+ for i in $predeps $postdeps; do
+ # can't use Xsed below, because $i might contain '/'
+ tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"`
+ done
+ fi
+ case $tmp_deplibs in
+ *[!\ \ ]*)
+ echo
+ if test none = "$deplibs_check_method"; then
+ echo "*** Warning: inter-library dependencies are not supported in this platform."
+ else
+ echo "*** Warning: inter-library dependencies are not known to be supported."
+ fi
+ echo "*** All declared inter-library dependencies are being dropped."
+ droppeddeps=yes
+ ;;
+ esac
+ ;;
+ esac
+ versuffix=$versuffix_save
+ major=$major_save
+ release=$release_save
+ libname=$libname_save
+ name=$name_save
+
+ case $host in
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # On Rhapsody replace the C library with the System framework
+ newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'`
+ ;;
+ esac
+
+ if test yes = "$droppeddeps"; then
+ if test yes = "$module"; then
+ echo
+ echo "*** Warning: libtool could not satisfy all declared inter-library"
+ $ECHO "*** dependencies of module $libname. Therefore, libtool will create"
+ echo "*** a static module, that should work as long as the dlopening"
+ echo "*** application is linked with the -dlopen flag."
+ if test -z "$global_symbol_pipe"; then
+ echo
+ echo "*** However, this would only work if libtool was able to extract symbol"
+ echo "*** lists from a program, using 'nm' or equivalent, but libtool could"
+ echo "*** not find such a program. So, this module is probably useless."
+ echo "*** 'nm' from GNU binutils and a full rebuild may help."
+ fi
+ if test no = "$build_old_libs"; then
+ oldlibs=$output_objdir/$libname.$libext
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ else
+ echo "*** The inter-library dependencies that have been dropped here will be"
+ echo "*** automatically added whenever a program is linked with this library"
+ echo "*** or is declared to -dlopen it."
+
+ if test no = "$allow_undefined"; then
+ echo
+ echo "*** Since this library must not contain undefined symbols,"
+ echo "*** because either the platform does not support them or"
+ echo "*** it was explicitly requested with -no-undefined,"
+ echo "*** libtool will only create a static version of it."
+ if test no = "$build_old_libs"; then
+ oldlibs=$output_objdir/$libname.$libext
+ build_libtool_libs=module
+ build_old_libs=yes
+ else
+ build_libtool_libs=no
+ fi
+ fi
+ fi
+ fi
+ # Done checking deplibs!
+ deplibs=$newdeplibs
+ fi
+ # Time to change all our "foo.ltframework" stuff back to "-framework foo"
+ case $host in
+ *-*-darwin*)
+ newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+ new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+ deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+ ;;
+ esac
+
+ # move library search paths that coincide with paths to not yet
+ # installed libraries to the beginning of the library search list
+ new_libs=
+ for path in $notinst_path; do
+ case " $new_libs " in
+ *" -L$path/$objdir "*) ;;
+ *)
+ case " $deplibs " in
+ *" -L$path/$objdir "*)
+ func_append new_libs " -L$path/$objdir" ;;
+ esac
+ ;;
+ esac
+ done
+ for deplib in $deplibs; do
+ case $deplib in
+ -L*)
+ case " $new_libs " in
+ *" $deplib "*) ;;
+ *) func_append new_libs " $deplib" ;;
+ esac
+ ;;
+ *) func_append new_libs " $deplib" ;;
+ esac
+ done
+ deplibs=$new_libs
+
+ # All the library-specific variables (install_libdir is set above).
+ library_names=
+ old_library=
+ dlname=
+
+ # Test again, we may have decided not to build it any more
+ if test yes = "$build_libtool_libs"; then
+ # Remove $wl instances when linking with ld.
+ # FIXME: should test the right _cmds variable.
+ case $archive_cmds in
+ *\$LD\ *) wl= ;;
+ esac
+ if test yes = "$hardcode_into_libs"; then
+ # Hardcode the library paths
+ hardcode_libdirs=
+ dep_rpath=
+ rpath=$finalize_rpath
+ test relink = "$opt_mode" || rpath=$compile_rpath$rpath
+ for libdir in $rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ func_replace_sysroot "$libdir"
+ libdir=$func_replace_sysroot_result
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs=$libdir
+ else
+ # Just accumulate the unique libdirs.
+ case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ func_append hardcode_libdirs "$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ func_append dep_rpath " $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$perm_rpath " in
+ *" $libdir "*) ;;
+ *) func_append perm_rpath " $libdir" ;;
+ esac
+ fi
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir=$hardcode_libdirs
+ eval "dep_rpath=\"$hardcode_libdir_flag_spec\""
+ fi
+ if test -n "$runpath_var" && test -n "$perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $perm_rpath; do
+ func_append rpath "$dir:"
+ done
+ eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var"
+ fi
+ test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs"
+ fi
+
+ shlibpath=$finalize_shlibpath
+ test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath
+ if test -n "$shlibpath"; then
+ eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var"
+ fi
+
+ # Get the real and link names of the library.
+ eval shared_ext=\"$shrext_cmds\"
+ eval library_names=\"$library_names_spec\"
+ set dummy $library_names
+ shift
+ realname=$1
+ shift
+
+ if test -n "$soname_spec"; then
+ eval soname=\"$soname_spec\"
+ else
+ soname=$realname
+ fi
+ if test -z "$dlname"; then
+ dlname=$soname
+ fi
+
+ lib=$output_objdir/$realname
+ linknames=
+ for link
+ do
+ func_append linknames " $link"
+ done
+
+ # Use standard objects if they are pic
+ test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP`
+ test "X$libobjs" = "X " && libobjs=
+
+ delfiles=
+ if test -n "$export_symbols" && test -n "$include_expsyms"; then
+ $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp"
+ export_symbols=$output_objdir/$libname.uexp
+ func_append delfiles " $export_symbols"
+ fi
+
+ orig_export_symbols=
+ case $host_os in
+ cygwin* | mingw* | cegcc*)
+ if test -n "$export_symbols" && test -z "$export_symbols_regex"; then
+ # exporting using user supplied symfile
+ func_dll_def_p "$export_symbols" || {
+ # and it's NOT already a .def file. Must figure out
+ # which of the given symbols are data symbols and tag
+ # them as such. So, trigger use of export_symbols_cmds.
+ # export_symbols gets reassigned inside the "prepare
+ # the list of exported symbols" if statement, so the
+ # include_expsyms logic still works.
+ orig_export_symbols=$export_symbols
+ export_symbols=
+ always_export_symbols=yes
+ }
+ fi
+ ;;
+ esac
+
+ # Prepare the list of exported symbols
+ if test -z "$export_symbols"; then
+ if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then
+ func_verbose "generating symbol list for '$libname.la'"
+ export_symbols=$output_objdir/$libname.exp
+ $opt_dry_run || $RM $export_symbols
+ cmds=$export_symbols_cmds
+ save_ifs=$IFS; IFS='~'
+ for cmd1 in $cmds; do
+ IFS=$save_ifs
+ # Take the normal branch if the nm_file_list_spec branch
+ # doesn't work or if tool conversion is not needed.
+ case $nm_file_list_spec~$to_tool_file_cmd in
+ *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*)
+ try_normal_branch=yes
+ eval cmd=\"$cmd1\"
+ func_len " $cmd"
+ len=$func_len_result
+ ;;
+ *)
+ try_normal_branch=no
+ ;;
+ esac
+ if test yes = "$try_normal_branch" \
+ && { test "$len" -lt "$max_cmd_len" \
+ || test "$max_cmd_len" -le -1; }
+ then
+ func_show_eval "$cmd" 'exit $?'
+ skipped_export=false
+ elif test -n "$nm_file_list_spec"; then
+ func_basename "$output"
+ output_la=$func_basename_result
+ save_libobjs=$libobjs
+ save_output=$output
+ output=$output_objdir/$output_la.nm
+ func_to_tool_file "$output"
+ libobjs=$nm_file_list_spec$func_to_tool_file_result
+ func_append delfiles " $output"
+ func_verbose "creating $NM input file list: $output"
+ for obj in $save_libobjs; do
+ func_to_tool_file "$obj"
+ $ECHO "$func_to_tool_file_result"
+ done > "$output"
+ eval cmd=\"$cmd1\"
+ func_show_eval "$cmd" 'exit $?'
+ output=$save_output
+ libobjs=$save_libobjs
+ skipped_export=false
+ else
+ # The command line is too long to execute in one step.
+ func_verbose "using reloadable object file for export list..."
+ skipped_export=:
+ # Break out early, otherwise skipped_export may be
+ # set to false by a later but shorter cmd.
+ break
+ fi
+ done
+ IFS=$save_ifs
+ if test -n "$export_symbols_regex" && test : != "$skipped_export"; then
+ func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+ func_show_eval '$MV "${export_symbols}T" "$export_symbols"'
+ fi
+ fi
+ fi
+
+ if test -n "$export_symbols" && test -n "$include_expsyms"; then
+ tmp_export_symbols=$export_symbols
+ test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols
+ $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"'
+ fi
+
+ if test : != "$skipped_export" && test -n "$orig_export_symbols"; then
+ # The given exports_symbols file has to be filtered, so filter it.
+ func_verbose "filter symbol list for '$libname.la' to tag DATA exports"
+ # FIXME: $output_objdir/$libname.filter potentially contains lots of
+ # 's' commands, which not all seds can handle. GNU sed should be fine
+ # though. Also, the filter scales superlinearly with the number of
+ # global variables. join(1) would be nice here, but unfortunately
+ # isn't a blessed tool.
+ $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
+ func_append delfiles " $export_symbols $output_objdir/$libname.filter"
+ export_symbols=$output_objdir/$libname.def
+ $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
+ fi
+
+ tmp_deplibs=
+ for test_deplib in $deplibs; do
+ case " $convenience " in
+ *" $test_deplib "*) ;;
+ *)
+ func_append tmp_deplibs " $test_deplib"
+ ;;
+ esac
+ done
+ deplibs=$tmp_deplibs
+
+ if test -n "$convenience"; then
+ if test -n "$whole_archive_flag_spec" &&
+ test yes = "$compiler_needs_object" &&
+ test -z "$libobjs"; then
+ # extract the archives, so we have objects to list.
+ # TODO: could optimize this to just extract one archive.
+ whole_archive_flag_spec=
+ fi
+ if test -n "$whole_archive_flag_spec"; then
+ save_libobjs=$libobjs
+ eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+ test "X$libobjs" = "X " && libobjs=
+ else
+ gentop=$output_objdir/${outputname}x
+ func_append generated " $gentop"
+
+ func_extract_archives $gentop $convenience
+ func_append libobjs " $func_extract_archives_result"
+ test "X$libobjs" = "X " && libobjs=
+ fi
+ fi
+
+ if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then
+ eval flag=\"$thread_safe_flag_spec\"
+ func_append linker_flags " $flag"
+ fi
+
+ # Make a backup of the uninstalled library when relinking
+ if test relink = "$opt_mode"; then
+ $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $?
+ fi
+
+ # Do each of the archive commands.
+ if test yes = "$module" && test -n "$module_cmds"; then
+ if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+ eval test_cmds=\"$module_expsym_cmds\"
+ cmds=$module_expsym_cmds
+ else
+ eval test_cmds=\"$module_cmds\"
+ cmds=$module_cmds
+ fi
+ else
+ if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+ eval test_cmds=\"$archive_expsym_cmds\"
+ cmds=$archive_expsym_cmds
+ else
+ eval test_cmds=\"$archive_cmds\"
+ cmds=$archive_cmds
+ fi
+ fi
+
+ if test : != "$skipped_export" &&
+ func_len " $test_cmds" &&
+ len=$func_len_result &&
+ test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+ :
+ else
+ # The command line is too long to link in one step, link piecewise
+ # or, if using GNU ld and skipped_export is not :, use a linker
+ # script.
+
+ # Save the value of $output and $libobjs because we want to
+ # use them later. If we have whole_archive_flag_spec, we
+ # want to use save_libobjs as it was before
+ # whole_archive_flag_spec was expanded, because we can't
+ # assume the linker understands whole_archive_flag_spec.
+ # This may have to be revisited, in case too many
+ # convenience libraries get linked in and end up exceeding
+ # the spec.
+ if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then
+ save_libobjs=$libobjs
+ fi
+ save_output=$output
+ func_basename "$output"
+ output_la=$func_basename_result
+
+ # Clear the reloadable object creation command queue and
+ # initialize k to one.
+ test_cmds=
+ concat_cmds=
+ objlist=
+ last_robj=
+ k=1
+
+ if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then
+ output=$output_objdir/$output_la.lnkscript
+ func_verbose "creating GNU ld script: $output"
+ echo 'INPUT (' > $output
+ for obj in $save_libobjs
+ do
+ func_to_tool_file "$obj"
+ $ECHO "$func_to_tool_file_result" >> $output
+ done
+ echo ')' >> $output
+ func_append delfiles " $output"
+ func_to_tool_file "$output"
+ output=$func_to_tool_file_result
+ elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then
+ output=$output_objdir/$output_la.lnk
+ func_verbose "creating linker input file list: $output"
+ : > $output
+ set x $save_libobjs
+ shift
+ firstobj=
+ if test yes = "$compiler_needs_object"; then
+ firstobj="$1 "
+ shift
+ fi
+ for obj
+ do
+ func_to_tool_file "$obj"
+ $ECHO "$func_to_tool_file_result" >> $output
+ done
+ func_append delfiles " $output"
+ func_to_tool_file "$output"
+ output=$firstobj\"$file_list_spec$func_to_tool_file_result\"
+ else
+ if test -n "$save_libobjs"; then
+ func_verbose "creating reloadable object files..."
+ output=$output_objdir/$output_la-$k.$objext
+ eval test_cmds=\"$reload_cmds\"
+ func_len " $test_cmds"
+ len0=$func_len_result
+ len=$len0
+
+ # Loop over the list of objects to be linked.
+ for obj in $save_libobjs
+ do
+ func_len " $obj"
+ func_arith $len + $func_len_result
+ len=$func_arith_result
+ if test -z "$objlist" ||
+ test "$len" -lt "$max_cmd_len"; then
+ func_append objlist " $obj"
+ else
+ # The command $test_cmds is almost too long, add a
+ # command to the queue.
+ if test 1 -eq "$k"; then
+ # The first file doesn't have a previous command to add.
+ reload_objs=$objlist
+ eval concat_cmds=\"$reload_cmds\"
+ else
+ # All subsequent reloadable object files will link in
+ # the last one created.
+ reload_objs="$objlist $last_robj"
+ eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\"
+ fi
+ last_robj=$output_objdir/$output_la-$k.$objext
+ func_arith $k + 1
+ k=$func_arith_result
+ output=$output_objdir/$output_la-$k.$objext
+ objlist=" $obj"
+ func_len " $last_robj"
+ func_arith $len0 + $func_len_result
+ len=$func_arith_result
+ fi
+ done
+ # Handle the remaining objects by creating one last
+ # reloadable object file. All subsequent reloadable object
+ # files will link in the last one created.
+ test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+ reload_objs="$objlist $last_robj"
+ eval concat_cmds=\"\$concat_cmds$reload_cmds\"
+ if test -n "$last_robj"; then
+ eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\"
+ fi
+ func_append delfiles " $output"
+
+ else
+ output=
+ fi
+
+ ${skipped_export-false} && {
+ func_verbose "generating symbol list for '$libname.la'"
+ export_symbols=$output_objdir/$libname.exp
+ $opt_dry_run || $RM $export_symbols
+ libobjs=$output
+ # Append the command to create the export file.
+ test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+ eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\"
+ if test -n "$last_robj"; then
+ eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\"
+ fi
+ }
+
+ test -n "$save_libobjs" &&
+ func_verbose "creating a temporary reloadable object file: $output"
+
+ # Loop through the commands generated above and execute them.
+ save_ifs=$IFS; IFS='~'
+ for cmd in $concat_cmds; do
+ IFS=$save_ifs
+ $opt_quiet || {
+ func_quote_for_expand "$cmd"
+ eval "func_echo $func_quote_for_expand_result"
+ }
+ $opt_dry_run || eval "$cmd" || {
+ lt_exit=$?
+
+ # Restore the uninstalled library and exit
+ if test relink = "$opt_mode"; then
+ ( cd "$output_objdir" && \
+ $RM "${realname}T" && \
+ $MV "${realname}U" "$realname" )
+ fi
+
+ exit $lt_exit
+ }
+ done
+ IFS=$save_ifs
+
+ if test -n "$export_symbols_regex" && ${skipped_export-false}; then
+ func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"'
+ func_show_eval '$MV "${export_symbols}T" "$export_symbols"'
+ fi
+ fi
+
+ ${skipped_export-false} && {
+ if test -n "$export_symbols" && test -n "$include_expsyms"; then
+ tmp_export_symbols=$export_symbols
+ test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols
+ $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"'
+ fi
+
+ if test -n "$orig_export_symbols"; then
+ # The given exports_symbols file has to be filtered, so filter it.
+ func_verbose "filter symbol list for '$libname.la' to tag DATA exports"
+ # FIXME: $output_objdir/$libname.filter potentially contains lots of
+ # 's' commands, which not all seds can handle. GNU sed should be fine
+ # though. Also, the filter scales superlinearly with the number of
+ # global variables. join(1) would be nice here, but unfortunately
+ # isn't a blessed tool.
+ $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter
+ func_append delfiles " $export_symbols $output_objdir/$libname.filter"
+ export_symbols=$output_objdir/$libname.def
+ $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols
+ fi
+ }
+
+ libobjs=$output
+ # Restore the value of output.
+ output=$save_output
+
+ if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then
+ eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
+ test "X$libobjs" = "X " && libobjs=
+ fi
+ # Expand the library linking commands again to reset the
+ # value of $libobjs for piecewise linking.
+
+ # Do each of the archive commands.
+ if test yes = "$module" && test -n "$module_cmds"; then
+ if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then
+ cmds=$module_expsym_cmds
+ else
+ cmds=$module_cmds
+ fi
+ else
+ if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then
+ cmds=$archive_expsym_cmds
+ else
+ cmds=$archive_cmds
+ fi
+ fi
+ fi
+
+ if test -n "$delfiles"; then
+ # Append the command to remove temporary files to $cmds.
+ eval cmds=\"\$cmds~\$RM $delfiles\"
+ fi
+
+ # Add any objects from preloaded convenience libraries
+ if test -n "$dlprefiles"; then
+ gentop=$output_objdir/${outputname}x
+ func_append generated " $gentop"
+
+ func_extract_archives $gentop $dlprefiles
+ func_append libobjs " $func_extract_archives_result"
+ test "X$libobjs" = "X " && libobjs=
+ fi
+
+ save_ifs=$IFS; IFS='~'
+ for cmd in $cmds; do
+ IFS=$sp$nl
+ eval cmd=\"$cmd\"
+ IFS=$save_ifs
+ $opt_quiet || {
+ func_quote_for_expand "$cmd"
+ eval "func_echo $func_quote_for_expand_result"
+ }
+ $opt_dry_run || eval "$cmd" || {
+ lt_exit=$?
+
+ # Restore the uninstalled library and exit
+ if test relink = "$opt_mode"; then
+ ( cd "$output_objdir" && \
+ $RM "${realname}T" && \
+ $MV "${realname}U" "$realname" )
+ fi
+
+ exit $lt_exit
+ }
+ done
+ IFS=$save_ifs
+
+ # Restore the uninstalled library and exit
+ if test relink = "$opt_mode"; then
+ $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $?
+
+ if test -n "$convenience"; then
+ if test -z "$whole_archive_flag_spec"; then
+ func_show_eval '${RM}r "$gentop"'
+ fi
+ fi
+
+ exit $EXIT_SUCCESS
+ fi
+
+ # Create links to the real library.
+ for linkname in $linknames; do
+ if test "$realname" != "$linkname"; then
+ func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?'
+ fi
+ done
+
+ # If -module or -export-dynamic was specified, set the dlname.
+ if test yes = "$module" || test yes = "$export_dynamic"; then
+ # On all known operating systems, these are identical.
+ dlname=$soname
+ fi
+ fi
+ ;;
+
+ obj)
+ if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then
+ func_warning "'-dlopen' is ignored for objects"
+ fi
+
+ case " $deplibs" in
+ *\ -l* | *\ -L*)
+ func_warning "'-l' and '-L' are ignored for objects" ;;
+ esac
+
+ test -n "$rpath" && \
+ func_warning "'-rpath' is ignored for objects"
+
+ test -n "$xrpath" && \
+ func_warning "'-R' is ignored for objects"
+
+ test -n "$vinfo" && \
+ func_warning "'-version-info' is ignored for objects"
+
+ test -n "$release" && \
+ func_warning "'-release' is ignored for objects"
+
+ case $output in
+ *.lo)
+ test -n "$objs$old_deplibs" && \
+ func_fatal_error "cannot build library object '$output' from non-libtool objects"
+
+ libobj=$output
+ func_lo2o "$libobj"
+ obj=$func_lo2o_result
+ ;;
+ *)
+ libobj=
+ obj=$output
+ ;;
+ esac
+
+ # Delete the old objects.
+ $opt_dry_run || $RM $obj $libobj
+
+ # Objects from convenience libraries. This assumes
+ # single-version convenience libraries. Whenever we create
+ # different ones for PIC/non-PIC, this we'll have to duplicate
+ # the extraction.
+ reload_conv_objs=
+ gentop=
+ # if reload_cmds runs $LD directly, get rid of -Wl from
+ # whole_archive_flag_spec and hope we can get by with turning comma
+ # into space.
+ case $reload_cmds in
+ *\$LD[\ \$]*) wl= ;;
+ esac
+ if test -n "$convenience"; then
+ if test -n "$whole_archive_flag_spec"; then
+ eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\"
+ test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'`
+ reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags
+ else
+ gentop=$output_objdir/${obj}x
+ func_append generated " $gentop"
+
+ func_extract_archives $gentop $convenience
+ reload_conv_objs="$reload_objs $func_extract_archives_result"
+ fi
+ fi
+
+ # If we're not building shared, we need to use non_pic_objs
+ test yes = "$build_libtool_libs" || libobjs=$non_pic_objects
+
+ # Create the old-style object.
+ reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs
+
+ output=$obj
+ func_execute_cmds "$reload_cmds" 'exit $?'
+
+ # Exit if we aren't doing a library object file.
+ if test -z "$libobj"; then
+ if test -n "$gentop"; then
+ func_show_eval '${RM}r "$gentop"'
+ fi
+
+ exit $EXIT_SUCCESS
+ fi
+
+ test yes = "$build_libtool_libs" || {
+ if test -n "$gentop"; then
+ func_show_eval '${RM}r "$gentop"'
+ fi
+
+ # Create an invalid libtool object if no PIC, so that we don't
+ # accidentally link it into a program.
+ # $show "echo timestamp > $libobj"
+ # $opt_dry_run || eval "echo timestamp > $libobj" || exit $?
+ exit $EXIT_SUCCESS
+ }
+
+ if test -n "$pic_flag" || test default != "$pic_mode"; then
+ # Only do commands if we really have different PIC objects.
+ reload_objs="$libobjs $reload_conv_objs"
+ output=$libobj
+ func_execute_cmds "$reload_cmds" 'exit $?'
+ fi
+
+ if test -n "$gentop"; then
+ func_show_eval '${RM}r "$gentop"'
+ fi
+
+ exit $EXIT_SUCCESS
+ ;;
+
+ prog)
+ case $host in
+ *cygwin*) func_stripname '' '.exe' "$output"
+ output=$func_stripname_result.exe;;
+ esac
+ test -n "$vinfo" && \
+ func_warning "'-version-info' is ignored for programs"
+
+ test -n "$release" && \
+ func_warning "'-release' is ignored for programs"
+
+ $preload \
+ && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \
+ && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support."
+
+ case $host in
+ *-*-rhapsody* | *-*-darwin1.[012])
+ # On Rhapsody replace the C library is the System framework
+ compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'`
+ finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'`
+ ;;
+ esac
+
+ case $host in
+ *-*-darwin*)
+ # Don't allow lazy linking, it breaks C++ global constructors
+ # But is supposedly fixed on 10.4 or later (yay!).
+ if test CXX = "$tagname"; then
+ case ${MACOSX_DEPLOYMENT_TARGET-10.0} in
+ 10.[0123])
+ func_append compile_command " $wl-bind_at_load"
+ func_append finalize_command " $wl-bind_at_load"
+ ;;
+ esac
+ fi
+ # Time to change all our "foo.ltframework" stuff back to "-framework foo"
+ compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+ finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'`
+ ;;
+ esac
+
+
+ # move library search paths that coincide with paths to not yet
+ # installed libraries to the beginning of the library search list
+ new_libs=
+ for path in $notinst_path; do
+ case " $new_libs " in
+ *" -L$path/$objdir "*) ;;
+ *)
+ case " $compile_deplibs " in
+ *" -L$path/$objdir "*)
+ func_append new_libs " -L$path/$objdir" ;;
+ esac
+ ;;
+ esac
+ done
+ for deplib in $compile_deplibs; do
+ case $deplib in
+ -L*)
+ case " $new_libs " in
+ *" $deplib "*) ;;
+ *) func_append new_libs " $deplib" ;;
+ esac
+ ;;
+ *) func_append new_libs " $deplib" ;;
+ esac
+ done
+ compile_deplibs=$new_libs
+
+
+ func_append compile_command " $compile_deplibs"
+ func_append finalize_command " $finalize_deplibs"
+
+ if test -n "$rpath$xrpath"; then
+ # If the user specified any rpath flags, then add them.
+ for libdir in $rpath $xrpath; do
+ # This is the magic to use -rpath.
+ case "$finalize_rpath " in
+ *" $libdir "*) ;;
+ *) func_append finalize_rpath " $libdir" ;;
+ esac
+ done
+ fi
+
+ # Now hardcode the library paths
+ rpath=
+ hardcode_libdirs=
+ for libdir in $compile_rpath $finalize_rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs=$libdir
+ else
+ # Just accumulate the unique libdirs.
+ case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ func_append hardcode_libdirs "$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ func_append rpath " $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$perm_rpath " in
+ *" $libdir "*) ;;
+ *) func_append perm_rpath " $libdir" ;;
+ esac
+ fi
+ case $host in
+ *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*)
+ testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'`
+ case :$dllsearchpath: in
+ *":$libdir:"*) ;;
+ ::) dllsearchpath=$libdir;;
+ *) func_append dllsearchpath ":$libdir";;
+ esac
+ case :$dllsearchpath: in
+ *":$testbindir:"*) ;;
+ ::) dllsearchpath=$testbindir;;
+ *) func_append dllsearchpath ":$testbindir";;
+ esac
+ ;;
+ esac
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir=$hardcode_libdirs
+ eval rpath=\" $hardcode_libdir_flag_spec\"
+ fi
+ compile_rpath=$rpath
+
+ rpath=
+ hardcode_libdirs=
+ for libdir in $finalize_rpath; do
+ if test -n "$hardcode_libdir_flag_spec"; then
+ if test -n "$hardcode_libdir_separator"; then
+ if test -z "$hardcode_libdirs"; then
+ hardcode_libdirs=$libdir
+ else
+ # Just accumulate the unique libdirs.
+ case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in
+ *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*)
+ ;;
+ *)
+ func_append hardcode_libdirs "$hardcode_libdir_separator$libdir"
+ ;;
+ esac
+ fi
+ else
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ func_append rpath " $flag"
+ fi
+ elif test -n "$runpath_var"; then
+ case "$finalize_perm_rpath " in
+ *" $libdir "*) ;;
+ *) func_append finalize_perm_rpath " $libdir" ;;
+ esac
+ fi
+ done
+ # Substitute the hardcoded libdirs into the rpath.
+ if test -n "$hardcode_libdir_separator" &&
+ test -n "$hardcode_libdirs"; then
+ libdir=$hardcode_libdirs
+ eval rpath=\" $hardcode_libdir_flag_spec\"
+ fi
+ finalize_rpath=$rpath
+
+ if test -n "$libobjs" && test yes = "$build_old_libs"; then
+ # Transform all the library objects into standard objects.
+ compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP`
+ finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP`
+ fi
+
+ func_generate_dlsyms "$outputname" "@PROGRAM@" false
+
+ # template prelinking step
+ if test -n "$prelink_cmds"; then
+ func_execute_cmds "$prelink_cmds" 'exit $?'
+ fi
+
+ wrappers_required=:
+ case $host in
+ *cegcc* | *mingw32ce*)
+ # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway.
+ wrappers_required=false
+ ;;
+ *cygwin* | *mingw* )
+ test yes = "$build_libtool_libs" || wrappers_required=false
+ ;;
+ *)
+ if test no = "$need_relink" || test yes != "$build_libtool_libs"; then
+ wrappers_required=false
+ fi
+ ;;
+ esac
+ $wrappers_required || {
+ # Replace the output file specification.
+ compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'`
+ link_command=$compile_command$compile_rpath
+
+ # We have no uninstalled library dependencies, so finalize right now.
+ exit_status=0
+ func_show_eval "$link_command" 'exit_status=$?'
+
+ if test -n "$postlink_cmds"; then
+ func_to_tool_file "$output"
+ postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'`
+ func_execute_cmds "$postlink_cmds" 'exit $?'
+ fi
+
+ # Delete the generated files.
+ if test -f "$output_objdir/${outputname}S.$objext"; then
+ func_show_eval '$RM "$output_objdir/${outputname}S.$objext"'
+ fi
+
+ exit $exit_status
+ }
+
+ if test -n "$compile_shlibpath$finalize_shlibpath"; then
+ compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command"
+ fi
+ if test -n "$finalize_shlibpath"; then
+ finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command"
+ fi
+
+ compile_var=
+ finalize_var=
+ if test -n "$runpath_var"; then
+ if test -n "$perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $perm_rpath; do
+ func_append rpath "$dir:"
+ done
+ compile_var="$runpath_var=\"$rpath\$$runpath_var\" "
+ fi
+ if test -n "$finalize_perm_rpath"; then
+ # We should set the runpath_var.
+ rpath=
+ for dir in $finalize_perm_rpath; do
+ func_append rpath "$dir:"
+ done
+ finalize_var="$runpath_var=\"$rpath\$$runpath_var\" "
+ fi
+ fi
+
+ if test yes = "$no_install"; then
+ # We don't need to create a wrapper script.
+ link_command=$compile_var$compile_command$compile_rpath
+ # Replace the output file specification.
+ link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'`
+ # Delete the old output file.
+ $opt_dry_run || $RM $output
+ # Link the executable and exit
+ func_show_eval "$link_command" 'exit $?'
+
+ if test -n "$postlink_cmds"; then
+ func_to_tool_file "$output"
+ postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'`
+ func_execute_cmds "$postlink_cmds" 'exit $?'
+ fi
+
+ exit $EXIT_SUCCESS
+ fi
+
+ case $hardcode_action,$fast_install in
+ relink,*)
+ # Fast installation is not supported
+ link_command=$compile_var$compile_command$compile_rpath
+ relink_command=$finalize_var$finalize_command$finalize_rpath
+
+ func_warning "this platform does not like uninstalled shared libraries"
+ func_warning "'$output' will be relinked during installation"
+ ;;
+ *,yes)
+ link_command=$finalize_var$compile_command$finalize_rpath
+ relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'`
+ ;;
+ *,no)
+ link_command=$compile_var$compile_command$compile_rpath
+ relink_command=$finalize_var$finalize_command$finalize_rpath
+ ;;
+ *,needless)
+ link_command=$finalize_var$compile_command$finalize_rpath
+ relink_command=
+ ;;
+ esac
+
+ # Replace the output file specification.
+ link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'`
+
+ # Delete the old output files.
+ $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname
+
+ func_show_eval "$link_command" 'exit $?'
+
+ if test -n "$postlink_cmds"; then
+ func_to_tool_file "$output_objdir/$outputname"
+ postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'`
+ func_execute_cmds "$postlink_cmds" 'exit $?'
+ fi
+
+ # Now create the wrapper script.
+ func_verbose "creating $output"
+
+ # Quote the relink command for shipping.
+ if test -n "$relink_command"; then
+ # Preserve any variables that may affect compiler behavior
+ for var in $variables_saved_for_relink; do
+ if eval test -z \"\${$var+set}\"; then
+ relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command"
+ elif eval var_value=\$$var; test -z "$var_value"; then
+ relink_command="$var=; export $var; $relink_command"
+ else
+ func_quote_for_eval "$var_value"
+ relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command"
+ fi
+ done
+ relink_command="(cd `pwd`; $relink_command)"
+ relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"`
+ fi
+
+ # Only actually do things if not in dry run mode.
+ $opt_dry_run || {
+ # win32 will think the script is a binary if it has
+ # a .exe suffix, so we strip it off here.
+ case $output in
+ *.exe) func_stripname '' '.exe' "$output"
+ output=$func_stripname_result ;;
+ esac
+ # test for cygwin because mv fails w/o .exe extensions
+ case $host in
+ *cygwin*)
+ exeext=.exe
+ func_stripname '' '.exe' "$outputname"
+ outputname=$func_stripname_result ;;
+ *) exeext= ;;
+ esac
+ case $host in
+ *cygwin* | *mingw* )
+ func_dirname_and_basename "$output" "" "."
+ output_name=$func_basename_result
+ output_path=$func_dirname_result
+ cwrappersource=$output_path/$objdir/lt-$output_name.c
+ cwrapper=$output_path/$output_name.exe
+ $RM $cwrappersource $cwrapper
+ trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15
+
+ func_emit_cwrapperexe_src > $cwrappersource
+
+ # The wrapper executable is built using the $host compiler,
+ # because it contains $host paths and files. If cross-
+ # compiling, it, like the target executable, must be
+ # executed on the $host or under an emulation environment.
+ $opt_dry_run || {
+ $LTCC $LTCFLAGS -o $cwrapper $cwrappersource
+ $STRIP $cwrapper
+ }
+
+ # Now, create the wrapper script for func_source use:
+ func_ltwrapper_scriptname $cwrapper
+ $RM $func_ltwrapper_scriptname_result
+ trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15
+ $opt_dry_run || {
+ # note: this script will not be executed, so do not chmod.
+ if test "x$build" = "x$host"; then
+ $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result
+ else
+ func_emit_wrapper no > $func_ltwrapper_scriptname_result
+ fi
+ }
+ ;;
+ * )
+ $RM $output
+ trap "$RM $output; exit $EXIT_FAILURE" 1 2 15
+
+ func_emit_wrapper no > $output
+ chmod +x $output
+ ;;
+ esac
+ }
+ exit $EXIT_SUCCESS
+ ;;
+ esac
+
+ # See if we need to build an old-fashioned archive.
+ for oldlib in $oldlibs; do
+
+ case $build_libtool_libs in
+ convenience)
+ oldobjs="$libobjs_save $symfileobj"
+ addlibs=$convenience
+ build_libtool_libs=no
+ ;;
+ module)
+ oldobjs=$libobjs_save
+ addlibs=$old_convenience
+ build_libtool_libs=no
+ ;;
+ *)
+ oldobjs="$old_deplibs $non_pic_objects"
+ $preload && test -f "$symfileobj" \
+ && func_append oldobjs " $symfileobj"
+ addlibs=$old_convenience
+ ;;
+ esac
+
+ if test -n "$addlibs"; then
+ gentop=$output_objdir/${outputname}x
+ func_append generated " $gentop"
+
+ func_extract_archives $gentop $addlibs
+ func_append oldobjs " $func_extract_archives_result"
+ fi
+
+ # Do each command in the archive commands.
+ if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then
+ cmds=$old_archive_from_new_cmds
+ else
+
+ # Add any objects from preloaded convenience libraries
+ if test -n "$dlprefiles"; then
+ gentop=$output_objdir/${outputname}x
+ func_append generated " $gentop"
+
+ func_extract_archives $gentop $dlprefiles
+ func_append oldobjs " $func_extract_archives_result"
+ fi
+
+ # POSIX demands no paths to be encoded in archives. We have
+ # to avoid creating archives with duplicate basenames if we
+ # might have to extract them afterwards, e.g., when creating a
+ # static archive out of a convenience library, or when linking
+ # the entirety of a libtool archive into another (currently
+ # not supported by libtool).
+ if (for obj in $oldobjs
+ do
+ func_basename "$obj"
+ $ECHO "$func_basename_result"
+ done | sort | sort -uc >/dev/null 2>&1); then
+ :
+ else
+ echo "copying selected object files to avoid basename conflicts..."
+ gentop=$output_objdir/${outputname}x
+ func_append generated " $gentop"
+ func_mkdir_p "$gentop"
+ save_oldobjs=$oldobjs
+ oldobjs=
+ counter=1
+ for obj in $save_oldobjs
+ do
+ func_basename "$obj"
+ objbase=$func_basename_result
+ case " $oldobjs " in
+ " ") oldobjs=$obj ;;
+ *[\ /]"$objbase "*)
+ while :; do
+ # Make sure we don't pick an alternate name that also
+ # overlaps.
+ newobj=lt$counter-$objbase
+ func_arith $counter + 1
+ counter=$func_arith_result
+ case " $oldobjs " in
+ *[\ /]"$newobj "*) ;;
+ *) if test ! -f "$gentop/$newobj"; then break; fi ;;
+ esac
+ done
+ func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj"
+ func_append oldobjs " $gentop/$newobj"
+ ;;
+ *) func_append oldobjs " $obj" ;;
+ esac
+ done
+ fi
+ func_to_tool_file "$oldlib" func_convert_file_msys_to_w32
+ tool_oldlib=$func_to_tool_file_result
+ eval cmds=\"$old_archive_cmds\"
+
+ func_len " $cmds"
+ len=$func_len_result
+ if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then
+ cmds=$old_archive_cmds
+ elif test -n "$archiver_list_spec"; then
+ func_verbose "using command file archive linking..."
+ for obj in $oldobjs
+ do
+ func_to_tool_file "$obj"
+ $ECHO "$func_to_tool_file_result"
+ done > $output_objdir/$libname.libcmd
+ func_to_tool_file "$output_objdir/$libname.libcmd"
+ oldobjs=" $archiver_list_spec$func_to_tool_file_result"
+ cmds=$old_archive_cmds
+ else
+ # the command line is too long to link in one step, link in parts
+ func_verbose "using piecewise archive linking..."
+ save_RANLIB=$RANLIB
+ RANLIB=:
+ objlist=
+ concat_cmds=
+ save_oldobjs=$oldobjs
+ oldobjs=
+ # Is there a better way of finding the last object in the list?
+ for obj in $save_oldobjs
+ do
+ last_oldobj=$obj
+ done
+ eval test_cmds=\"$old_archive_cmds\"
+ func_len " $test_cmds"
+ len0=$func_len_result
+ len=$len0
+ for obj in $save_oldobjs
+ do
+ func_len " $obj"
+ func_arith $len + $func_len_result
+ len=$func_arith_result
+ func_append objlist " $obj"
+ if test "$len" -lt "$max_cmd_len"; then
+ :
+ else
+ # the above command should be used before it gets too long
+ oldobjs=$objlist
+ if test "$obj" = "$last_oldobj"; then
+ RANLIB=$save_RANLIB
+ fi
+ test -z "$concat_cmds" || concat_cmds=$concat_cmds~
+ eval concat_cmds=\"\$concat_cmds$old_archive_cmds\"
+ objlist=
+ len=$len0
+ fi
+ done
+ RANLIB=$save_RANLIB
+ oldobjs=$objlist
+ if test -z "$oldobjs"; then
+ eval cmds=\"\$concat_cmds\"
+ else
+ eval cmds=\"\$concat_cmds~\$old_archive_cmds\"
+ fi
+ fi
+ fi
+ func_execute_cmds "$cmds" 'exit $?'
+ done
+
+ test -n "$generated" && \
+ func_show_eval "${RM}r$generated"
+
+ # Now create the libtool archive.
+ case $output in
+ *.la)
+ old_library=
+ test yes = "$build_old_libs" && old_library=$libname.$libext
+ func_verbose "creating $output"
+
+ # Preserve any variables that may affect compiler behavior
+ for var in $variables_saved_for_relink; do
+ if eval test -z \"\${$var+set}\"; then
+ relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command"
+ elif eval var_value=\$$var; test -z "$var_value"; then
+ relink_command="$var=; export $var; $relink_command"
+ else
+ func_quote_for_eval "$var_value"
+ relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command"
+ fi
+ done
+ # Quote the link command for shipping.
+ relink_command="(cd `pwd`; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
+ relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"`
+ if test yes = "$hardcode_automatic"; then
+ relink_command=
+ fi
+
+ # Only create the output if not a dry run.
+ $opt_dry_run || {
+ for installed in no yes; do
+ if test yes = "$installed"; then
+ if test -z "$install_libdir"; then
+ break
+ fi
+ output=$output_objdir/${outputname}i
+ # Replace all uninstalled libtool libraries with the installed ones
+ newdependency_libs=
+ for deplib in $dependency_libs; do
+ case $deplib in
+ *.la)
+ func_basename "$deplib"
+ name=$func_basename_result
+ func_resolve_sysroot "$deplib"
+ eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result`
+ test -z "$libdir" && \
+ func_fatal_error "'$deplib' is not a valid libtool archive"
+ func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name"
+ ;;
+ -L*)
+ func_stripname -L '' "$deplib"
+ func_replace_sysroot "$func_stripname_result"
+ func_append newdependency_libs " -L$func_replace_sysroot_result"
+ ;;
+ -R*)
+ func_stripname -R '' "$deplib"
+ func_replace_sysroot "$func_stripname_result"
+ func_append newdependency_libs " -R$func_replace_sysroot_result"
+ ;;
+ *) func_append newdependency_libs " $deplib" ;;
+ esac
+ done
+ dependency_libs=$newdependency_libs
+ newdlfiles=
+
+ for lib in $dlfiles; do
+ case $lib in
+ *.la)
+ func_basename "$lib"
+ name=$func_basename_result
+ eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+ test -z "$libdir" && \
+ func_fatal_error "'$lib' is not a valid libtool archive"
+ func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name"
+ ;;
+ *) func_append newdlfiles " $lib" ;;
+ esac
+ done
+ dlfiles=$newdlfiles
+ newdlprefiles=
+ for lib in $dlprefiles; do
+ case $lib in
+ *.la)
+ # Only pass preopened files to the pseudo-archive (for
+ # eventual linking with the app. that links it) if we
+ # didn't already link the preopened objects directly into
+ # the library:
+ func_basename "$lib"
+ name=$func_basename_result
+ eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib`
+ test -z "$libdir" && \
+ func_fatal_error "'$lib' is not a valid libtool archive"
+ func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name"
+ ;;
+ esac
+ done
+ dlprefiles=$newdlprefiles
+ else
+ newdlfiles=
+ for lib in $dlfiles; do
+ case $lib in
+ [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;;
+ *) abs=`pwd`"/$lib" ;;
+ esac
+ func_append newdlfiles " $abs"
+ done
+ dlfiles=$newdlfiles
+ newdlprefiles=
+ for lib in $dlprefiles; do
+ case $lib in
+ [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;;
+ *) abs=`pwd`"/$lib" ;;
+ esac
+ func_append newdlprefiles " $abs"
+ done
+ dlprefiles=$newdlprefiles
+ fi
+ $RM $output
+ # place dlname in correct position for cygwin
+ # In fact, it would be nice if we could use this code for all target
+ # systems that can't hard-code library paths into their executables
+ # and that have no shared library path variable independent of PATH,
+ # but it turns out we can't easily determine that from inspecting
+ # libtool variables, so we have to hard-code the OSs to which it
+ # applies here; at the moment, that means platforms that use the PE
+ # object format with DLL files. See the long comment at the top of
+ # tests/bindir.at for full details.
+ tdlname=$dlname
+ case $host,$output,$installed,$module,$dlname in
+ *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll)
+ # If a -bindir argument was supplied, place the dll there.
+ if test -n "$bindir"; then
+ func_relative_path "$install_libdir" "$bindir"
+ tdlname=$func_relative_path_result/$dlname
+ else
+ # Otherwise fall back on heuristic.
+ tdlname=../bin/$dlname
+ fi
+ ;;
+ esac
+ $ECHO > $output "\
+# $outputname - a libtool library file
+# Generated by $PROGRAM (GNU $PACKAGE) $VERSION
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# The name that we can dlopen(3).
+dlname='$tdlname'
+
+# Names of this library.
+library_names='$library_names'
+
+# The name of the static archive.
+old_library='$old_library'
+
+# Linker flags that cannot go in dependency_libs.
+inherited_linker_flags='$new_inherited_linker_flags'
+
+# Libraries that this one depends upon.
+dependency_libs='$dependency_libs'
+
+# Names of additional weak libraries provided by this library
+weak_library_names='$weak_libs'
+
+# Version information for $libname.
+current=$current
+age=$age
+revision=$revision
+
+# Is this an already installed library?
+installed=$installed
+
+# Should we warn about portability when linking against -modules?
+shouldnotlink=$module
+
+# Files to dlopen/dlpreopen
+dlopen='$dlfiles'
+dlpreopen='$dlprefiles'
+
+# Directory that this library needs to be installed in:
+libdir='$install_libdir'"
+ if test no,yes = "$installed,$need_relink"; then
+ $ECHO >> $output "\
+relink_command=\"$relink_command\""
+ fi
+ done
+ }
+
+ # Do a symbolic link so that the libtool archive can be found in
+ # LD_LIBRARY_PATH before the program is installed.
+ func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?'
+ ;;
+ esac
+ exit $EXIT_SUCCESS
+}
+
+if test link = "$opt_mode" || test relink = "$opt_mode"; then
+ func_mode_link ${1+"$@"}
+fi
+
+
+# func_mode_uninstall arg...
+func_mode_uninstall ()
+{
+ $debug_cmd
+
+ RM=$nonopt
+ files=
+ rmforce=false
+ exit_status=0
+
+ # This variable tells wrapper scripts just to set variables rather
+ # than running their programs.
+ libtool_install_magic=$magic
+
+ for arg
+ do
+ case $arg in
+ -f) func_append RM " $arg"; rmforce=: ;;
+ -*) func_append RM " $arg" ;;
+ *) func_append files " $arg" ;;
+ esac
+ done
+
+ test -z "$RM" && \
+ func_fatal_help "you must specify an RM program"
+
+ rmdirs=
+
+ for file in $files; do
+ func_dirname "$file" "" "."
+ dir=$func_dirname_result
+ if test . = "$dir"; then
+ odir=$objdir
+ else
+ odir=$dir/$objdir
+ fi
+ func_basename "$file"
+ name=$func_basename_result
+ test uninstall = "$opt_mode" && odir=$dir
+
+ # Remember odir for removal later, being careful to avoid duplicates
+ if test clean = "$opt_mode"; then
+ case " $rmdirs " in
+ *" $odir "*) ;;
+ *) func_append rmdirs " $odir" ;;
+ esac
+ fi
+
+ # Don't error if the file doesn't exist and rm -f was used.
+ if { test -L "$file"; } >/dev/null 2>&1 ||
+ { test -h "$file"; } >/dev/null 2>&1 ||
+ test -f "$file"; then
+ :
+ elif test -d "$file"; then
+ exit_status=1
+ continue
+ elif $rmforce; then
+ continue
+ fi
+
+ rmfiles=$file
+
+ case $name in
+ *.la)
+ # Possibly a libtool archive, so verify it.
+ if func_lalib_p "$file"; then
+ func_source $dir/$name
+
+ # Delete the libtool libraries and symlinks.
+ for n in $library_names; do
+ func_append rmfiles " $odir/$n"
+ done
+ test -n "$old_library" && func_append rmfiles " $odir/$old_library"
+
+ case $opt_mode in
+ clean)
+ case " $library_names " in
+ *" $dlname "*) ;;
+ *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;;
+ esac
+ test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i"
+ ;;
+ uninstall)
+ if test -n "$library_names"; then
+ # Do each command in the postuninstall commands.
+ func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1'
+ fi
+
+ if test -n "$old_library"; then
+ # Do each command in the old_postuninstall commands.
+ func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1'
+ fi
+ # FIXME: should reinstall the best remaining shared library.
+ ;;
+ esac
+ fi
+ ;;
+
+ *.lo)
+ # Possibly a libtool object, so verify it.
+ if func_lalib_p "$file"; then
+
+ # Read the .lo file
+ func_source $dir/$name
+
+ # Add PIC object to the list of files to remove.
+ if test -n "$pic_object" && test none != "$pic_object"; then
+ func_append rmfiles " $dir/$pic_object"
+ fi
+
+ # Add non-PIC object to the list of files to remove.
+ if test -n "$non_pic_object" && test none != "$non_pic_object"; then
+ func_append rmfiles " $dir/$non_pic_object"
+ fi
+ fi
+ ;;
+
+ *)
+ if test clean = "$opt_mode"; then
+ noexename=$name
+ case $file in
+ *.exe)
+ func_stripname '' '.exe' "$file"
+ file=$func_stripname_result
+ func_stripname '' '.exe' "$name"
+ noexename=$func_stripname_result
+ # $file with .exe has already been added to rmfiles,
+ # add $file without .exe
+ func_append rmfiles " $file"
+ ;;
+ esac
+ # Do a test to see if this is a libtool program.
+ if func_ltwrapper_p "$file"; then
+ if func_ltwrapper_executable_p "$file"; then
+ func_ltwrapper_scriptname "$file"
+ relink_command=
+ func_source $func_ltwrapper_scriptname_result
+ func_append rmfiles " $func_ltwrapper_scriptname_result"
+ else
+ relink_command=
+ func_source $dir/$noexename
+ fi
+
+ # note $name still contains .exe if it was in $file originally
+ # as does the version of $file that was added into $rmfiles
+ func_append rmfiles " $odir/$name $odir/${name}S.$objext"
+ if test yes = "$fast_install" && test -n "$relink_command"; then
+ func_append rmfiles " $odir/lt-$name"
+ fi
+ if test "X$noexename" != "X$name"; then
+ func_append rmfiles " $odir/lt-$noexename.c"
+ fi
+ fi
+ fi
+ ;;
+ esac
+ func_show_eval "$RM $rmfiles" 'exit_status=1'
+ done
+
+ # Try to remove the $objdir's in the directories where we deleted files
+ for dir in $rmdirs; do
+ if test -d "$dir"; then
+ func_show_eval "rmdir $dir >/dev/null 2>&1"
+ fi
+ done
+
+ exit $exit_status
+}
+
+if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then
+ func_mode_uninstall ${1+"$@"}
+fi
+
+test -z "$opt_mode" && {
+ help=$generic_help
+ func_fatal_help "you must specify a MODE"
+}
+
+test -z "$exec_cmd" && \
+ func_fatal_help "invalid operation mode '$opt_mode'"
+
+if test -n "$exec_cmd"; then
+ eval exec "$exec_cmd"
+ exit $EXIT_FAILURE
+fi
+
+exit $exit_status
+
+
+# The TAGs below are defined such that we never get into a situation
+# where we disable both kinds of libraries. Given conflicting
+# choices, we go for a static library, that is the most portable,
+# since we can't tell whether shared libraries were disabled because
+# the user asked for that or because the platform doesn't support
+# them. This is particularly important on AIX, because we don't
+# support having both static and shared libraries enabled at the same
+# time on that platform, so we default to a shared-only configuration.
+# If a disable-shared tag is given, we'll fallback to a static-only
+# configuration. But we'll never go from static-only to shared-only.
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-shared
+build_libtool_libs=no
+build_old_libs=yes
+# ### END LIBTOOL TAG CONFIG: disable-shared
+
+# ### BEGIN LIBTOOL TAG CONFIG: disable-static
+build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac`
+# ### END LIBTOOL TAG CONFIG: disable-static
+
+# Local Variables:
+# mode:shell-script
+# sh-indentation:2
+# End:
--- /dev/null
+dnl as-compiler-flag.m4 0.1.0
+
+dnl autostars m4 macro for detection of compiler flags
+
+dnl David Schleef <ds@schleef.org>
+dnl Tim-Philipp Müller <tim centricular net>
+
+dnl AS_COMPILER_FLAG(CFLAGS, ACTION-IF-ACCEPTED, [ACTION-IF-NOT-ACCEPTED])
+dnl Tries to compile with the given CFLAGS.
+dnl Runs ACTION-IF-ACCEPTED if the compiler can compile with the flags,
+dnl and ACTION-IF-NOT-ACCEPTED otherwise.
+
+AC_DEFUN([AS_COMPILER_FLAG],
+[
+ AC_MSG_CHECKING([to see if compiler understands $1])
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $1"
+
+ AC_TRY_COMPILE([ ], [], [flag_ok=yes], [flag_ok=no])
+ CFLAGS="$save_CFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ $2
+ true
+ else
+ $3
+ true
+ fi
+ AC_MSG_RESULT([$flag_ok])
+])
+
+dnl AS_CXX_COMPILER_FLAG(CPPFLAGS, ACTION-IF-ACCEPTED, [ACTION-IF-NOT-ACCEPTED])
+dnl Tries to compile with the given CPPFLAGS.
+dnl Runs ACTION-IF-ACCEPTED if the compiler can compile with the flags,
+dnl and ACTION-IF-NOT-ACCEPTED otherwise.
+
+AC_DEFUN([AS_CXX_COMPILER_FLAG],
+[
+ AC_REQUIRE([AC_PROG_CXX])
+
+ AC_MSG_CHECKING([to see if c++ compiler understands $1])
+
+ save_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $1"
+
+ AC_LANG_PUSH(C++)
+
+ AC_TRY_COMPILE([ ], [], [flag_ok=yes], [flag_ok=no])
+ CPPFLAGS="$save_CPPFLAGS"
+
+ if test "X$flag_ok" = Xyes ; then
+ $2
+ true
+ else
+ $3
+ true
+ fi
+
+ AC_LANG_POP(C++)
+
+ AC_MSG_RESULT([$flag_ok])
+])
+
--- /dev/null
+# ===========================================================================
+# https://www.gnu.org/software/autoconf-archive/ax_check_openssl.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_CHECK_OPENSSL([action-if-found[, action-if-not-found]])
+#
+# DESCRIPTION
+#
+# Look for OpenSSL in a number of default spots, or in a user-selected
+# spot (via --with-openssl). Sets
+#
+# OPENSSL_INCLUDES to the include directives required
+# OPENSSL_LIBS to the -l directives required
+# OPENSSL_LDFLAGS to the -L or -R flags required
+#
+# and calls ACTION-IF-FOUND or ACTION-IF-NOT-FOUND appropriately
+#
+# This macro sets OPENSSL_INCLUDES such that source files should use the
+# openssl/ directory in include directives:
+#
+# #include <openssl/hmac.h>
+#
+# LICENSE
+#
+# Copyright (c) 2009,2010 Zmanda Inc. <http://www.zmanda.com/>
+# Copyright (c) 2009,2010 Dustin J. Mitchell <dustin@zmanda.com>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 10
+
+AU_ALIAS([CHECK_SSL], [AX_CHECK_OPENSSL])
+AC_DEFUN([AX_CHECK_OPENSSL], [
+ found=false
+ AC_ARG_WITH([openssl],
+ [AS_HELP_STRING([--with-openssl=DIR],
+ [root of the OpenSSL directory])],
+ [
+ case "$withval" in
+ "" | y | ye | yes | n | no)
+ AC_MSG_ERROR([Invalid --with-openssl value])
+ ;;
+ *) ssldirs="$withval"
+ ;;
+ esac
+ ], [
+ # if pkg-config is installed and openssl has installed a .pc file,
+ # then use that information and don't search ssldirs
+ AC_CHECK_TOOL([PKG_CONFIG], [pkg-config])
+ if test x"$PKG_CONFIG" != x""; then
+ OPENSSL_LDFLAGS=`$PKG_CONFIG openssl --libs-only-L 2>/dev/null`
+ if test $? = 0; then
+ OPENSSL_LIBS=`$PKG_CONFIG openssl --libs-only-l 2>/dev/null`
+ OPENSSL_INCLUDES=`$PKG_CONFIG openssl --cflags-only-I 2>/dev/null`
+ found=true
+ fi
+ fi
+
+ # no such luck; use some default ssldirs
+ if ! $found; then
+ ssldirs="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /usr"
+ fi
+ ]
+ )
+
+
+ # note that we #include <openssl/foo.h>, so the OpenSSL headers have to be in
+ # an 'openssl' subdirectory
+
+ if ! $found; then
+ OPENSSL_INCLUDES=
+ for ssldir in $ssldirs; do
+ AC_MSG_CHECKING([for openssl/ssl.h in $ssldir])
+ if test -f "$ssldir/include/openssl/ssl.h"; then
+ OPENSSL_INCLUDES="-I$ssldir/include"
+ OPENSSL_LDFLAGS="-L$ssldir/lib"
+ OPENSSL_LIBS="-lssl -lcrypto"
+ found=true
+ AC_MSG_RESULT([yes])
+ break
+ else
+ AC_MSG_RESULT([no])
+ fi
+ done
+
+ # if the file wasn't found, well, go ahead and try the link anyway -- maybe
+ # it will just work!
+ fi
+
+ # try the preprocessor and linker with our new flags,
+ # being careful not to pollute the global LIBS, LDFLAGS, and CPPFLAGS
+
+ AC_MSG_CHECKING([whether compiling and linking against OpenSSL works])
+ echo "Trying link with OPENSSL_LDFLAGS=$OPENSSL_LDFLAGS;" \
+ "OPENSSL_LIBS=$OPENSSL_LIBS; OPENSSL_INCLUDES=$OPENSSL_INCLUDES" >&AS_MESSAGE_LOG_FD
+
+ save_LIBS="$LIBS"
+ save_LDFLAGS="$LDFLAGS"
+ save_CPPFLAGS="$CPPFLAGS"
+ LDFLAGS="$LDFLAGS $OPENSSL_LDFLAGS"
+ LIBS="$OPENSSL_LIBS $LIBS"
+ CPPFLAGS="$OPENSSL_INCLUDES $CPPFLAGS"
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM([#include <openssl/ssl.h>], [SSL_new(NULL)])],
+ [
+ AC_MSG_RESULT([yes])
+ $1
+ ], [
+ AC_MSG_RESULT([no])
+ $2
+ ])
+ CPPFLAGS="$save_CPPFLAGS"
+ LDFLAGS="$save_LDFLAGS"
+ LIBS="$save_LIBS"
+
+ AC_SUBST([OPENSSL_INCLUDES])
+ AC_SUBST([OPENSSL_LIBS])
+ AC_SUBST([OPENSSL_LDFLAGS])
+])
--- /dev/null
+dnl -*- mode: autoconf -*-
+
+# serial 2
+
+dnl Usage:
+dnl GTK_DOC_CHECK([minimum-gtk-doc-version])
+AC_DEFUN([GTK_DOC_CHECK],
+[
+ AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+ AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first
+ AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first
+
+ ifelse([$1],[],[gtk_doc_requires="gtk-doc"],[gtk_doc_requires="gtk-doc >= $1"])
+ AC_MSG_CHECKING([for gtk-doc])
+ PKG_CHECK_EXISTS([$gtk_doc_requires],[have_gtk_doc=yes],[have_gtk_doc=no])
+ AC_MSG_RESULT($have_gtk_doc)
+
+ if test "$have_gtk_doc" = "no"; then
+ AC_MSG_WARN([
+ You will not be able to create source packages with 'make dist'
+ because $gtk_doc_requires is not found.])
+ fi
+
+ dnl check for tools we added during development
+ dnl Use AC_CHECK_PROG to avoid the check target using an absolute path that
+ dnl may not be writable by the user. Currently, automake requires that the
+ dnl test name must end in '.test'.
+ dnl https://bugzilla.gnome.org/show_bug.cgi?id=701638
+ AC_CHECK_PROG([GTKDOC_CHECK],[gtkdoc-check],[gtkdoc-check.test])
+ AC_PATH_PROG([GTKDOC_CHECK_PATH],[gtkdoc-check])
+ AC_PATH_PROGS([GTKDOC_REBASE],[gtkdoc-rebase],[true])
+ AC_PATH_PROG([GTKDOC_MKPDF],[gtkdoc-mkpdf])
+
+ dnl for overriding the documentation installation directory
+ AC_ARG_WITH([html-dir],
+ AS_HELP_STRING([--with-html-dir=PATH], [path to installed docs]),,
+ [with_html_dir='${datadir}/gtk-doc/html'])
+ HTML_DIR="$with_html_dir"
+ AC_SUBST([HTML_DIR])
+
+ dnl enable/disable documentation building
+ AC_ARG_ENABLE([gtk-doc],
+ AS_HELP_STRING([--enable-gtk-doc],
+ [use gtk-doc to build documentation [[default=no]]]),,
+ [enable_gtk_doc=no])
+
+ AC_MSG_CHECKING([whether to build gtk-doc documentation])
+ AC_MSG_RESULT($enable_gtk_doc)
+
+ if test "x$enable_gtk_doc" = "xyes" && test "$have_gtk_doc" = "no"; then
+ AC_MSG_ERROR([
+ You must have $gtk_doc_requires installed to build documentation for
+ $PACKAGE_NAME. Please install gtk-doc or disable building the
+ documentation by adding '--disable-gtk-doc' to '[$]0'.])
+ fi
+
+ dnl don't check for glib if we build glib
+ if test "x$PACKAGE_NAME" != "xglib"; then
+ dnl don't fail if someone does not have glib
+ PKG_CHECK_MODULES(GTKDOC_DEPS, glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0,,[:])
+ fi
+
+ dnl enable/disable output formats
+ AC_ARG_ENABLE([gtk-doc-html],
+ AS_HELP_STRING([--enable-gtk-doc-html],
+ [build documentation in html format [[default=yes]]]),,
+ [enable_gtk_doc_html=yes])
+ AC_ARG_ENABLE([gtk-doc-pdf],
+ AS_HELP_STRING([--enable-gtk-doc-pdf],
+ [build documentation in pdf format [[default=no]]]),,
+ [enable_gtk_doc_pdf=no])
+
+ if test -z "$GTKDOC_MKPDF"; then
+ enable_gtk_doc_pdf=no
+ fi
+
+ if test -z "$AM_DEFAULT_VERBOSITY"; then
+ AM_DEFAULT_VERBOSITY=1
+ fi
+ AC_SUBST([AM_DEFAULT_VERBOSITY])
+
+ AM_CONDITIONAL([HAVE_GTK_DOC], [test x$have_gtk_doc = xyes])
+ AM_CONDITIONAL([ENABLE_GTK_DOC], [test x$enable_gtk_doc = xyes])
+ AM_CONDITIONAL([GTK_DOC_BUILD_HTML], [test x$enable_gtk_doc_html = xyes])
+ AM_CONDITIONAL([GTK_DOC_BUILD_PDF], [test x$enable_gtk_doc_pdf = xyes])
+ AM_CONDITIONAL([GTK_DOC_USE_LIBTOOL], [test -n "$LIBTOOL"])
+ AM_CONDITIONAL([GTK_DOC_USE_REBASE], [test -n "$GTKDOC_REBASE"])
+])
--- /dev/null
+dnl -*- mode: autoconf -*-
+dnl Copyright 2009 Johan Dahlin
+dnl
+dnl This file is free software; the author(s) gives unlimited
+dnl permission to copy and/or distribute it, with or without
+dnl modifications, as long as this notice is preserved.
+dnl
+
+# serial 1
+
+m4_define([_GOBJECT_INTROSPECTION_CHECK_INTERNAL],
+[
+ AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first
+ AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first
+ AC_BEFORE([LT_INIT],[$0])dnl setup libtool first
+
+ dnl enable/disable introspection
+ m4_if([$2], [require],
+ [dnl
+ enable_introspection=yes
+ ],[dnl
+ AC_ARG_ENABLE(introspection,
+ AS_HELP_STRING([--enable-introspection[=@<:@no/auto/yes@:>@]],
+ [Enable introspection for this build]),,
+ [enable_introspection=auto])
+ ])dnl
+
+ AC_MSG_CHECKING([for gobject-introspection])
+
+ dnl presence/version checking
+ AS_CASE([$enable_introspection],
+ [no], [dnl
+ found_introspection="no (disabled, use --enable-introspection to enable)"
+ ],dnl
+ [yes],[dnl
+ PKG_CHECK_EXISTS([gobject-introspection-1.0],,
+ AC_MSG_ERROR([gobject-introspection-1.0 is not installed]))
+ PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1],
+ found_introspection=yes,
+ AC_MSG_ERROR([You need to have gobject-introspection >= $1 installed to build AC_PACKAGE_NAME]))
+ ],dnl
+ [auto],[dnl
+ PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1], found_introspection=yes, found_introspection=no)
+ dnl Canonicalize enable_introspection
+ enable_introspection=$found_introspection
+ ],dnl
+ [dnl
+ AC_MSG_ERROR([invalid argument passed to --enable-introspection, should be one of @<:@no/auto/yes@:>@])
+ ])dnl
+
+ AC_MSG_RESULT([$found_introspection])
+
+ INTROSPECTION_SCANNER=
+ INTROSPECTION_COMPILER=
+ INTROSPECTION_GENERATE=
+ INTROSPECTION_GIRDIR=
+ INTROSPECTION_TYPELIBDIR=
+ if test "x$found_introspection" = "xyes"; then
+ INTROSPECTION_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0`
+ INTROSPECTION_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0`
+ INTROSPECTION_GENERATE=`$PKG_CONFIG --variable=g_ir_generate gobject-introspection-1.0`
+ INTROSPECTION_GIRDIR=`$PKG_CONFIG --variable=girdir gobject-introspection-1.0`
+ INTROSPECTION_TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)"
+ INTROSPECTION_CFLAGS=`$PKG_CONFIG --cflags gobject-introspection-1.0`
+ INTROSPECTION_LIBS=`$PKG_CONFIG --libs gobject-introspection-1.0`
+ INTROSPECTION_MAKEFILE=`$PKG_CONFIG --variable=datadir gobject-introspection-1.0`/gobject-introspection-1.0/Makefile.introspection
+ fi
+ AC_SUBST(INTROSPECTION_SCANNER)
+ AC_SUBST(INTROSPECTION_COMPILER)
+ AC_SUBST(INTROSPECTION_GENERATE)
+ AC_SUBST(INTROSPECTION_GIRDIR)
+ AC_SUBST(INTROSPECTION_TYPELIBDIR)
+ AC_SUBST(INTROSPECTION_CFLAGS)
+ AC_SUBST(INTROSPECTION_LIBS)
+ AC_SUBST(INTROSPECTION_MAKEFILE)
+
+ AM_CONDITIONAL(HAVE_INTROSPECTION, test "x$found_introspection" = "xyes")
+])
+
+
+dnl Usage:
+dnl GOBJECT_INTROSPECTION_CHECK([minimum-g-i-version])
+
+AC_DEFUN([GOBJECT_INTROSPECTION_CHECK],
+[
+ _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1])
+])
+
+dnl Usage:
+dnl GOBJECT_INTROSPECTION_REQUIRE([minimum-g-i-version])
+
+
+AC_DEFUN([GOBJECT_INTROSPECTION_REQUIRE],
+[
+ _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1], [require])
+])
--- /dev/null
+# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
+#
+# Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc.
+# Written by Gordon Matzigkeit, 1996
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+m4_define([_LT_COPYING], [dnl
+# Copyright (C) 2014 Free Software Foundation, Inc.
+# This is free software; see the source for copying conditions. There is NO
+# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+# GNU Libtool is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of of the License, or
+# (at your option) any later version.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program or library that is built
+# using GNU Libtool, you may include this file under the same
+# distribution terms that you use for the rest of that program.
+#
+# GNU Libtool is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+])
+
+# serial 58 LT_INIT
+
+
+# LT_PREREQ(VERSION)
+# ------------------
+# Complain and exit if this libtool version is less that VERSION.
+m4_defun([LT_PREREQ],
+[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1,
+ [m4_default([$3],
+ [m4_fatal([Libtool version $1 or higher is required],
+ 63)])],
+ [$2])])
+
+
+# _LT_CHECK_BUILDDIR
+# ------------------
+# Complain if the absolute build directory name contains unusual characters
+m4_defun([_LT_CHECK_BUILDDIR],
+[case `pwd` in
+ *\ * | *\ *)
+ AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;;
+esac
+])
+
+
+# LT_INIT([OPTIONS])
+# ------------------
+AC_DEFUN([LT_INIT],
+[AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK
+AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
+AC_BEFORE([$0], [LT_LANG])dnl
+AC_BEFORE([$0], [LT_OUTPUT])dnl
+AC_BEFORE([$0], [LTDL_INIT])dnl
+m4_require([_LT_CHECK_BUILDDIR])dnl
+
+dnl Autoconf doesn't catch unexpanded LT_ macros by default:
+m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl
+m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl
+dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4
+dnl unless we require an AC_DEFUNed macro:
+AC_REQUIRE([LTOPTIONS_VERSION])dnl
+AC_REQUIRE([LTSUGAR_VERSION])dnl
+AC_REQUIRE([LTVERSION_VERSION])dnl
+AC_REQUIRE([LTOBSOLETE_VERSION])dnl
+m4_require([_LT_PROG_LTMAIN])dnl
+
+_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}])
+
+dnl Parse OPTIONS
+_LT_SET_OPTIONS([$0], [$1])
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS=$ltmain
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+AC_SUBST(LIBTOOL)dnl
+
+_LT_SETUP
+
+# Only expand once:
+m4_define([LT_INIT])
+])# LT_INIT
+
+# Old names:
+AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT])
+AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_PROG_LIBTOOL], [])
+dnl AC_DEFUN([AM_PROG_LIBTOOL], [])
+
+
+# _LT_PREPARE_CC_BASENAME
+# -----------------------
+m4_defun([_LT_PREPARE_CC_BASENAME], [
+# Calculate cc_basename. Skip known compiler wrappers and cross-prefix.
+func_cc_basename ()
+{
+ for cc_temp in @S|@*""; do
+ case $cc_temp in
+ compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;;
+ distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+ done
+ func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"`
+}
+])# _LT_PREPARE_CC_BASENAME
+
+
+# _LT_CC_BASENAME(CC)
+# -------------------
+# It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME,
+# but that macro is also expanded into generated libtool script, which
+# arranges for $SED and $ECHO to be set by different means.
+m4_defun([_LT_CC_BASENAME],
+[m4_require([_LT_PREPARE_CC_BASENAME])dnl
+AC_REQUIRE([_LT_DECL_SED])dnl
+AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl
+func_cc_basename $1
+cc_basename=$func_cc_basename_result
+])
+
+
+# _LT_FILEUTILS_DEFAULTS
+# ----------------------
+# It is okay to use these file commands and assume they have been set
+# sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'.
+m4_defun([_LT_FILEUTILS_DEFAULTS],
+[: ${CP="cp -f"}
+: ${MV="mv -f"}
+: ${RM="rm -f"}
+])# _LT_FILEUTILS_DEFAULTS
+
+
+# _LT_SETUP
+# ---------
+m4_defun([_LT_SETUP],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl
+AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl
+
+_LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl
+dnl
+_LT_DECL([], [host_alias], [0], [The host system])dnl
+_LT_DECL([], [host], [0])dnl
+_LT_DECL([], [host_os], [0])dnl
+dnl
+_LT_DECL([], [build_alias], [0], [The build system])dnl
+_LT_DECL([], [build], [0])dnl
+_LT_DECL([], [build_os], [0])dnl
+dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([LT_PATH_LD])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+dnl
+AC_REQUIRE([AC_PROG_LN_S])dnl
+test -z "$LN_S" && LN_S="ln -s"
+_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl
+dnl
+AC_REQUIRE([LT_CMD_MAX_LEN])dnl
+_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl
+_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl
+dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_CHECK_SHELL_FEATURES])dnl
+m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl
+m4_require([_LT_CMD_RELOAD])dnl
+m4_require([_LT_CHECK_MAGIC_METHOD])dnl
+m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl
+m4_require([_LT_CMD_OLD_ARCHIVE])dnl
+m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
+m4_require([_LT_WITH_SYSROOT])dnl
+m4_require([_LT_CMD_TRUNCATE])dnl
+
+_LT_CONFIG_LIBTOOL_INIT([
+# See if we are running on zsh, and set the options that allow our
+# commands through without removal of \ escapes INIT.
+if test -n "\${ZSH_VERSION+set}"; then
+ setopt NO_GLOB_SUBST
+fi
+])
+if test -n "${ZSH_VERSION+set}"; then
+ setopt NO_GLOB_SUBST
+fi
+
+_LT_CHECK_OBJDIR
+
+m4_require([_LT_TAG_COMPILER])dnl
+
+case $host_os in
+aix3*)
+ # AIX sometimes has problems with the GCC collect2 program. For some
+ # reason, if we set the COLLECT_NAMES environment variable, the problems
+ # vanish in a puff of smoke.
+ if test set != "${COLLECT_NAMES+set}"; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+ fi
+ ;;
+esac
+
+# Global variables:
+ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a '.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+
+with_gnu_ld=$lt_cv_prog_gnu_ld
+
+old_CC=$CC
+old_CFLAGS=$CFLAGS
+
+# Set sane defaults for various variables
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS
+test -z "$LD" && LD=ld
+test -z "$ac_objext" && ac_objext=o
+
+_LT_CC_BASENAME([$compiler])
+
+# Only perform the check for file, if the check method requires it
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+case $deplibs_check_method in
+file_magic*)
+ if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+ _LT_PATH_MAGIC
+ fi
+ ;;
+esac
+
+# Use C for the default configuration in the libtool script
+LT_SUPPORTED_TAG([CC])
+_LT_LANG_C_CONFIG
+_LT_LANG_DEFAULT_CONFIG
+_LT_CONFIG_COMMANDS
+])# _LT_SETUP
+
+
+# _LT_PREPARE_SED_QUOTE_VARS
+# --------------------------
+# Define a few sed substitution that help us do robust quoting.
+m4_defun([_LT_PREPARE_SED_QUOTE_VARS],
+[# Backslashify metacharacters that are still active within
+# double-quoted strings.
+sed_quote_subst='s/\([["`$\\]]\)/\\\1/g'
+
+# Same as above, but do not quote variable references.
+double_quote_subst='s/\([["`\\]]\)/\\\1/g'
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to delay expansion of an escaped single quote.
+delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+])
+
+# _LT_PROG_LTMAIN
+# ---------------
+# Note that this code is called both from 'configure', and 'config.status'
+# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably,
+# 'config.status' has no value for ac_aux_dir unless we are using Automake,
+# so we pass a copy along to make sure it has a sensible value anyway.
+m4_defun([_LT_PROG_LTMAIN],
+[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl
+_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir'])
+ltmain=$ac_aux_dir/ltmain.sh
+])# _LT_PROG_LTMAIN
+
+
+## ------------------------------------- ##
+## Accumulate code for creating libtool. ##
+## ------------------------------------- ##
+
+# So that we can recreate a full libtool script including additional
+# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS
+# in macros and then make a single call at the end using the 'libtool'
+# label.
+
+
+# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS])
+# ----------------------------------------
+# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later.
+m4_define([_LT_CONFIG_LIBTOOL_INIT],
+[m4_ifval([$1],
+ [m4_append([_LT_OUTPUT_LIBTOOL_INIT],
+ [$1
+])])])
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_INIT])
+
+
+# _LT_CONFIG_LIBTOOL([COMMANDS])
+# ------------------------------
+# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later.
+m4_define([_LT_CONFIG_LIBTOOL],
+[m4_ifval([$1],
+ [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS],
+ [$1
+])])])
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS])
+
+
+# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS])
+# -----------------------------------------------------
+m4_defun([_LT_CONFIG_SAVE_COMMANDS],
+[_LT_CONFIG_LIBTOOL([$1])
+_LT_CONFIG_LIBTOOL_INIT([$2])
+])
+
+
+# _LT_FORMAT_COMMENT([COMMENT])
+# -----------------------------
+# Add leading comment marks to the start of each line, and a trailing
+# full-stop to the whole comment if one is not present already.
+m4_define([_LT_FORMAT_COMMENT],
+[m4_ifval([$1], [
+m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])],
+ [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.])
+)])
+
+
+
+## ------------------------ ##
+## FIXME: Eliminate VARNAME ##
+## ------------------------ ##
+
+
+# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?])
+# -------------------------------------------------------------------
+# CONFIGNAME is the name given to the value in the libtool script.
+# VARNAME is the (base) name used in the configure script.
+# VALUE may be 0, 1 or 2 for a computed quote escaped value based on
+# VARNAME. Any other value will be used directly.
+m4_define([_LT_DECL],
+[lt_if_append_uniq([lt_decl_varnames], [$2], [, ],
+ [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name],
+ [m4_ifval([$1], [$1], [$2])])
+ lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3])
+ m4_ifval([$4],
+ [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])])
+ lt_dict_add_subkey([lt_decl_dict], [$2],
+ [tagged?], [m4_ifval([$5], [yes], [no])])])
+])
+
+
+# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION])
+# --------------------------------------------------------
+m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])])
+
+
+# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...])
+# ------------------------------------------------
+m4_define([lt_decl_tag_varnames],
+[_lt_decl_filter([tagged?], [yes], $@)])
+
+
+# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..])
+# ---------------------------------------------------------
+m4_define([_lt_decl_filter],
+[m4_case([$#],
+ [0], [m4_fatal([$0: too few arguments: $#])],
+ [1], [m4_fatal([$0: too few arguments: $#: $1])],
+ [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)],
+ [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)],
+ [lt_dict_filter([lt_decl_dict], $@)])[]dnl
+])
+
+
+# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...])
+# --------------------------------------------------
+m4_define([lt_decl_quote_varnames],
+[_lt_decl_filter([value], [1], $@)])
+
+
+# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...])
+# ---------------------------------------------------
+m4_define([lt_decl_dquote_varnames],
+[_lt_decl_filter([value], [2], $@)])
+
+
+# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...])
+# ---------------------------------------------------
+m4_define([lt_decl_varnames_tagged],
+[m4_assert([$# <= 2])dnl
+_$0(m4_quote(m4_default([$1], [[, ]])),
+ m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]),
+ m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))])
+m4_define([_lt_decl_varnames_tagged],
+[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])])
+
+
+# lt_decl_all_varnames([SEPARATOR], [VARNAME1...])
+# ------------------------------------------------
+m4_define([lt_decl_all_varnames],
+[_$0(m4_quote(m4_default([$1], [[, ]])),
+ m4_if([$2], [],
+ m4_quote(lt_decl_varnames),
+ m4_quote(m4_shift($@))))[]dnl
+])
+m4_define([_lt_decl_all_varnames],
+[lt_join($@, lt_decl_varnames_tagged([$1],
+ lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl
+])
+
+
+# _LT_CONFIG_STATUS_DECLARE([VARNAME])
+# ------------------------------------
+# Quote a variable value, and forward it to 'config.status' so that its
+# declaration there will have the same value as in 'configure'. VARNAME
+# must have a single quote delimited value for this to work.
+m4_define([_LT_CONFIG_STATUS_DECLARE],
+[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`'])
+
+
+# _LT_CONFIG_STATUS_DECLARATIONS
+# ------------------------------
+# We delimit libtool config variables with single quotes, so when
+# we write them to config.status, we have to be sure to quote all
+# embedded single quotes properly. In configure, this macro expands
+# each variable declared with _LT_DECL (and _LT_TAGDECL) into:
+#
+# <var>='`$ECHO "$<var>" | $SED "$delay_single_quote_subst"`'
+m4_defun([_LT_CONFIG_STATUS_DECLARATIONS],
+[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames),
+ [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])])
+
+
+# _LT_LIBTOOL_TAGS
+# ----------------
+# Output comment and list of tags supported by the script
+m4_defun([_LT_LIBTOOL_TAGS],
+[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl
+available_tags='_LT_TAGS'dnl
+])
+
+
+# _LT_LIBTOOL_DECLARE(VARNAME, [TAG])
+# -----------------------------------
+# Extract the dictionary values for VARNAME (optionally with TAG) and
+# expand to a commented shell variable setting:
+#
+# # Some comment about what VAR is for.
+# visible_name=$lt_internal_name
+m4_define([_LT_LIBTOOL_DECLARE],
+[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1],
+ [description])))[]dnl
+m4_pushdef([_libtool_name],
+ m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl
+m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])),
+ [0], [_libtool_name=[$]$1],
+ [1], [_libtool_name=$lt_[]$1],
+ [2], [_libtool_name=$lt_[]$1],
+ [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl
+m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl
+])
+
+
+# _LT_LIBTOOL_CONFIG_VARS
+# -----------------------
+# Produce commented declarations of non-tagged libtool config variables
+# suitable for insertion in the LIBTOOL CONFIG section of the 'libtool'
+# script. Tagged libtool config variables (even for the LIBTOOL CONFIG
+# section) are produced by _LT_LIBTOOL_TAG_VARS.
+m4_defun([_LT_LIBTOOL_CONFIG_VARS],
+[m4_foreach([_lt_var],
+ m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)),
+ [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])])
+
+
+# _LT_LIBTOOL_TAG_VARS(TAG)
+# -------------------------
+m4_define([_LT_LIBTOOL_TAG_VARS],
+[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames),
+ [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])])
+
+
+# _LT_TAGVAR(VARNAME, [TAGNAME])
+# ------------------------------
+m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])])
+
+
+# _LT_CONFIG_COMMANDS
+# -------------------
+# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of
+# variables for single and double quote escaping we saved from calls
+# to _LT_DECL, we can put quote escaped variables declarations
+# into 'config.status', and then the shell code to quote escape them in
+# for loops in 'config.status'. Finally, any additional code accumulated
+# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded.
+m4_defun([_LT_CONFIG_COMMANDS],
+[AC_PROVIDE_IFELSE([LT_OUTPUT],
+ dnl If the libtool generation code has been placed in $CONFIG_LT,
+ dnl instead of duplicating it all over again into config.status,
+ dnl then we will have config.status run $CONFIG_LT later, so it
+ dnl needs to know what name is stored there:
+ [AC_CONFIG_COMMANDS([libtool],
+ [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])],
+ dnl If the libtool generation code is destined for config.status,
+ dnl expand the accumulated commands and init code now:
+ [AC_CONFIG_COMMANDS([libtool],
+ [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])])
+])#_LT_CONFIG_COMMANDS
+
+
+# Initialize.
+m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT],
+[
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+sed_quote_subst='$sed_quote_subst'
+double_quote_subst='$double_quote_subst'
+delay_variable_subst='$delay_variable_subst'
+_LT_CONFIG_STATUS_DECLARATIONS
+LTCC='$LTCC'
+LTCFLAGS='$LTCFLAGS'
+compiler='$compiler_DEFAULT'
+
+# A function that is used when there is no print builtin or printf.
+func_fallback_echo ()
+{
+ eval 'cat <<_LTECHO_EOF
+\$[]1
+_LTECHO_EOF'
+}
+
+# Quote evaled strings.
+for var in lt_decl_all_varnames([[ \
+]], lt_decl_quote_varnames); do
+ case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+ *[[\\\\\\\`\\"\\\$]]*)
+ eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
+ ;;
+ *)
+ eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+ ;;
+ esac
+done
+
+# Double-quote double-evaled strings.
+for var in lt_decl_all_varnames([[ \
+]], lt_decl_dquote_varnames); do
+ case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in
+ *[[\\\\\\\`\\"\\\$]]*)
+ eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes
+ ;;
+ *)
+ eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\""
+ ;;
+ esac
+done
+
+_LT_OUTPUT_LIBTOOL_INIT
+])
+
+# _LT_GENERATED_FILE_INIT(FILE, [COMMENT])
+# ------------------------------------
+# Generate a child script FILE with all initialization necessary to
+# reuse the environment learned by the parent script, and make the
+# file executable. If COMMENT is supplied, it is inserted after the
+# '#!' sequence but before initialization text begins. After this
+# macro, additional text can be appended to FILE to form the body of
+# the child script. The macro ends with non-zero status if the
+# file could not be fully written (such as if the disk is full).
+m4_ifdef([AS_INIT_GENERATED],
+[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])],
+[m4_defun([_LT_GENERATED_FILE_INIT],
+[m4_require([AS_PREPARE])]dnl
+[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl
+[lt_write_fail=0
+cat >$1 <<_ASEOF || lt_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+$2
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$1 <<\_ASEOF || lt_write_fail=1
+AS_SHELL_SANITIZE
+_AS_PREPARE
+exec AS_MESSAGE_FD>&1
+_ASEOF
+test 0 = "$lt_write_fail" && chmod +x $1[]dnl
+m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT
+
+# LT_OUTPUT
+# ---------
+# This macro allows early generation of the libtool script (before
+# AC_OUTPUT is called), incase it is used in configure for compilation
+# tests.
+AC_DEFUN([LT_OUTPUT],
+[: ${CONFIG_LT=./config.lt}
+AC_MSG_NOTICE([creating $CONFIG_LT])
+_LT_GENERATED_FILE_INIT(["$CONFIG_LT"],
+[# Run this file to recreate a libtool stub with the current configuration.])
+
+cat >>"$CONFIG_LT" <<\_LTEOF
+lt_cl_silent=false
+exec AS_MESSAGE_LOG_FD>>config.log
+{
+ echo
+ AS_BOX([Running $as_me.])
+} >&AS_MESSAGE_LOG_FD
+
+lt_cl_help="\
+'$as_me' creates a local libtool stub from the current configuration,
+for use in further configure time tests before the real libtool is
+generated.
+
+Usage: $[0] [[OPTIONS]]
+
+ -h, --help print this help, then exit
+ -V, --version print version number, then exit
+ -q, --quiet do not print progress messages
+ -d, --debug don't remove temporary files
+
+Report bugs to <bug-libtool@gnu.org>."
+
+lt_cl_version="\
+m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl
+m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION])
+configured by $[0], generated by m4_PACKAGE_STRING.
+
+Copyright (C) 2011 Free Software Foundation, Inc.
+This config.lt script is free software; the Free Software Foundation
+gives unlimited permision to copy, distribute and modify it."
+
+while test 0 != $[#]
+do
+ case $[1] in
+ --version | --v* | -V )
+ echo "$lt_cl_version"; exit 0 ;;
+ --help | --h* | -h )
+ echo "$lt_cl_help"; exit 0 ;;
+ --debug | --d* | -d )
+ debug=: ;;
+ --quiet | --q* | --silent | --s* | -q )
+ lt_cl_silent=: ;;
+
+ -*) AC_MSG_ERROR([unrecognized option: $[1]
+Try '$[0] --help' for more information.]) ;;
+
+ *) AC_MSG_ERROR([unrecognized argument: $[1]
+Try '$[0] --help' for more information.]) ;;
+ esac
+ shift
+done
+
+if $lt_cl_silent; then
+ exec AS_MESSAGE_FD>/dev/null
+fi
+_LTEOF
+
+cat >>"$CONFIG_LT" <<_LTEOF
+_LT_OUTPUT_LIBTOOL_COMMANDS_INIT
+_LTEOF
+
+cat >>"$CONFIG_LT" <<\_LTEOF
+AC_MSG_NOTICE([creating $ofile])
+_LT_OUTPUT_LIBTOOL_COMMANDS
+AS_EXIT(0)
+_LTEOF
+chmod +x "$CONFIG_LT"
+
+# configure is writing to config.log, but config.lt does its own redirection,
+# appending to config.log, which fails on DOS, as config.log is still kept
+# open by configure. Here we exec the FD to /dev/null, effectively closing
+# config.log, so it can be properly (re)opened and appended to by config.lt.
+lt_cl_success=:
+test yes = "$silent" &&
+ lt_config_lt_args="$lt_config_lt_args --quiet"
+exec AS_MESSAGE_LOG_FD>/dev/null
+$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false
+exec AS_MESSAGE_LOG_FD>>config.log
+$lt_cl_success || AS_EXIT(1)
+])# LT_OUTPUT
+
+
+# _LT_CONFIG(TAG)
+# ---------------
+# If TAG is the built-in tag, create an initial libtool script with a
+# default configuration from the untagged config vars. Otherwise add code
+# to config.status for appending the configuration named by TAG from the
+# matching tagged config vars.
+m4_defun([_LT_CONFIG],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+_LT_CONFIG_SAVE_COMMANDS([
+ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl
+ m4_if(_LT_TAG, [C], [
+ # See if we are running on zsh, and set the options that allow our
+ # commands through without removal of \ escapes.
+ if test -n "${ZSH_VERSION+set}"; then
+ setopt NO_GLOB_SUBST
+ fi
+
+ cfgfile=${ofile}T
+ trap "$RM \"$cfgfile\"; exit 1" 1 2 15
+ $RM "$cfgfile"
+
+ cat <<_LT_EOF >> "$cfgfile"
+#! $SHELL
+# Generated automatically by $as_me ($PACKAGE) $VERSION
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+
+# Provide generalized library-building support services.
+# Written by Gordon Matzigkeit, 1996
+
+_LT_COPYING
+_LT_LIBTOOL_TAGS
+
+# Configured defaults for sys_lib_dlsearch_path munging.
+: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"}
+
+# ### BEGIN LIBTOOL CONFIG
+_LT_LIBTOOL_CONFIG_VARS
+_LT_LIBTOOL_TAG_VARS
+# ### END LIBTOOL CONFIG
+
+_LT_EOF
+
+ cat <<'_LT_EOF' >> "$cfgfile"
+
+# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE
+
+_LT_PREPARE_MUNGE_PATH_LIST
+_LT_PREPARE_CC_BASENAME
+
+# ### END FUNCTIONS SHARED WITH CONFIGURE
+
+_LT_EOF
+
+ case $host_os in
+ aix3*)
+ cat <<\_LT_EOF >> "$cfgfile"
+# AIX sometimes has problems with the GCC collect2 program. For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test set != "${COLLECT_NAMES+set}"; then
+ COLLECT_NAMES=
+ export COLLECT_NAMES
+fi
+_LT_EOF
+ ;;
+ esac
+
+ _LT_PROG_LTMAIN
+
+ # We use sed instead of cat because bash on DJGPP gets confused if
+ # if finds mixed CR/LF and LF-only lines. Since sed operates in
+ # text mode, it properly converts lines to CR/LF. This bash problem
+ # is reportedly fixed, but why not run on old versions too?
+ sed '$q' "$ltmain" >> "$cfgfile" \
+ || (rm -f "$cfgfile"; exit 1)
+
+ mv -f "$cfgfile" "$ofile" ||
+ (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+ chmod +x "$ofile"
+],
+[cat <<_LT_EOF >> "$ofile"
+
+dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded
+dnl in a comment (ie after a #).
+# ### BEGIN LIBTOOL TAG CONFIG: $1
+_LT_LIBTOOL_TAG_VARS(_LT_TAG)
+# ### END LIBTOOL TAG CONFIG: $1
+_LT_EOF
+])dnl /m4_if
+],
+[m4_if([$1], [], [
+ PACKAGE='$PACKAGE'
+ VERSION='$VERSION'
+ RM='$RM'
+ ofile='$ofile'], [])
+])dnl /_LT_CONFIG_SAVE_COMMANDS
+])# _LT_CONFIG
+
+
+# LT_SUPPORTED_TAG(TAG)
+# ---------------------
+# Trace this macro to discover what tags are supported by the libtool
+# --tag option, using:
+# autoconf --trace 'LT_SUPPORTED_TAG:$1'
+AC_DEFUN([LT_SUPPORTED_TAG], [])
+
+
+# C support is built-in for now
+m4_define([_LT_LANG_C_enabled], [])
+m4_define([_LT_TAGS], [])
+
+
+# LT_LANG(LANG)
+# -------------
+# Enable libtool support for the given language if not already enabled.
+AC_DEFUN([LT_LANG],
+[AC_BEFORE([$0], [LT_OUTPUT])dnl
+m4_case([$1],
+ [C], [_LT_LANG(C)],
+ [C++], [_LT_LANG(CXX)],
+ [Go], [_LT_LANG(GO)],
+ [Java], [_LT_LANG(GCJ)],
+ [Fortran 77], [_LT_LANG(F77)],
+ [Fortran], [_LT_LANG(FC)],
+ [Windows Resource], [_LT_LANG(RC)],
+ [m4_ifdef([_LT_LANG_]$1[_CONFIG],
+ [_LT_LANG($1)],
+ [m4_fatal([$0: unsupported language: "$1"])])])dnl
+])# LT_LANG
+
+
+# _LT_LANG(LANGNAME)
+# ------------------
+m4_defun([_LT_LANG],
+[m4_ifdef([_LT_LANG_]$1[_enabled], [],
+ [LT_SUPPORTED_TAG([$1])dnl
+ m4_append([_LT_TAGS], [$1 ])dnl
+ m4_define([_LT_LANG_]$1[_enabled], [])dnl
+ _LT_LANG_$1_CONFIG($1)])dnl
+])# _LT_LANG
+
+
+m4_ifndef([AC_PROG_GO], [
+############################################################
+# NOTE: This macro has been submitted for inclusion into #
+# GNU Autoconf as AC_PROG_GO. When it is available in #
+# a released version of Autoconf we should remove this #
+# macro and use it instead. #
+############################################################
+m4_defun([AC_PROG_GO],
+[AC_LANG_PUSH(Go)dnl
+AC_ARG_VAR([GOC], [Go compiler command])dnl
+AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl
+_AC_ARG_VAR_LDFLAGS()dnl
+AC_CHECK_TOOL(GOC, gccgo)
+if test -z "$GOC"; then
+ if test -n "$ac_tool_prefix"; then
+ AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo])
+ fi
+fi
+if test -z "$GOC"; then
+ AC_CHECK_PROG(GOC, gccgo, gccgo, false)
+fi
+])#m4_defun
+])#m4_ifndef
+
+
+# _LT_LANG_DEFAULT_CONFIG
+# -----------------------
+m4_defun([_LT_LANG_DEFAULT_CONFIG],
+[AC_PROVIDE_IFELSE([AC_PROG_CXX],
+ [LT_LANG(CXX)],
+ [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])])
+
+AC_PROVIDE_IFELSE([AC_PROG_F77],
+ [LT_LANG(F77)],
+ [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])])
+
+AC_PROVIDE_IFELSE([AC_PROG_FC],
+ [LT_LANG(FC)],
+ [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])])
+
+dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal
+dnl pulling things in needlessly.
+AC_PROVIDE_IFELSE([AC_PROG_GCJ],
+ [LT_LANG(GCJ)],
+ [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],
+ [LT_LANG(GCJ)],
+ [AC_PROVIDE_IFELSE([LT_PROG_GCJ],
+ [LT_LANG(GCJ)],
+ [m4_ifdef([AC_PROG_GCJ],
+ [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])])
+ m4_ifdef([A][M_PROG_GCJ],
+ [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])])
+ m4_ifdef([LT_PROG_GCJ],
+ [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])])
+
+AC_PROVIDE_IFELSE([AC_PROG_GO],
+ [LT_LANG(GO)],
+ [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])])
+
+AC_PROVIDE_IFELSE([LT_PROG_RC],
+ [LT_LANG(RC)],
+ [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])])
+])# _LT_LANG_DEFAULT_CONFIG
+
+# Obsolete macros:
+AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)])
+AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)])
+AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)])
+AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)])
+AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_CXX], [])
+dnl AC_DEFUN([AC_LIBTOOL_F77], [])
+dnl AC_DEFUN([AC_LIBTOOL_FC], [])
+dnl AC_DEFUN([AC_LIBTOOL_GCJ], [])
+dnl AC_DEFUN([AC_LIBTOOL_RC], [])
+
+
+# _LT_TAG_COMPILER
+# ----------------
+m4_defun([_LT_TAG_COMPILER],
+[AC_REQUIRE([AC_PROG_CC])dnl
+
+_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl
+_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl
+_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl
+_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# If no C compiler flags were specified, use CFLAGS.
+LTCFLAGS=${LTCFLAGS-"$CFLAGS"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+])# _LT_TAG_COMPILER
+
+
+# _LT_COMPILER_BOILERPLATE
+# ------------------------
+# Check for compiler boilerplate output or warnings with
+# the simple compiler test code.
+m4_defun([_LT_COMPILER_BOILERPLATE],
+[m4_require([_LT_DECL_SED])dnl
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_compile_test_code" >conftest.$ac_ext
+eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_compiler_boilerplate=`cat conftest.err`
+$RM conftest*
+])# _LT_COMPILER_BOILERPLATE
+
+
+# _LT_LINKER_BOILERPLATE
+# ----------------------
+# Check for linker boilerplate output or warnings with
+# the simple link test code.
+m4_defun([_LT_LINKER_BOILERPLATE],
+[m4_require([_LT_DECL_SED])dnl
+ac_outfile=conftest.$ac_objext
+echo "$lt_simple_link_test_code" >conftest.$ac_ext
+eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err
+_lt_linker_boilerplate=`cat conftest.err`
+$RM -r conftest*
+])# _LT_LINKER_BOILERPLATE
+
+# _LT_REQUIRED_DARWIN_CHECKS
+# -------------------------
+m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[
+ case $host_os in
+ rhapsody* | darwin*)
+ AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:])
+ AC_CHECK_TOOL([NMEDIT], [nmedit], [:])
+ AC_CHECK_TOOL([LIPO], [lipo], [:])
+ AC_CHECK_TOOL([OTOOL], [otool], [:])
+ AC_CHECK_TOOL([OTOOL64], [otool64], [:])
+ _LT_DECL([], [DSYMUTIL], [1],
+ [Tool to manipulate archived DWARF debug symbol files on Mac OS X])
+ _LT_DECL([], [NMEDIT], [1],
+ [Tool to change global to local symbols on Mac OS X])
+ _LT_DECL([], [LIPO], [1],
+ [Tool to manipulate fat objects and archives on Mac OS X])
+ _LT_DECL([], [OTOOL], [1],
+ [ldd/readelf like tool for Mach-O binaries on Mac OS X])
+ _LT_DECL([], [OTOOL64], [1],
+ [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4])
+
+ AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod],
+ [lt_cv_apple_cc_single_mod=no
+ if test -z "$LT_MULTI_MODULE"; then
+ # By default we will add the -single_module flag. You can override
+ # by either setting the environment variable LT_MULTI_MODULE
+ # non-empty at configure time, or by adding -multi_module to the
+ # link flags.
+ rm -rf libconftest.dylib*
+ echo "int foo(void){return 1;}" > conftest.c
+ echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+-dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD
+ $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \
+ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err
+ _lt_result=$?
+ # If there is a non-empty error log, and "single_module"
+ # appears in it, assume the flag caused a linker warning
+ if test -s conftest.err && $GREP single_module conftest.err; then
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ # Otherwise, if the output was created with a 0 exit code from
+ # the compiler, it worked.
+ elif test -f libconftest.dylib && test 0 = "$_lt_result"; then
+ lt_cv_apple_cc_single_mod=yes
+ else
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ fi
+ rm -rf libconftest.dylib*
+ rm -f conftest.*
+ fi])
+
+ AC_CACHE_CHECK([for -exported_symbols_list linker flag],
+ [lt_cv_ld_exported_symbols_list],
+ [lt_cv_ld_exported_symbols_list=no
+ save_LDFLAGS=$LDFLAGS
+ echo "_main" > conftest.sym
+ LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym"
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
+ [lt_cv_ld_exported_symbols_list=yes],
+ [lt_cv_ld_exported_symbols_list=no])
+ LDFLAGS=$save_LDFLAGS
+ ])
+
+ AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load],
+ [lt_cv_ld_force_load=no
+ cat > conftest.c << _LT_EOF
+int forced_loaded() { return 2;}
+_LT_EOF
+ echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD
+ $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD
+ echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD
+ $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD
+ echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD
+ $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD
+ cat > conftest.c << _LT_EOF
+int main() { return 0;}
+_LT_EOF
+ echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD
+ $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err
+ _lt_result=$?
+ if test -s conftest.err && $GREP force_load conftest.err; then
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then
+ lt_cv_ld_force_load=yes
+ else
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ fi
+ rm -f conftest.err libconftest.a conftest conftest.c
+ rm -rf conftest.dSYM
+ ])
+ case $host_os in
+ rhapsody* | darwin1.[[012]])
+ _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;;
+ darwin1.*)
+ _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
+ darwin*) # darwin 5.x on
+ # if running on 10.5 or later, the deployment target defaults
+ # to the OS version, if on x86, and 10.4, the deployment
+ # target defaults to 10.4. Don't you love it?
+ case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
+ 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*)
+ _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
+ 10.[[012]][[,.]]*)
+ _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
+ 10.*)
+ _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
+ esac
+ ;;
+ esac
+ if test yes = "$lt_cv_apple_cc_single_mod"; then
+ _lt_dar_single_mod='$single_module'
+ fi
+ if test yes = "$lt_cv_ld_exported_symbols_list"; then
+ _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym'
+ else
+ _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib'
+ fi
+ if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then
+ _lt_dsymutil='~$DSYMUTIL $lib || :'
+ else
+ _lt_dsymutil=
+ fi
+ ;;
+ esac
+])
+
+
+# _LT_DARWIN_LINKER_FEATURES([TAG])
+# ---------------------------------
+# Checks for linker and compiler features on darwin
+m4_defun([_LT_DARWIN_LINKER_FEATURES],
+[
+ m4_require([_LT_REQUIRED_DARWIN_CHECKS])
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_automatic, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+ if test yes = "$lt_cv_ld_force_load"; then
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`'
+ m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes],
+ [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes])
+ else
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=''
+ fi
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined
+ case $cc_basename in
+ ifort*|nagfor*) _lt_dar_can_shared=yes ;;
+ *) _lt_dar_can_shared=$GCC ;;
+ esac
+ if test yes = "$_lt_dar_can_shared"; then
+ output_verbose_link_cmd=func_echo_all
+ _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil"
+ _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil"
+ _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil"
+ _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil"
+ m4_if([$1], [CXX],
+[ if test yes != "$lt_cv_apple_cc_single_mod"; then
+ _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil"
+ _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil"
+ fi
+],[])
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+])
+
+# _LT_SYS_MODULE_PATH_AIX([TAGNAME])
+# ----------------------------------
+# Links a minimal program and checks the executable
+# for the system default hardcoded library path. In most cases,
+# this is /usr/lib:/lib, but when the MPI compilers are used
+# the location of the communication and MPI libs are included too.
+# If we don't find anything, use the default library path according
+# to the aix ld manual.
+# Store the results from the different compilers for each TAGNAME.
+# Allow to override them for all tags through lt_cv_aix_libpath.
+m4_defun([_LT_SYS_MODULE_PATH_AIX],
+[m4_require([_LT_DECL_SED])dnl
+if test set = "${lt_cv_aix_libpath+set}"; then
+ aix_libpath=$lt_cv_aix_libpath
+else
+ AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])],
+ [AC_LINK_IFELSE([AC_LANG_PROGRAM],[
+ lt_aix_libpath_sed='[
+ /Import File Strings/,/^$/ {
+ /^0/ {
+ s/^0 *\([^ ]*\) *$/\1/
+ p
+ }
+ }]'
+ _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+ # Check for a 64-bit object if we didn't find anything.
+ if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then
+ _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"`
+ fi],[])
+ if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then
+ _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib
+ fi
+ ])
+ aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])
+fi
+])# _LT_SYS_MODULE_PATH_AIX
+
+
+# _LT_SHELL_INIT(ARG)
+# -------------------
+m4_define([_LT_SHELL_INIT],
+[m4_divert_text([M4SH-INIT], [$1
+])])# _LT_SHELL_INIT
+
+
+
+# _LT_PROG_ECHO_BACKSLASH
+# -----------------------
+# Find how we can fake an echo command that does not interpret backslash.
+# In particular, with Autoconf 2.60 or later we add some code to the start
+# of the generated configure script that will find a shell with a builtin
+# printf (that we can use as an echo command).
+m4_defun([_LT_PROG_ECHO_BACKSLASH],
+[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+
+AC_MSG_CHECKING([how to print strings])
+# Test print first, because it will be a builtin if present.
+if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \
+ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then
+ ECHO='print -r --'
+elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then
+ ECHO='printf %s\n'
+else
+ # Use this function as a fallback that always works.
+ func_fallback_echo ()
+ {
+ eval 'cat <<_LTECHO_EOF
+$[]1
+_LTECHO_EOF'
+ }
+ ECHO='func_fallback_echo'
+fi
+
+# func_echo_all arg...
+# Invoke $ECHO with all args, space-separated.
+func_echo_all ()
+{
+ $ECHO "$*"
+}
+
+case $ECHO in
+ printf*) AC_MSG_RESULT([printf]) ;;
+ print*) AC_MSG_RESULT([print -r]) ;;
+ *) AC_MSG_RESULT([cat]) ;;
+esac
+
+m4_ifdef([_AS_DETECT_SUGGESTED],
+[_AS_DETECT_SUGGESTED([
+ test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || (
+ ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+ ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO
+ ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO
+ PATH=/empty FPATH=/empty; export PATH FPATH
+ test "X`printf %s $ECHO`" = "X$ECHO" \
+ || test "X`print -r -- $ECHO`" = "X$ECHO" )])])
+
+_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts])
+_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes])
+])# _LT_PROG_ECHO_BACKSLASH
+
+
+# _LT_WITH_SYSROOT
+# ----------------
+AC_DEFUN([_LT_WITH_SYSROOT],
+[AC_MSG_CHECKING([for sysroot])
+AC_ARG_WITH([sysroot],
+[AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@],
+ [Search for dependent libraries within DIR (or the compiler's sysroot
+ if not specified).])],
+[], [with_sysroot=no])
+
+dnl lt_sysroot will always be passed unquoted. We quote it here
+dnl in case the user passed a directory name.
+lt_sysroot=
+case $with_sysroot in #(
+ yes)
+ if test yes = "$GCC"; then
+ lt_sysroot=`$CC --print-sysroot 2>/dev/null`
+ fi
+ ;; #(
+ /*)
+ lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"`
+ ;; #(
+ no|'')
+ ;; #(
+ *)
+ AC_MSG_RESULT([$with_sysroot])
+ AC_MSG_ERROR([The sysroot must be an absolute path.])
+ ;;
+esac
+
+ AC_MSG_RESULT([${lt_sysroot:-no}])
+_LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl
+[dependent libraries, and where our libraries should be installed.])])
+
+# _LT_ENABLE_LOCK
+# ---------------
+m4_defun([_LT_ENABLE_LOCK],
+[AC_ARG_ENABLE([libtool-lock],
+ [AS_HELP_STRING([--disable-libtool-lock],
+ [avoid locking (might break parallel builds)])])
+test no = "$enable_libtool_lock" || enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+ # Find out what ABI is being produced by ac_compile, and set mode
+ # options accordingly.
+ echo 'int i;' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *ELF-32*)
+ HPUX_IA64_MODE=32
+ ;;
+ *ELF-64*)
+ HPUX_IA64_MODE=64
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+*-*-irix6*)
+ # Find out what ABI is being produced by ac_compile, and set linker
+ # options accordingly.
+ echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ if test yes = "$lt_cv_prog_gnu_ld"; then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -melf32bsmip"
+ ;;
+ *N32*)
+ LD="${LD-ld} -melf32bmipn32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -melf64bmip"
+ ;;
+ esac
+ else
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ LD="${LD-ld} -32"
+ ;;
+ *N32*)
+ LD="${LD-ld} -n32"
+ ;;
+ *64-bit*)
+ LD="${LD-ld} -64"
+ ;;
+ esac
+ fi
+ fi
+ rm -rf conftest*
+ ;;
+
+mips64*-*linux*)
+ # Find out what ABI is being produced by ac_compile, and set linker
+ # options accordingly.
+ echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ emul=elf
+ case `/usr/bin/file conftest.$ac_objext` in
+ *32-bit*)
+ emul="${emul}32"
+ ;;
+ *64-bit*)
+ emul="${emul}64"
+ ;;
+ esac
+ case `/usr/bin/file conftest.$ac_objext` in
+ *MSB*)
+ emul="${emul}btsmip"
+ ;;
+ *LSB*)
+ emul="${emul}ltsmip"
+ ;;
+ esac
+ case `/usr/bin/file conftest.$ac_objext` in
+ *N32*)
+ emul="${emul}n32"
+ ;;
+ esac
+ LD="${LD-ld} -m $emul"
+ fi
+ rm -rf conftest*
+ ;;
+
+x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \
+s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
+ # Find out what ABI is being produced by ac_compile, and set linker
+ # options accordingly. Note that the listed cases only cover the
+ # situations where additional linker options are needed (such as when
+ # doing 32-bit compilation for a host where ld defaults to 64-bit, or
+ # vice versa); the common cases where no linker options are needed do
+ # not appear in the list.
+ echo 'int i;' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ case `/usr/bin/file conftest.o` in
+ *32-bit*)
+ case $host in
+ x86_64-*kfreebsd*-gnu)
+ LD="${LD-ld} -m elf_i386_fbsd"
+ ;;
+ x86_64-*linux*)
+ case `/usr/bin/file conftest.o` in
+ *x86-64*)
+ LD="${LD-ld} -m elf32_x86_64"
+ ;;
+ *)
+ LD="${LD-ld} -m elf_i386"
+ ;;
+ esac
+ ;;
+ powerpc64le-*linux*)
+ LD="${LD-ld} -m elf32lppclinux"
+ ;;
+ powerpc64-*linux*)
+ LD="${LD-ld} -m elf32ppclinux"
+ ;;
+ s390x-*linux*)
+ LD="${LD-ld} -m elf_s390"
+ ;;
+ sparc64-*linux*)
+ LD="${LD-ld} -m elf32_sparc"
+ ;;
+ esac
+ ;;
+ *64-bit*)
+ case $host in
+ x86_64-*kfreebsd*-gnu)
+ LD="${LD-ld} -m elf_x86_64_fbsd"
+ ;;
+ x86_64-*linux*)
+ LD="${LD-ld} -m elf_x86_64"
+ ;;
+ powerpcle-*linux*)
+ LD="${LD-ld} -m elf64lppc"
+ ;;
+ powerpc-*linux*)
+ LD="${LD-ld} -m elf64ppc"
+ ;;
+ s390*-*linux*|s390*-*tpf*)
+ LD="${LD-ld} -m elf64_s390"
+ ;;
+ sparc*-*linux*)
+ LD="${LD-ld} -m elf64_sparc"
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+
+*-*-sco3.2v5*)
+ # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+ SAVE_CFLAGS=$CFLAGS
+ CFLAGS="$CFLAGS -belf"
+ AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
+ [AC_LANG_PUSH(C)
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
+ AC_LANG_POP])
+ if test yes != "$lt_cv_cc_needs_belf"; then
+ # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+ CFLAGS=$SAVE_CFLAGS
+ fi
+ ;;
+*-*solaris*)
+ # Find out what ABI is being produced by ac_compile, and set linker
+ # options accordingly.
+ echo 'int i;' > conftest.$ac_ext
+ if AC_TRY_EVAL(ac_compile); then
+ case `/usr/bin/file conftest.o` in
+ *64-bit*)
+ case $lt_cv_prog_gnu_ld in
+ yes*)
+ case $host in
+ i?86-*-solaris*|x86_64-*-solaris*)
+ LD="${LD-ld} -m elf_x86_64"
+ ;;
+ sparc*-*-solaris*)
+ LD="${LD-ld} -m elf64_sparc"
+ ;;
+ esac
+ # GNU ld 2.21 introduced _sol2 emulations. Use them if available.
+ if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then
+ LD=${LD-ld}_sol2
+ fi
+ ;;
+ *)
+ if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then
+ LD="${LD-ld} -64"
+ fi
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+ ;;
+esac
+
+need_locks=$enable_libtool_lock
+])# _LT_ENABLE_LOCK
+
+
+# _LT_PROG_AR
+# -----------
+m4_defun([_LT_PROG_AR],
+[AC_CHECK_TOOLS(AR, [ar], false)
+: ${AR=ar}
+: ${AR_FLAGS=cru}
+_LT_DECL([], [AR], [1], [The archiver])
+_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive])
+
+AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file],
+ [lt_cv_ar_at_file=no
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM],
+ [echo conftest.$ac_objext > conftest.lst
+ lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD'
+ AC_TRY_EVAL([lt_ar_try])
+ if test 0 -eq "$ac_status"; then
+ # Ensure the archiver fails upon bogus file names.
+ rm -f conftest.$ac_objext libconftest.a
+ AC_TRY_EVAL([lt_ar_try])
+ if test 0 -ne "$ac_status"; then
+ lt_cv_ar_at_file=@
+ fi
+ fi
+ rm -f conftest.* libconftest.a
+ ])
+ ])
+
+if test no = "$lt_cv_ar_at_file"; then
+ archiver_list_spec=
+else
+ archiver_list_spec=$lt_cv_ar_at_file
+fi
+_LT_DECL([], [archiver_list_spec], [1],
+ [How to feed a file listing to the archiver])
+])# _LT_PROG_AR
+
+
+# _LT_CMD_OLD_ARCHIVE
+# -------------------
+m4_defun([_LT_CMD_OLD_ARCHIVE],
+[_LT_PROG_AR
+
+AC_CHECK_TOOL(STRIP, strip, :)
+test -z "$STRIP" && STRIP=:
+_LT_DECL([], [STRIP], [1], [A symbol stripping program])
+
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+test -z "$RANLIB" && RANLIB=:
+_LT_DECL([], [RANLIB], [1],
+ [Commands used to install an old-style archive])
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+ case $host_os in
+ bitrig* | openbsd*)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib"
+ ;;
+ *)
+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib"
+ ;;
+ esac
+ old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib"
+fi
+
+case $host_os in
+ darwin*)
+ lock_old_archive_extraction=yes ;;
+ *)
+ lock_old_archive_extraction=no ;;
+esac
+_LT_DECL([], [old_postinstall_cmds], [2])
+_LT_DECL([], [old_postuninstall_cmds], [2])
+_LT_TAGDECL([], [old_archive_cmds], [2],
+ [Commands used to build an old-style archive])
+_LT_DECL([], [lock_old_archive_extraction], [0],
+ [Whether to use a lock for old archive extraction])
+])# _LT_CMD_OLD_ARCHIVE
+
+
+# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------------------
+# Check whether the given compiler option works
+AC_DEFUN([_LT_COMPILER_OPTION],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_SED])dnl
+AC_CACHE_CHECK([$1], [$2],
+ [$2=no
+ m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+ lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ # The option is referenced via a variable to avoid confusing sed.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+ (eval "$lt_compile" 2>conftest.err)
+ ac_status=$?
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+ if (exit $ac_status) && test -s "$ac_outfile"; then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings other than the usual output.
+ $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then
+ $2=yes
+ fi
+ fi
+ $RM conftest*
+])
+
+if test yes = "[$]$2"; then
+ m4_if([$5], , :, [$5])
+else
+ m4_if([$6], , :, [$6])
+fi
+])# _LT_COMPILER_OPTION
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], [])
+
+
+# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+# [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------
+# Check whether the given linker option works
+AC_DEFUN([_LT_LINKER_OPTION],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_SED])dnl
+AC_CACHE_CHECK([$1], [$2],
+ [$2=no
+ save_LDFLAGS=$LDFLAGS
+ LDFLAGS="$LDFLAGS $3"
+ echo "$lt_simple_link_test_code" > conftest.$ac_ext
+ if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+ # The linker can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ if test -s conftest.err; then
+ # Append any errors to the config.log.
+ cat conftest.err 1>&AS_MESSAGE_LOG_FD
+ $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp
+ $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2
+ if diff conftest.exp conftest.er2 >/dev/null; then
+ $2=yes
+ fi
+ else
+ $2=yes
+ fi
+ fi
+ $RM -r conftest*
+ LDFLAGS=$save_LDFLAGS
+])
+
+if test yes = "[$]$2"; then
+ m4_if([$4], , :, [$4])
+else
+ m4_if([$5], , :, [$5])
+fi
+])# _LT_LINKER_OPTION
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], [])
+
+
+# LT_CMD_MAX_LEN
+#---------------
+AC_DEFUN([LT_CMD_MAX_LEN],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+# find the maximum length of command line arguments
+AC_MSG_CHECKING([the maximum length of command line arguments])
+AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
+ i=0
+ teststring=ABCD
+
+ case $build_os in
+ msdosdjgpp*)
+ # On DJGPP, this test can blow up pretty badly due to problems in libc
+ # (any single argument exceeding 2000 bytes causes a buffer overrun
+ # during glob expansion). Even if it were fixed, the result of this
+ # check would be larger than it should be.
+ lt_cv_sys_max_cmd_len=12288; # 12K is about right
+ ;;
+
+ gnu*)
+ # Under GNU Hurd, this test is not required because there is
+ # no limit to the length of command line arguments.
+ # Libtool will interpret -1 as no limit whatsoever
+ lt_cv_sys_max_cmd_len=-1;
+ ;;
+
+ cygwin* | mingw* | cegcc*)
+ # On Win9x/ME, this test blows up -- it succeeds, but takes
+ # about 5 minutes as the teststring grows exponentially.
+ # Worse, since 9x/ME are not pre-emptively multitasking,
+ # you end up with a "frozen" computer, even though with patience
+ # the test eventually succeeds (with a max line length of 256k).
+ # Instead, let's just punt: use the minimum linelength reported by
+ # all of the supported platforms: 8192 (on NT/2K/XP).
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ mint*)
+ # On MiNT this can take a long time and run out of memory.
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ amigaos*)
+ # On AmigaOS with pdksh, this test takes hours, literally.
+ # So we just punt and use a minimum line length of 8192.
+ lt_cv_sys_max_cmd_len=8192;
+ ;;
+
+ bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*)
+ # This has been around since 386BSD, at least. Likely further.
+ if test -x /sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
+ elif test -x /usr/sbin/sysctl; then
+ lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax`
+ else
+ lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs
+ fi
+ # And add a safety zone
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+ ;;
+
+ interix*)
+ # We know the value 262144 and hardcode it with a safety zone (like BSD)
+ lt_cv_sys_max_cmd_len=196608
+ ;;
+
+ os2*)
+ # The test takes a long time on OS/2.
+ lt_cv_sys_max_cmd_len=8192
+ ;;
+
+ osf*)
+ # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure
+ # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not
+ # nice to cause kernel panics so lets avoid the loop below.
+ # First set a reasonable default.
+ lt_cv_sys_max_cmd_len=16384
+ #
+ if test -x /sbin/sysconfig; then
+ case `/sbin/sysconfig -q proc exec_disable_arg_limit` in
+ *1*) lt_cv_sys_max_cmd_len=-1 ;;
+ esac
+ fi
+ ;;
+ sco3.2v5*)
+ lt_cv_sys_max_cmd_len=102400
+ ;;
+ sysv5* | sco5v6* | sysv4.2uw2*)
+ kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
+ if test -n "$kargmax"; then
+ lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'`
+ else
+ lt_cv_sys_max_cmd_len=32768
+ fi
+ ;;
+ *)
+ lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null`
+ if test -n "$lt_cv_sys_max_cmd_len" && \
+ test undefined != "$lt_cv_sys_max_cmd_len"; then
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4`
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3`
+ else
+ # Make teststring a little bigger before we do anything with it.
+ # a 1K string should be a reasonable start.
+ for i in 1 2 3 4 5 6 7 8; do
+ teststring=$teststring$teststring
+ done
+ SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}}
+ # If test is not a shell built-in, we'll probably end up computing a
+ # maximum length that is only half of the actual maximum length, but
+ # we can't tell.
+ while { test X`env echo "$teststring$teststring" 2>/dev/null` \
+ = "X$teststring$teststring"; } >/dev/null 2>&1 &&
+ test 17 != "$i" # 1/2 MB should be enough
+ do
+ i=`expr $i + 1`
+ teststring=$teststring$teststring
+ done
+ # Only check the string length outside the loop.
+ lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1`
+ teststring=
+ # Add a significant safety factor because C++ compilers can tack on
+ # massive amounts of additional arguments before passing them to the
+ # linker. It appears as though 1/2 is a usable value.
+ lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+ fi
+ ;;
+ esac
+])
+if test -n "$lt_cv_sys_max_cmd_len"; then
+ AC_MSG_RESULT($lt_cv_sys_max_cmd_len)
+else
+ AC_MSG_RESULT(none)
+fi
+max_cmd_len=$lt_cv_sys_max_cmd_len
+_LT_DECL([], [max_cmd_len], [0],
+ [What is the maximum length of a command?])
+])# LT_CMD_MAX_LEN
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], [])
+
+
+# _LT_HEADER_DLFCN
+# ----------------
+m4_defun([_LT_HEADER_DLFCN],
+[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl
+])# _LT_HEADER_DLFCN
+
+
+# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
+# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
+# ----------------------------------------------------------------
+m4_defun([_LT_TRY_DLOPEN_SELF],
+[m4_require([_LT_HEADER_DLFCN])dnl
+if test yes = "$cross_compiling"; then :
+ [$4]
+else
+ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+ lt_status=$lt_dlunknown
+ cat > conftest.$ac_ext <<_LT_EOF
+[#line $LINENO "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+# define LT_DLGLOBAL RTLD_GLOBAL
+#else
+# ifdef DL_GLOBAL
+# define LT_DLGLOBAL DL_GLOBAL
+# else
+# define LT_DLGLOBAL 0
+# endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+ find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+# ifdef RTLD_LAZY
+# define LT_DLLAZY_OR_NOW RTLD_LAZY
+# else
+# ifdef DL_LAZY
+# define LT_DLLAZY_OR_NOW DL_LAZY
+# else
+# ifdef RTLD_NOW
+# define LT_DLLAZY_OR_NOW RTLD_NOW
+# else
+# ifdef DL_NOW
+# define LT_DLLAZY_OR_NOW DL_NOW
+# else
+# define LT_DLLAZY_OR_NOW 0
+# endif
+# endif
+# endif
+# endif
+#endif
+
+/* When -fvisibility=hidden is used, assume the code has been annotated
+ correspondingly for the symbols needed. */
+#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3))
+int fnord () __attribute__((visibility("default")));
+#endif
+
+int fnord () { return 42; }
+int main ()
+{
+ void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+ int status = $lt_dlunknown;
+
+ if (self)
+ {
+ if (dlsym (self,"fnord")) status = $lt_dlno_uscore;
+ else
+ {
+ if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+ else puts (dlerror ());
+ }
+ /* dlclose (self); */
+ }
+ else
+ puts (dlerror ());
+
+ return status;
+}]
+_LT_EOF
+ if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then
+ (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null
+ lt_status=$?
+ case x$lt_status in
+ x$lt_dlno_uscore) $1 ;;
+ x$lt_dlneed_uscore) $2 ;;
+ x$lt_dlunknown|x*) $3 ;;
+ esac
+ else :
+ # compilation failed
+ $3
+ fi
+fi
+rm -fr conftest*
+])# _LT_TRY_DLOPEN_SELF
+
+
+# LT_SYS_DLOPEN_SELF
+# ------------------
+AC_DEFUN([LT_SYS_DLOPEN_SELF],
+[m4_require([_LT_HEADER_DLFCN])dnl
+if test yes != "$enable_dlopen"; then
+ enable_dlopen=unknown
+ enable_dlopen_self=unknown
+ enable_dlopen_self_static=unknown
+else
+ lt_cv_dlopen=no
+ lt_cv_dlopen_libs=
+
+ case $host_os in
+ beos*)
+ lt_cv_dlopen=load_add_on
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ;;
+
+ mingw* | pw32* | cegcc*)
+ lt_cv_dlopen=LoadLibrary
+ lt_cv_dlopen_libs=
+ ;;
+
+ cygwin*)
+ lt_cv_dlopen=dlopen
+ lt_cv_dlopen_libs=
+ ;;
+
+ darwin*)
+ # if libdl is installed we need to link against it
+ AC_CHECK_LIB([dl], [dlopen],
+ [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[
+ lt_cv_dlopen=dyld
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=yes
+ ])
+ ;;
+
+ tpf*)
+ # Don't try to run any link tests for TPF. We know it's impossible
+ # because TPF is a cross-compiler, and we know how we open DSOs.
+ lt_cv_dlopen=dlopen
+ lt_cv_dlopen_libs=
+ lt_cv_dlopen_self=no
+ ;;
+
+ *)
+ AC_CHECK_FUNC([shl_load],
+ [lt_cv_dlopen=shl_load],
+ [AC_CHECK_LIB([dld], [shl_load],
+ [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld],
+ [AC_CHECK_FUNC([dlopen],
+ [lt_cv_dlopen=dlopen],
+ [AC_CHECK_LIB([dl], [dlopen],
+ [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],
+ [AC_CHECK_LIB([svld], [dlopen],
+ [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld],
+ [AC_CHECK_LIB([dld], [dld_link],
+ [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld])
+ ])
+ ])
+ ])
+ ])
+ ])
+ ;;
+ esac
+
+ if test no = "$lt_cv_dlopen"; then
+ enable_dlopen=no
+ else
+ enable_dlopen=yes
+ fi
+
+ case $lt_cv_dlopen in
+ dlopen)
+ save_CPPFLAGS=$CPPFLAGS
+ test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+ save_LDFLAGS=$LDFLAGS
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+ save_LIBS=$LIBS
+ LIBS="$lt_cv_dlopen_libs $LIBS"
+
+ AC_CACHE_CHECK([whether a program can dlopen itself],
+ lt_cv_dlopen_self, [dnl
+ _LT_TRY_DLOPEN_SELF(
+ lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,
+ lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)
+ ])
+
+ if test yes = "$lt_cv_dlopen_self"; then
+ wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\"
+ AC_CACHE_CHECK([whether a statically linked program can dlopen itself],
+ lt_cv_dlopen_self_static, [dnl
+ _LT_TRY_DLOPEN_SELF(
+ lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,
+ lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross)
+ ])
+ fi
+
+ CPPFLAGS=$save_CPPFLAGS
+ LDFLAGS=$save_LDFLAGS
+ LIBS=$save_LIBS
+ ;;
+ esac
+
+ case $lt_cv_dlopen_self in
+ yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+ *) enable_dlopen_self=unknown ;;
+ esac
+
+ case $lt_cv_dlopen_self_static in
+ yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+ *) enable_dlopen_self_static=unknown ;;
+ esac
+fi
+_LT_DECL([dlopen_support], [enable_dlopen], [0],
+ [Whether dlopen is supported])
+_LT_DECL([dlopen_self], [enable_dlopen_self], [0],
+ [Whether dlopen of programs is supported])
+_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0],
+ [Whether dlopen of statically linked programs is supported])
+])# LT_SYS_DLOPEN_SELF
+
+# Old name:
+AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], [])
+
+
+# _LT_COMPILER_C_O([TAGNAME])
+# ---------------------------
+# Check to see if options -c and -o are simultaneously supported by compiler.
+# This macro does not hard code the compiler like AC_PROG_CC_C_O.
+m4_defun([_LT_COMPILER_C_O],
+[m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
+ [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)],
+ [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no
+ $RM -r conftest 2>/dev/null
+ mkdir conftest
+ cd conftest
+ mkdir out
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ lt_compiler_flag="-o out/conftest2.$ac_objext"
+ # Insert the option either (1) after the last *FLAGS variable, or
+ # (2) before a word containing "conftest.", or (3) at the end.
+ # Note that $ac_compile itself does not contain backslashes and begins
+ # with a dollar sign (not a hyphen), so the echo should work correctly.
+ lt_compile=`echo "$ac_compile" | $SED \
+ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
+ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+ -e 's:$: $lt_compiler_flag:'`
+ (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+ (eval "$lt_compile" 2>out/conftest.err)
+ ac_status=$?
+ cat out/conftest.err >&AS_MESSAGE_LOG_FD
+ echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+ if (exit $ac_status) && test -s out/conftest2.$ac_objext
+ then
+ # The compiler can only warn and ignore the option if not recognized
+ # So say no if there are warnings
+ $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp
+ $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2
+ if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then
+ _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+ fi
+ fi
+ chmod u+w . 2>&AS_MESSAGE_LOG_FD
+ $RM conftest*
+ # SGI C++ compiler will create directory out/ii_files/ for
+ # template instantiation
+ test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files
+ $RM out/* && rmdir out
+ cd ..
+ $RM -r conftest
+ $RM conftest*
+])
+_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1],
+ [Does compiler simultaneously support -c and -o options?])
+])# _LT_COMPILER_C_O
+
+
+# _LT_COMPILER_FILE_LOCKS([TAGNAME])
+# ----------------------------------
+# Check to see if we can do hard links to lock some files if needed
+m4_defun([_LT_COMPILER_FILE_LOCKS],
+[m4_require([_LT_ENABLE_LOCK])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+_LT_COMPILER_C_O([$1])
+
+hard_links=nottested
+if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then
+ # do not overwrite the value of need_locks provided by the user
+ AC_MSG_CHECKING([if we can lock with hard links])
+ hard_links=yes
+ $RM conftest*
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ touch conftest.a
+ ln conftest.a conftest.b 2>&5 || hard_links=no
+ ln conftest.a conftest.b 2>/dev/null && hard_links=no
+ AC_MSG_RESULT([$hard_links])
+ if test no = "$hard_links"; then
+ AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe])
+ need_locks=warn
+ fi
+else
+ need_locks=no
+fi
+_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?])
+])# _LT_COMPILER_FILE_LOCKS
+
+
+# _LT_CHECK_OBJDIR
+# ----------------
+m4_defun([_LT_CHECK_OBJDIR],
+[AC_CACHE_CHECK([for objdir], [lt_cv_objdir],
+[rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+ lt_cv_objdir=.libs
+else
+ # MS-DOS does not allow filenames that begin with a dot.
+ lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null])
+objdir=$lt_cv_objdir
+_LT_DECL([], [objdir], [0],
+ [The name of the directory that contains temporary libtool files])dnl
+m4_pattern_allow([LT_OBJDIR])dnl
+AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/",
+ [Define to the sub-directory where libtool stores uninstalled libraries.])
+])# _LT_CHECK_OBJDIR
+
+
+# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME])
+# --------------------------------------
+# Check hardcoding attributes.
+m4_defun([_LT_LINKER_HARDCODE_LIBPATH],
+[AC_MSG_CHECKING([how to hardcode library paths into programs])
+_LT_TAGVAR(hardcode_action, $1)=
+if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" ||
+ test -n "$_LT_TAGVAR(runpath_var, $1)" ||
+ test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then
+
+ # We can hardcode non-existent directories.
+ if test no != "$_LT_TAGVAR(hardcode_direct, $1)" &&
+ # If the only mechanism to avoid hardcoding is shlibpath_var, we
+ # have to relink, otherwise we might link with an installed library
+ # when we should be linking with a yet-to-be-installed one
+ ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" &&
+ test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then
+ # Linking always hardcodes the temporary library directory.
+ _LT_TAGVAR(hardcode_action, $1)=relink
+ else
+ # We can link without hardcoding, and we can hardcode nonexisting dirs.
+ _LT_TAGVAR(hardcode_action, $1)=immediate
+ fi
+else
+ # We cannot hardcode anything, or else we can only hardcode existing
+ # directories.
+ _LT_TAGVAR(hardcode_action, $1)=unsupported
+fi
+AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)])
+
+if test relink = "$_LT_TAGVAR(hardcode_action, $1)" ||
+ test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then
+ # Fast installation is not supported
+ enable_fast_install=no
+elif test yes = "$shlibpath_overrides_runpath" ||
+ test no = "$enable_shared"; then
+ # Fast installation is not necessary
+ enable_fast_install=needless
+fi
+_LT_TAGDECL([], [hardcode_action], [0],
+ [How to hardcode a shared library path into an executable])
+])# _LT_LINKER_HARDCODE_LIBPATH
+
+
+# _LT_CMD_STRIPLIB
+# ----------------
+m4_defun([_LT_CMD_STRIPLIB],
+[m4_require([_LT_DECL_EGREP])
+striplib=
+old_striplib=
+AC_MSG_CHECKING([whether stripping libraries is possible])
+if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
+ test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+ test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+ AC_MSG_RESULT([yes])
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+ case $host_os in
+ darwin*)
+ if test -n "$STRIP"; then
+ striplib="$STRIP -x"
+ old_striplib="$STRIP -S"
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ fi
+ ;;
+ *)
+ AC_MSG_RESULT([no])
+ ;;
+ esac
+fi
+_LT_DECL([], [old_striplib], [1], [Commands to strip libraries])
+_LT_DECL([], [striplib], [1])
+])# _LT_CMD_STRIPLIB
+
+
+# _LT_PREPARE_MUNGE_PATH_LIST
+# ---------------------------
+# Make sure func_munge_path_list() is defined correctly.
+m4_defun([_LT_PREPARE_MUNGE_PATH_LIST],
+[[# func_munge_path_list VARIABLE PATH
+# -----------------------------------
+# VARIABLE is name of variable containing _space_ separated list of
+# directories to be munged by the contents of PATH, which is string
+# having a format:
+# "DIR[:DIR]:"
+# string "DIR[ DIR]" will be prepended to VARIABLE
+# ":DIR[:DIR]"
+# string "DIR[ DIR]" will be appended to VARIABLE
+# "DIRP[:DIRP]::[DIRA:]DIRA"
+# string "DIRP[ DIRP]" will be prepended to VARIABLE and string
+# "DIRA[ DIRA]" will be appended to VARIABLE
+# "DIR[:DIR]"
+# VARIABLE will be replaced by "DIR[ DIR]"
+func_munge_path_list ()
+{
+ case x@S|@2 in
+ x)
+ ;;
+ *:)
+ eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\"
+ ;;
+ x:*)
+ eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\"
+ ;;
+ *::*)
+ eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\"
+ eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\"
+ ;;
+ *)
+ eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\"
+ ;;
+ esac
+}
+]])# _LT_PREPARE_PATH_LIST
+
+
+# _LT_SYS_DYNAMIC_LINKER([TAG])
+# -----------------------------
+# PORTME Fill in your ld.so characteristics
+m4_defun([_LT_SYS_DYNAMIC_LINKER],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_OBJDUMP])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_CHECK_SHELL_FEATURES])dnl
+m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl
+AC_MSG_CHECKING([dynamic linker characteristics])
+m4_if([$1],
+ [], [
+if test yes = "$GCC"; then
+ case $host_os in
+ darwin*) lt_awk_arg='/^libraries:/,/LR/' ;;
+ *) lt_awk_arg='/^libraries:/' ;;
+ esac
+ case $host_os in
+ mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;;
+ *) lt_sed_strip_eq='s|=/|/|g' ;;
+ esac
+ lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq`
+ case $lt_search_path_spec in
+ *\;*)
+ # if the path contains ";" then we assume it to be the separator
+ # otherwise default to the standard path separator (i.e. ":") - it is
+ # assumed that no part of a normal pathname contains ";" but that should
+ # okay in the real world where ";" in dirpaths is itself problematic.
+ lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'`
+ ;;
+ *)
+ lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"`
+ ;;
+ esac
+ # Ok, now we have the path, separated by spaces, we can step through it
+ # and add multilib dir if necessary...
+ lt_tmp_lt_search_path_spec=
+ lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null`
+ # ...but if some path component already ends with the multilib dir we assume
+ # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer).
+ case "$lt_multi_os_dir; $lt_search_path_spec " in
+ "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*)
+ lt_multi_os_dir=
+ ;;
+ esac
+ for lt_sys_path in $lt_search_path_spec; do
+ if test -d "$lt_sys_path$lt_multi_os_dir"; then
+ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir"
+ elif test -n "$lt_multi_os_dir"; then
+ test -d "$lt_sys_path" && \
+ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path"
+ fi
+ done
+ lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk '
+BEGIN {RS = " "; FS = "/|\n";} {
+ lt_foo = "";
+ lt_count = 0;
+ for (lt_i = NF; lt_i > 0; lt_i--) {
+ if ($lt_i != "" && $lt_i != ".") {
+ if ($lt_i == "..") {
+ lt_count++;
+ } else {
+ if (lt_count == 0) {
+ lt_foo = "/" $lt_i lt_foo;
+ } else {
+ lt_count--;
+ }
+ }
+ }
+ }
+ if (lt_foo != "") { lt_freq[[lt_foo]]++; }
+ if (lt_freq[[lt_foo]] == 1) { print lt_foo; }
+}'`
+ # AWK program above erroneously prepends '/' to C:/dos/paths
+ # for these hosts.
+ case $host_os in
+ mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\
+ $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;;
+ esac
+ sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP`
+else
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi])
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext_cmds=.so
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+AC_ARG_VAR([LT_SYS_LIBRARY_PATH],
+[User-defined run-time library search path.])
+
+case $host_os in
+aix3*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ library_names_spec='$libname$release$shared_ext$versuffix $libname.a'
+ shlibpath_var=LIBPATH
+
+ # AIX 3 has no versioning support, so we append a major version to the name.
+ soname_spec='$libname$release$shared_ext$major'
+ ;;
+
+aix[[4-9]]*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ hardcode_into_libs=yes
+ if test ia64 = "$host_cpu"; then
+ # AIX 5 supports IA64
+ library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext'
+ shlibpath_var=LD_LIBRARY_PATH
+ else
+ # With GCC up to 2.95.x, collect2 would create an import file
+ # for dependence libraries. The import file would start with
+ # the line '#! .'. This would cause the generated library to
+ # depend on '.', always an invalid library. This was fixed in
+ # development snapshots of GCC prior to 3.0.
+ case $host_os in
+ aix4 | aix4.[[01]] | aix4.[[01]].*)
+ if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+ echo ' yes '
+ echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then
+ :
+ else
+ can_build_shared=no
+ fi
+ ;;
+ esac
+ # Using Import Files as archive members, it is possible to support
+ # filename-based versioning of shared library archives on AIX. While
+ # this would work for both with and without runtime linking, it will
+ # prevent static linking of such archives. So we do filename-based
+ # shared library versioning with .so extension only, which is used
+ # when both runtime linking and shared linking is enabled.
+ # Unfortunately, runtime linking may impact performance, so we do
+ # not want this to be the default eventually. Also, we use the
+ # versioned .so libs for executables only if there is the -brtl
+ # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only.
+ # To allow for filename-based versioning support, we need to create
+ # libNAME.so.V as an archive file, containing:
+ # *) an Import File, referring to the versioned filename of the
+ # archive as well as the shared archive member, telling the
+ # bitwidth (32 or 64) of that shared object, and providing the
+ # list of exported symbols of that shared object, eventually
+ # decorated with the 'weak' keyword
+ # *) the shared object with the F_LOADONLY flag set, to really avoid
+ # it being seen by the linker.
+ # At run time we better use the real file rather than another symlink,
+ # but for link time we create the symlink libNAME.so -> libNAME.so.V
+
+ case $with_aix_soname,$aix_use_runtimelinking in
+ # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct
+ # soname into executable. Probably we can add versioning support to
+ # collect2, so additional links can be useful in future.
+ aix,yes) # traditional libtool
+ dynamic_linker='AIX unversionable lib.so'
+ # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+ # instead of lib<name>.a to let people know that these are not
+ # typical AIX shared libraries.
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ ;;
+ aix,no) # traditional AIX only
+ dynamic_linker='AIX lib.a[(]lib.so.V[)]'
+ # We preserve .a as extension for shared libraries through AIX4.2
+ # and later when we are not doing run time linking.
+ library_names_spec='$libname$release.a $libname.a'
+ soname_spec='$libname$release$shared_ext$major'
+ ;;
+ svr4,*) # full svr4 only
+ dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]"
+ library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
+ # We do not specify a path in Import Files, so LIBPATH fires.
+ shlibpath_overrides_runpath=yes
+ ;;
+ *,yes) # both, prefer svr4
+ dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]"
+ library_names_spec='$libname$release$shared_ext$major $libname$shared_ext'
+ # unpreferred sharedlib libNAME.a needs extra handling
+ postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"'
+ postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"'
+ # We do not specify a path in Import Files, so LIBPATH fires.
+ shlibpath_overrides_runpath=yes
+ ;;
+ *,no) # both, prefer aix
+ dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]"
+ library_names_spec='$libname$release.a $libname.a'
+ soname_spec='$libname$release$shared_ext$major'
+ # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling
+ postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)'
+ postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"'
+ ;;
+ esac
+ shlibpath_var=LIBPATH
+ fi
+ ;;
+
+amigaos*)
+ case $host_cpu in
+ powerpc)
+ # Since July 2007 AmigaOS4 officially supports .so libraries.
+ # When compiling the executable, add -use-dynld -Lsobjs: to the compileline.
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ ;;
+ m68k)
+ library_names_spec='$libname.ixlibrary $libname.a'
+ # Create ${libname}_ixlibrary.a entries in /sys/libs.
+ finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+ ;;
+ esac
+ ;;
+
+beos*)
+ library_names_spec='$libname$shared_ext'
+ dynamic_linker="$host_os ld.so"
+ shlibpath_var=LIBRARY_PATH
+ ;;
+
+bsdi[[45]]*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+ # the default ld.so.conf also contains /usr/contrib/lib and
+ # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+ # libtool to hard-code these into programs
+ ;;
+
+cygwin* | mingw* | pw32* | cegcc*)
+ version_type=windows
+ shrext_cmds=.dll
+ need_version=no
+ need_lib_prefix=no
+
+ case $GCC,$cc_basename in
+ yes,*)
+ # gcc
+ library_names_spec='$libname.dll.a'
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \$file`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname~
+ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+ eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+ fi'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $RM \$dlpath'
+ shlibpath_overrides_runpath=yes
+
+ case $host_os in
+ cygwin*)
+ # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+ soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
+m4_if([$1], [],[
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"])
+ ;;
+ mingw* | cegcc*)
+ # MinGW DLLs use traditional 'lib' prefix
+ soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
+ ;;
+ pw32*)
+ # pw32 DLLs use 'pw' prefix rather than 'lib'
+ library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
+ ;;
+ esac
+ dynamic_linker='Win32 ld.exe'
+ ;;
+
+ *,cl*)
+ # Native MSVC
+ libname_spec='$name'
+ soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
+ library_names_spec='$libname.dll.lib'
+
+ case $build_os in
+ mingw*)
+ sys_lib_search_path_spec=
+ lt_save_ifs=$IFS
+ IFS=';'
+ for lt_path in $LIB
+ do
+ IFS=$lt_save_ifs
+ # Let DOS variable expansion print the short 8.3 style file name.
+ lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"`
+ sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path"
+ done
+ IFS=$lt_save_ifs
+ # Convert to MSYS style.
+ sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'`
+ ;;
+ cygwin*)
+ # Convert to unix form, then to dos form, then back to unix form
+ # but this time dos style (no spaces!) so that the unix form looks
+ # like /cygdrive/c/PROGRA~1:/cygdr...
+ sys_lib_search_path_spec=`cygpath --path --unix "$LIB"`
+ sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null`
+ sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ ;;
+ *)
+ sys_lib_search_path_spec=$LIB
+ if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then
+ # It is most probably a Windows format PATH.
+ sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+ else
+ sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"`
+ fi
+ # FIXME: find the short name or the path components, as spaces are
+ # common. (e.g. "Program Files" -> "PROGRA~1")
+ ;;
+ esac
+
+ # DLL is installed to $(libdir)/../bin by postinstall_cmds
+ postinstall_cmds='base_file=`basename \$file`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $RM \$dlpath'
+ shlibpath_overrides_runpath=yes
+ dynamic_linker='Win32 link.exe'
+ ;;
+
+ *)
+ # Assume MSVC wrapper
+ library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib'
+ dynamic_linker='Win32 ld.exe'
+ ;;
+ esac
+ # FIXME: first we should search . and the directory the executable is in
+ shlibpath_var=PATH
+ ;;
+
+darwin* | rhapsody*)
+ dynamic_linker="$host_os dyld"
+ version_type=darwin
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$major$shared_ext $libname$shared_ext'
+ soname_spec='$libname$release$major$shared_ext'
+ shlibpath_overrides_runpath=yes
+ shlibpath_var=DYLD_LIBRARY_PATH
+ shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
+m4_if([$1], [],[
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"])
+ sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+ ;;
+
+dgux*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+freebsd* | dragonfly*)
+ # DragonFly does not have aout. When/if they implement a new
+ # versioning mechanism, adjust this.
+ if test -x /usr/bin/objformat; then
+ objformat=`/usr/bin/objformat`
+ else
+ case $host_os in
+ freebsd[[23]].*) objformat=aout ;;
+ *) objformat=elf ;;
+ esac
+ fi
+ version_type=freebsd-$objformat
+ case $version_type in
+ freebsd-elf*)
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ need_version=no
+ need_lib_prefix=no
+ ;;
+ freebsd-*)
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+ need_version=yes
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_os in
+ freebsd2.*)
+ shlibpath_overrides_runpath=yes
+ ;;
+ freebsd3.[[01]]* | freebsdelf3.[[01]]*)
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \
+ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1)
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+ *) # from 4.6 on, and DragonFly
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+ esac
+ ;;
+
+haiku*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ dynamic_linker="$host_os runtime_loader"
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib'
+ hardcode_into_libs=yes
+ ;;
+
+hpux9* | hpux10* | hpux11*)
+ # Give a soname corresponding to the major version so that dld.sl refuses to
+ # link against other versions.
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ case $host_cpu in
+ ia64*)
+ shrext_cmds='.so'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.so"
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ if test 32 = "$HPUX_IA64_MODE"; then
+ sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+ sys_lib_dlsearch_path_spec=/usr/lib/hpux32
+ else
+ sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+ sys_lib_dlsearch_path_spec=/usr/lib/hpux64
+ fi
+ ;;
+ hppa*64*)
+ shrext_cmds='.sl'
+ hardcode_into_libs=yes
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+ shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+ *)
+ shrext_cmds='.sl'
+ dynamic_linker="$host_os dld.sl"
+ shlibpath_var=SHLIB_PATH
+ shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ ;;
+ esac
+ # HP-UX runs *really* slowly unless shared libraries are mode 555, ...
+ postinstall_cmds='chmod 555 $lib'
+ # or fails outright, so override atomically:
+ install_override_mode=555
+ ;;
+
+interix[[3-9]]*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $host_os in
+ nonstopux*) version_type=nonstopux ;;
+ *)
+ if test yes = "$lt_cv_prog_gnu_ld"; then
+ version_type=linux # correct to gnu/linux during the next big refactor
+ else
+ version_type=irix
+ fi ;;
+ esac
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='$libname$release$shared_ext$major'
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext'
+ case $host_os in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in # libtool.m4 will add one of these switches to LD
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+ libsuff= shlibsuff= libmagic=32-bit;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+ libsuff=32 shlibsuff=N32 libmagic=N32;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+ libsuff=64 shlibsuff=64 libmagic=64-bit;;
+ *) libsuff= shlibsuff= libmagic=never-match;;
+ esac
+ ;;
+ esac
+ shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff"
+ sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff"
+ hardcode_into_libs=yes
+ ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+ dynamic_linker=no
+ ;;
+
+linux*android*)
+ version_type=none # Android doesn't support versioned libraries.
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext'
+ soname_spec='$libname$release$shared_ext'
+ finish_cmds=
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ dynamic_linker='Android linker'
+ # Don't embed -rpath directories since the linker doesn't support them.
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ ;;
+
+# This must be glibc/ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+
+ # Some binutils ld are patched to set DT_RUNPATH
+ AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath],
+ [lt_cv_shlibpath_overrides_runpath=no
+ save_LDFLAGS=$LDFLAGS
+ save_libdir=$libdir
+ eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \
+ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\""
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])],
+ [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null],
+ [lt_cv_shlibpath_overrides_runpath=yes])])
+ LDFLAGS=$save_LDFLAGS
+ libdir=$save_libdir
+ ])
+ shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath
+
+ # This implies no fast_install, which is unacceptable.
+ # Some rework will be needed to allow for fast_install
+ # before this can be enabled.
+ hardcode_into_libs=yes
+
+ # Add ABI-specific directories to the system library path.
+ sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib"
+
+ # Ideally, we could use ldconfig to report *all* directores which are
+ # searched for libraries, however this is still not possible. Aside from not
+ # being certain /sbin/ldconfig is available, command
+ # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64,
+ # even though it is searched at run-time. Try to do the best guess by
+ # appending ld.so.conf contents (and includes) to the search path.
+ if test -f /etc/ld.so.conf; then
+ lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
+ sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra"
+ fi
+
+ # We used to test for /lib/ld.so.1 and disable shared libraries on
+ # powerpc, because MkLinux only supported shared libraries with the
+ # GNU dynamic linker. Since this was broken with cross compilers,
+ # most powerpc-linux boxes support dynamic linking these days and
+ # people can always --disable-shared, the test was removed, and we
+ # assume the GNU/Linux dynamic linker is in use.
+ dynamic_linker='GNU/Linux ld.so'
+ ;;
+
+netbsd*)
+ version_type=sunos
+ need_lib_prefix=no
+ need_version=no
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ dynamic_linker='NetBSD (a.out) ld.so'
+ else
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ dynamic_linker='NetBSD ld.elf_so'
+ fi
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ ;;
+
+newsos6)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+*nto* | *qnx*)
+ version_type=qnx
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ dynamic_linker='ldqnx.so'
+ ;;
+
+openbsd* | bitrig*)
+ version_type=sunos
+ sys_lib_dlsearch_path_spec=/usr/lib
+ need_lib_prefix=no
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+ need_version=no
+ else
+ need_version=yes
+ fi
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+ finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ ;;
+
+os2*)
+ libname_spec='$name'
+ version_type=windows
+ shrext_cmds=.dll
+ need_version=no
+ need_lib_prefix=no
+ # OS/2 can only load a DLL with a base name of 8 characters or less.
+ soname_spec='`test -n "$os2dllname" && libname="$os2dllname";
+ v=$($ECHO $release$versuffix | tr -d .-);
+ n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _);
+ $ECHO $n$v`$shared_ext'
+ library_names_spec='${libname}_dll.$libext'
+ dynamic_linker='OS/2 ld.exe'
+ shlibpath_var=BEGINLIBPATH
+ sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ postinstall_cmds='base_file=`basename \$file`~
+ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~
+ dldir=$destdir/`dirname \$dlpath`~
+ test -d \$dldir || mkdir -p \$dldir~
+ $install_prog $dir/$dlname \$dldir/$dlname~
+ chmod a+x \$dldir/$dlname~
+ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then
+ eval '\''$striplib \$dldir/$dlname'\'' || exit \$?;
+ fi'
+ postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~
+ dlpath=$dir/\$dldll~
+ $RM \$dlpath'
+ ;;
+
+osf3* | osf4* | osf5*)
+ version_type=osf
+ need_lib_prefix=no
+ need_version=no
+ soname_spec='$libname$release$shared_ext$major'
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ shlibpath_var=LD_LIBRARY_PATH
+ sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+ sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+ ;;
+
+rdos*)
+ dynamic_linker=no
+ ;;
+
+solaris*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ # ldd complains unless libraries are executable
+ postinstall_cmds='chmod +x $lib'
+ ;;
+
+sunos4*)
+ version_type=sunos
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix'
+ finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ if test yes = "$with_gnu_ld"; then
+ need_lib_prefix=no
+ fi
+ need_version=yes
+ ;;
+
+sysv4 | sysv4.3*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ case $host_vendor in
+ sni)
+ shlibpath_overrides_runpath=no
+ need_lib_prefix=no
+ runpath_var=LD_RUN_PATH
+ ;;
+ siemens)
+ need_lib_prefix=no
+ ;;
+ motorola)
+ need_lib_prefix=no
+ need_version=no
+ shlibpath_overrides_runpath=no
+ sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+ ;;
+ esac
+ ;;
+
+sysv4*MP*)
+ if test -d /usr/nec; then
+ version_type=linux # correct to gnu/linux during the next big refactor
+ library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext'
+ soname_spec='$libname$shared_ext.$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ fi
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ version_type=sco
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=yes
+ hardcode_into_libs=yes
+ if test yes = "$with_gnu_ld"; then
+ sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib'
+ else
+ sys_lib_search_path_spec='/usr/ccs/lib /usr/lib'
+ case $host_os in
+ sco3.2v5*)
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /lib"
+ ;;
+ esac
+ fi
+ sys_lib_dlsearch_path_spec='/usr/lib'
+ ;;
+
+tpf*)
+ # TPF is a cross-target only. Preferred cross-host = GNU/Linux.
+ version_type=linux # correct to gnu/linux during the next big refactor
+ need_lib_prefix=no
+ need_version=no
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ shlibpath_var=LD_LIBRARY_PATH
+ shlibpath_overrides_runpath=no
+ hardcode_into_libs=yes
+ ;;
+
+uts4*)
+ version_type=linux # correct to gnu/linux during the next big refactor
+ library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext'
+ soname_spec='$libname$release$shared_ext$major'
+ shlibpath_var=LD_LIBRARY_PATH
+ ;;
+
+*)
+ dynamic_linker=no
+ ;;
+esac
+AC_MSG_RESULT([$dynamic_linker])
+test no = "$dynamic_linker" && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test yes = "$GCC"; then
+ variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then
+ sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec
+fi
+
+if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then
+ sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec
+fi
+
+# remember unaugmented sys_lib_dlsearch_path content for libtool script decls...
+configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec
+
+# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code
+func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH"
+
+# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool
+configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH
+
+_LT_DECL([], [variables_saved_for_relink], [1],
+ [Variables whose values should be saved in libtool wrapper scripts and
+ restored at link time])
+_LT_DECL([], [need_lib_prefix], [0],
+ [Do we need the "lib" prefix for modules?])
+_LT_DECL([], [need_version], [0], [Do we need a version for libraries?])
+_LT_DECL([], [version_type], [0], [Library versioning type])
+_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable])
+_LT_DECL([], [shlibpath_var], [0],[Shared library path variable])
+_LT_DECL([], [shlibpath_overrides_runpath], [0],
+ [Is shlibpath searched before the hard-coded library search path?])
+_LT_DECL([], [libname_spec], [1], [Format of library name prefix])
+_LT_DECL([], [library_names_spec], [1],
+ [[List of archive names. First name is the real one, the rest are links.
+ The last name is the one that the linker finds with -lNAME]])
+_LT_DECL([], [soname_spec], [1],
+ [[The coded name of the library, if different from the real name]])
+_LT_DECL([], [install_override_mode], [1],
+ [Permission mode override for installation of shared libraries])
+_LT_DECL([], [postinstall_cmds], [2],
+ [Command to use after installation of a shared archive])
+_LT_DECL([], [postuninstall_cmds], [2],
+ [Command to use after uninstallation of a shared archive])
+_LT_DECL([], [finish_cmds], [2],
+ [Commands used to finish a libtool library installation in a directory])
+_LT_DECL([], [finish_eval], [1],
+ [[As "finish_cmds", except a single script fragment to be evaled but
+ not shown]])
+_LT_DECL([], [hardcode_into_libs], [0],
+ [Whether we should hardcode library paths into libraries])
+_LT_DECL([], [sys_lib_search_path_spec], [2],
+ [Compile-time system search path for libraries])
+_LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2],
+ [Detected run-time system search path for libraries])
+_LT_DECL([], [configure_time_lt_sys_library_path], [2],
+ [Explicit LT_SYS_LIBRARY_PATH set during ./configure time])
+])# _LT_SYS_DYNAMIC_LINKER
+
+
+# _LT_PATH_TOOL_PREFIX(TOOL)
+# --------------------------
+# find a file program that can recognize shared library
+AC_DEFUN([_LT_PATH_TOOL_PREFIX],
+[m4_require([_LT_DECL_EGREP])dnl
+AC_MSG_CHECKING([for $1])
+AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
+[case $MAGIC_CMD in
+[[\\/*] | ?:[\\/]*])
+ lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path.
+ ;;
+*)
+ lt_save_MAGIC_CMD=$MAGIC_CMD
+ lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+dnl $ac_dummy forces splitting on constant user-supplied paths.
+dnl POSIX.2 word splitting is done only on the output of word expansions,
+dnl not every word. This closes a longstanding sh security hole.
+ ac_dummy="m4_if([$2], , $PATH, [$2])"
+ for ac_dir in $ac_dummy; do
+ IFS=$lt_save_ifs
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$1"; then
+ lt_cv_path_MAGIC_CMD=$ac_dir/"$1"
+ if test -n "$file_magic_test_file"; then
+ case $deplibs_check_method in
+ "file_magic "*)
+ file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"`
+ MAGIC_CMD=$lt_cv_path_MAGIC_CMD
+ if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+ $EGREP "$file_magic_regex" > /dev/null; then
+ :
+ else
+ cat <<_LT_EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such. This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem. Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+_LT_EOF
+ fi ;;
+ esac
+ fi
+ break
+ fi
+ done
+ IFS=$lt_save_ifs
+ MAGIC_CMD=$lt_save_MAGIC_CMD
+ ;;
+esac])
+MAGIC_CMD=$lt_cv_path_MAGIC_CMD
+if test -n "$MAGIC_CMD"; then
+ AC_MSG_RESULT($MAGIC_CMD)
+else
+ AC_MSG_RESULT(no)
+fi
+_LT_DECL([], [MAGIC_CMD], [0],
+ [Used to examine libraries when file_magic_cmd begins with "file"])dnl
+])# _LT_PATH_TOOL_PREFIX
+
+# Old name:
+AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], [])
+
+
+# _LT_PATH_MAGIC
+# --------------
+# find a file program that can recognize a shared library
+m4_defun([_LT_PATH_MAGIC],
+[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+ if test -n "$ac_tool_prefix"; then
+ _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH)
+ else
+ MAGIC_CMD=:
+ fi
+fi
+])# _LT_PATH_MAGIC
+
+
+# LT_PATH_LD
+# ----------
+# find the pathname to the GNU or non-GNU linker
+AC_DEFUN([LT_PATH_LD],
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_PROG_ECHO_BACKSLASH])dnl
+
+AC_ARG_WITH([gnu-ld],
+ [AS_HELP_STRING([--with-gnu-ld],
+ [assume the C compiler uses GNU ld @<:@default=no@:>@])],
+ [test no = "$withval" || with_gnu_ld=yes],
+ [with_gnu_ld=no])dnl
+
+ac_prog=ld
+if test yes = "$GCC"; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ AC_MSG_CHECKING([for ld used by $CC])
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return, which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [[\\/]]* | ?:[[\\/]]*)
+ re_direlt='/[[^/]][[^/]]*/\.\./'
+ # Canonicalize the pathname of ld
+ ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'`
+ while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD=$ac_prog
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test yes = "$with_gnu_ld"; then
+ AC_MSG_CHECKING([for GNU ld])
+else
+ AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(lt_cv_path_LD,
+[if test -z "$LD"; then
+ lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH; do
+ IFS=$lt_save_ifs
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ lt_cv_path_LD=$ac_dir/$ac_prog
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some variants of GNU ld only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+ *GNU* | *'with BFD'*)
+ test no != "$with_gnu_ld" && break
+ ;;
+ *)
+ test yes != "$with_gnu_ld" && break
+ ;;
+ esac
+ fi
+ done
+ IFS=$lt_save_ifs
+else
+ lt_cv_path_LD=$LD # Let the user override the test with a path.
+fi])
+LD=$lt_cv_path_LD
+if test -n "$LD"; then
+ AC_MSG_RESULT($LD)
+else
+ AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+_LT_PATH_LD_GNU
+AC_SUBST([LD])
+
+_LT_TAGDECL([], [LD], [1], [The linker used to build libraries])
+])# LT_PATH_LD
+
+# Old names:
+AU_ALIAS([AM_PROG_LD], [LT_PATH_LD])
+AU_ALIAS([AC_PROG_LD], [LT_PATH_LD])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_PROG_LD], [])
+dnl AC_DEFUN([AC_PROG_LD], [])
+
+
+# _LT_PATH_LD_GNU
+#- --------------
+m4_defun([_LT_PATH_LD_GNU],
+[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ lt_cv_prog_gnu_ld=yes
+ ;;
+*)
+ lt_cv_prog_gnu_ld=no
+ ;;
+esac])
+with_gnu_ld=$lt_cv_prog_gnu_ld
+])# _LT_PATH_LD_GNU
+
+
+# _LT_CMD_RELOAD
+# --------------
+# find reload flag for linker
+# -- PORTME Some linkers may need a different reload flag.
+m4_defun([_LT_CMD_RELOAD],
+[AC_CACHE_CHECK([for $LD option to reload object files],
+ lt_cv_ld_reload_flag,
+ [lt_cv_ld_reload_flag='-r'])
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+case $host_os in
+ cygwin* | mingw* | pw32* | cegcc*)
+ if test yes != "$GCC"; then
+ reload_cmds=false
+ fi
+ ;;
+ darwin*)
+ if test yes = "$GCC"; then
+ reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs'
+ else
+ reload_cmds='$LD$reload_flag -o $output$reload_objs'
+ fi
+ ;;
+esac
+_LT_TAGDECL([], [reload_flag], [1], [How to create reloadable object files])dnl
+_LT_TAGDECL([], [reload_cmds], [2])dnl
+])# _LT_CMD_RELOAD
+
+
+# _LT_PATH_DD
+# -----------
+# find a working dd
+m4_defun([_LT_PATH_DD],
+[AC_CACHE_CHECK([for a working dd], [ac_cv_path_lt_DD],
+[printf 0123456789abcdef0123456789abcdef >conftest.i
+cat conftest.i conftest.i >conftest2.i
+: ${lt_DD:=$DD}
+AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd],
+[if "$ac_path_lt_DD" bs=32 count=1 <conftest2.i >conftest.out 2>/dev/null; then
+ cmp -s conftest.i conftest.out \
+ && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=:
+fi])
+rm -f conftest.i conftest2.i conftest.out])
+])# _LT_PATH_DD
+
+
+# _LT_CMD_TRUNCATE
+# ----------------
+# find command to truncate a binary pipe
+m4_defun([_LT_CMD_TRUNCATE],
+[m4_require([_LT_PATH_DD])
+AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin],
+[printf 0123456789abcdef0123456789abcdef >conftest.i
+cat conftest.i conftest.i >conftest2.i
+lt_cv_truncate_bin=
+if "$ac_cv_path_lt_DD" bs=32 count=1 <conftest2.i >conftest.out 2>/dev/null; then
+ cmp -s conftest.i conftest.out \
+ && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1"
+fi
+rm -f conftest.i conftest2.i conftest.out
+test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"])
+_LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1],
+ [Command to truncate a binary pipe])
+])# _LT_CMD_TRUNCATE
+
+
+# _LT_CHECK_MAGIC_METHOD
+# ----------------------
+# how to check for library dependencies
+# -- PORTME fill in with the dynamic library characteristics
+m4_defun([_LT_CHECK_MAGIC_METHOD],
+[m4_require([_LT_DECL_EGREP])
+m4_require([_LT_DECL_OBJDUMP])
+AC_CACHE_CHECK([how to recognize dependent libraries],
+lt_cv_deplibs_check_method,
+[lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# 'unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# that responds to the $file_magic_cmd with a given extended regex.
+# If you have 'file' or equivalent on your system and you're not sure
+# whether 'pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix[[4-9]]*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+beos*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+bsdi[[45]]*)
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
+ lt_cv_file_magic_cmd='/usr/bin/file -L'
+ lt_cv_file_magic_test_file=/shlib/libc.so
+ ;;
+
+cygwin*)
+ # func_win32_libid is a shell function defined in ltmain.sh
+ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+ lt_cv_file_magic_cmd='func_win32_libid'
+ ;;
+
+mingw* | pw32*)
+ # Base MSYS/MinGW do not provide the 'file' command needed by
+ # func_win32_libid shell function, so use a weaker test based on 'objdump',
+ # unless we find 'file', for example because we are cross-compiling.
+ if ( file / ) >/dev/null 2>&1; then
+ lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+ lt_cv_file_magic_cmd='func_win32_libid'
+ else
+ # Keep this pattern in sync with the one in func_win32_libid.
+ lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)'
+ lt_cv_file_magic_cmd='$OBJDUMP -f'
+ fi
+ ;;
+
+cegcc*)
+ # use the weaker test based on 'objdump'. See mingw*.
+ lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?'
+ lt_cv_file_magic_cmd='$OBJDUMP -f'
+ ;;
+
+darwin* | rhapsody*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+freebsd* | dragonfly*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+ case $host_cpu in
+ i*86 )
+ # Not sure whether the presence of OpenBSD here was a mistake.
+ # Let's accept both of them until this is cleared up.
+ lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+ ;;
+ esac
+ else
+ lt_cv_deplibs_check_method=pass_all
+ fi
+ ;;
+
+haiku*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+hpux10.20* | hpux11*)
+ lt_cv_file_magic_cmd=/usr/bin/file
+ case $host_cpu in
+ ia64*)
+ lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
+ lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+ ;;
+ hppa*64*)
+ [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]']
+ lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+ ;;
+ *)
+ lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library'
+ lt_cv_file_magic_test_file=/usr/lib/libc.sl
+ ;;
+ esac
+ ;;
+
+interix[[3-9]]*)
+ # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$'
+ ;;
+
+irix5* | irix6* | nonstopux*)
+ case $LD in
+ *-32|*"-32 ") libmagic=32-bit;;
+ *-n32|*"-n32 ") libmagic=N32;;
+ *-64|*"-64 ") libmagic=64-bit;;
+ *) libmagic=never-match;;
+ esac
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+# This must be glibc/ELF.
+linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+netbsd*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$'
+ fi
+ ;;
+
+newos6*)
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
+ lt_cv_file_magic_cmd=/usr/bin/file
+ lt_cv_file_magic_test_file=/usr/lib/libnls.so
+ ;;
+
+*nto* | *qnx*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+openbsd* | bitrig*)
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$'
+ else
+ lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+ fi
+ ;;
+
+osf3* | osf4* | osf5*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+rdos*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+solaris*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+
+sysv4 | sysv4.3*)
+ case $host_vendor in
+ motorola)
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
+ lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+ ;;
+ ncr)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ sequent)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
+ ;;
+ sni)
+ lt_cv_file_magic_cmd='/bin/file'
+ lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
+ lt_cv_file_magic_test_file=/lib/libc.so
+ ;;
+ siemens)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ pc)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+ esac
+ ;;
+
+tpf*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+os2*)
+ lt_cv_deplibs_check_method=pass_all
+ ;;
+esac
+])
+
+file_magic_glob=
+want_nocaseglob=no
+if test "$build" = "$host"; then
+ case $host_os in
+ mingw* | pw32*)
+ if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then
+ want_nocaseglob=yes
+ else
+ file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"`
+ fi
+ ;;
+ esac
+fi
+
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+
+_LT_DECL([], [deplibs_check_method], [1],
+ [Method to check whether dependent libraries are shared objects])
+_LT_DECL([], [file_magic_cmd], [1],
+ [Command to use when deplibs_check_method = "file_magic"])
+_LT_DECL([], [file_magic_glob], [1],
+ [How to find potential files when deplibs_check_method = "file_magic"])
+_LT_DECL([], [want_nocaseglob], [1],
+ [Find potential files using nocaseglob when deplibs_check_method = "file_magic"])
+])# _LT_CHECK_MAGIC_METHOD
+
+
+# LT_PATH_NM
+# ----------
+# find the pathname to a BSD- or MS-compatible name lister
+AC_DEFUN([LT_PATH_NM],
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM,
+[if test -n "$NM"; then
+ # Let the user override the test.
+ lt_cv_path_NM=$NM
+else
+ lt_nm_to_check=${ac_tool_prefix}nm
+ if test -n "$ac_tool_prefix" && test "$build" = "$host"; then
+ lt_nm_to_check="$lt_nm_to_check nm"
+ fi
+ for lt_tmp_nm in $lt_nm_to_check; do
+ lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do
+ IFS=$lt_save_ifs
+ test -z "$ac_dir" && ac_dir=.
+ tmp_nm=$ac_dir/$lt_tmp_nm
+ if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then
+ # Check to see if the nm accepts a BSD-compat flag.
+ # Adding the 'sed 1q' prevents false positives on HP-UX, which says:
+ # nm: unknown option "B" ignored
+ # Tru64's nm complains that /dev/null is an invalid object file
+ # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty
+ case $build_os in
+ mingw*) lt_bad_file=conftest.nm/nofile ;;
+ *) lt_bad_file=/dev/null ;;
+ esac
+ case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in
+ *$lt_bad_file* | *'Invalid file or object type'*)
+ lt_cv_path_NM="$tmp_nm -B"
+ break 2
+ ;;
+ *)
+ case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+ */dev/null*)
+ lt_cv_path_NM="$tmp_nm -p"
+ break 2
+ ;;
+ *)
+ lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+ continue # so that we can try to find one that supports BSD flags
+ ;;
+ esac
+ ;;
+ esac
+ fi
+ done
+ IFS=$lt_save_ifs
+ done
+ : ${lt_cv_path_NM=no}
+fi])
+if test no != "$lt_cv_path_NM"; then
+ NM=$lt_cv_path_NM
+else
+ # Didn't find any BSD compatible name lister, look for dumpbin.
+ if test -n "$DUMPBIN"; then :
+ # Let the user override the test.
+ else
+ AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :)
+ case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in
+ *COFF*)
+ DUMPBIN="$DUMPBIN -symbols -headers"
+ ;;
+ *)
+ DUMPBIN=:
+ ;;
+ esac
+ fi
+ AC_SUBST([DUMPBIN])
+ if test : != "$DUMPBIN"; then
+ NM=$DUMPBIN
+ fi
+fi
+test -z "$NM" && NM=nm
+AC_SUBST([NM])
+_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl
+
+AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface],
+ [lt_cv_nm_interface="BSD nm"
+ echo "int some_variable = 0;" > conftest.$ac_ext
+ (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD)
+ (eval "$ac_compile" 2>conftest.err)
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD)
+ (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD)
+ cat conftest.out >&AS_MESSAGE_LOG_FD
+ if $GREP 'External.*some_variable' conftest.out > /dev/null; then
+ lt_cv_nm_interface="MS dumpbin"
+ fi
+ rm -f conftest*])
+])# LT_PATH_NM
+
+# Old names:
+AU_ALIAS([AM_PROG_NM], [LT_PATH_NM])
+AU_ALIAS([AC_PROG_NM], [LT_PATH_NM])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_PROG_NM], [])
+dnl AC_DEFUN([AC_PROG_NM], [])
+
+# _LT_CHECK_SHAREDLIB_FROM_LINKLIB
+# --------------------------------
+# how to determine the name of the shared library
+# associated with a specific link library.
+# -- PORTME fill in with the dynamic library characteristics
+m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB],
+[m4_require([_LT_DECL_EGREP])
+m4_require([_LT_DECL_OBJDUMP])
+m4_require([_LT_DECL_DLLTOOL])
+AC_CACHE_CHECK([how to associate runtime and link libraries],
+lt_cv_sharedlib_from_linklib_cmd,
+[lt_cv_sharedlib_from_linklib_cmd='unknown'
+
+case $host_os in
+cygwin* | mingw* | pw32* | cegcc*)
+ # two different shell functions defined in ltmain.sh;
+ # decide which one to use based on capabilities of $DLLTOOL
+ case `$DLLTOOL --help 2>&1` in
+ *--identify-strict*)
+ lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib
+ ;;
+ *)
+ lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback
+ ;;
+ esac
+ ;;
+*)
+ # fallback: assume linklib IS sharedlib
+ lt_cv_sharedlib_from_linklib_cmd=$ECHO
+ ;;
+esac
+])
+sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd
+test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO
+
+_LT_DECL([], [sharedlib_from_linklib_cmd], [1],
+ [Command to associate shared and link libraries])
+])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB
+
+
+# _LT_PATH_MANIFEST_TOOL
+# ----------------------
+# locate the manifest tool
+m4_defun([_LT_PATH_MANIFEST_TOOL],
+[AC_CHECK_TOOL(MANIFEST_TOOL, mt, :)
+test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt
+AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool],
+ [lt_cv_path_mainfest_tool=no
+ echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD
+ $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out
+ cat conftest.err >&AS_MESSAGE_LOG_FD
+ if $GREP 'Manifest Tool' conftest.out > /dev/null; then
+ lt_cv_path_mainfest_tool=yes
+ fi
+ rm -f conftest*])
+if test yes != "$lt_cv_path_mainfest_tool"; then
+ MANIFEST_TOOL=:
+fi
+_LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl
+])# _LT_PATH_MANIFEST_TOOL
+
+
+# _LT_DLL_DEF_P([FILE])
+# ---------------------
+# True iff FILE is a Windows DLL '.def' file.
+# Keep in sync with func_dll_def_p in the libtool script
+AC_DEFUN([_LT_DLL_DEF_P],
+[dnl
+ test DEF = "`$SED -n dnl
+ -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace
+ -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments
+ -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl
+ -e q dnl Only consider the first "real" line
+ $1`" dnl
+])# _LT_DLL_DEF_P
+
+
+# LT_LIB_M
+# --------
+# check for math library
+AC_DEFUN([LT_LIB_M],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+LIBM=
+case $host in
+*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*)
+ # These system don't have libm, or don't need it
+ ;;
+*-ncr-sysv4.3*)
+ AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw)
+ AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
+ ;;
+*)
+ AC_CHECK_LIB(m, cos, LIBM=-lm)
+ ;;
+esac
+AC_SUBST([LIBM])
+])# LT_LIB_M
+
+# Old name:
+AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_CHECK_LIBM], [])
+
+
+# _LT_COMPILER_NO_RTTI([TAGNAME])
+# -------------------------------
+m4_defun([_LT_COMPILER_NO_RTTI],
+[m4_require([_LT_TAG_COMPILER])dnl
+
+_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+
+if test yes = "$GCC"; then
+ case $cc_basename in
+ nvcc*)
+ _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;;
+ esac
+
+ _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],
+ lt_cv_prog_compiler_rtti_exceptions,
+ [-fno-rtti -fno-exceptions], [],
+ [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"])
+fi
+_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1],
+ [Compiler flag to turn off builtin functions])
+])# _LT_COMPILER_NO_RTTI
+
+
+# _LT_CMD_GLOBAL_SYMBOLS
+# ----------------------
+m4_defun([_LT_CMD_GLOBAL_SYMBOLS],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+AC_REQUIRE([LT_PATH_LD])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+AC_MSG_CHECKING([command to parse $NM output from $compiler object])
+AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe],
+[
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix. What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[[BCDEGRST]]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+ symcode='[[BCDT]]'
+ ;;
+cygwin* | mingw* | pw32* | cegcc*)
+ symcode='[[ABCDGISTW]]'
+ ;;
+hpux*)
+ if test ia64 = "$host_cpu"; then
+ symcode='[[ABCDEGRST]]'
+ fi
+ ;;
+irix* | nonstopux*)
+ symcode='[[BCDEGRST]]'
+ ;;
+osf*)
+ symcode='[[BCDEGQRST]]'
+ ;;
+solaris*)
+ symcode='[[BDRT]]'
+ ;;
+sco3.2v5*)
+ symcode='[[DT]]'
+ ;;
+sysv4.2uw2*)
+ symcode='[[DT]]'
+ ;;
+sysv5* | sco5v6* | unixware* | OpenUNIX*)
+ symcode='[[ABDT]]'
+ ;;
+sysv4)
+ symcode='[[DFNSTU]]'
+ ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+ symcode='[[ABCDGIRSTW]]' ;;
+esac
+
+if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+ # Gets list of data symbols to import.
+ lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'"
+ # Adjust the below global symbol transforms to fixup imported variables.
+ lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'"
+ lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'"
+ lt_c_name_lib_hook="\
+ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\
+ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'"
+else
+ # Disable hooks by default.
+ lt_cv_sys_global_symbol_to_import=
+ lt_cdecl_hook=
+ lt_c_name_hook=
+ lt_c_name_lib_hook=
+fi
+
+# Transform an extracted symbol line into a proper C declaration.
+# Some systems (esp. on ia64) link data and code symbols differently,
+# so use this general approach.
+lt_cv_sys_global_symbol_to_cdecl="sed -n"\
+$lt_cdecl_hook\
+" -e 's/^T .* \(.*\)$/extern int \1();/p'"\
+" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n"\
+$lt_c_name_hook\
+" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\
+" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'"
+
+# Transform an extracted symbol line into symbol name with lib prefix and
+# symbol address.
+lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\
+$lt_c_name_lib_hook\
+" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\
+" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\
+" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'"
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+ opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+ ;;
+esac
+
+# Try without a prefix underscore, then with it.
+for ac_symprfx in "" "_"; do
+
+ # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol.
+ symxfrm="\\1 $ac_symprfx\\2 \\2"
+
+ # Write the raw and C identifiers.
+ if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+ # Fake it for dumpbin and say T for any non-static function,
+ # D for any global variable and I for any imported variable.
+ # Also find C++ and __fastcall symbols from MSVC++,
+ # which start with @ or ?.
+ lt_cv_sys_global_symbol_pipe="$AWK ['"\
+" {last_section=section; section=\$ 3};"\
+" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\
+" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\
+" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\
+" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\
+" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\
+" \$ 0!~/External *\|/{next};"\
+" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\
+" {if(hide[section]) next};"\
+" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\
+" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\
+" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\
+" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\
+" ' prfx=^$ac_symprfx]"
+ else
+ lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
+ fi
+ lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'"
+
+ # Check to see that the pipe works correctly.
+ pipe_works=no
+
+ rm -f conftest*
+ cat > conftest.$ac_ext <<_LT_EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(void);
+void nm_test_func(void){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+_LT_EOF
+
+ if AC_TRY_EVAL(ac_compile); then
+ # Now try to grab the symbols.
+ nlist=conftest.nm
+ if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then
+ # Try sorting and uniquifying the output.
+ if sort "$nlist" | uniq > "$nlist"T; then
+ mv -f "$nlist"T "$nlist"
+ else
+ rm -f "$nlist"T
+ fi
+
+ # Make sure that we snagged all the symbols we need.
+ if $GREP ' nm_test_var$' "$nlist" >/dev/null; then
+ if $GREP ' nm_test_func$' "$nlist" >/dev/null; then
+ cat <<_LT_EOF > conftest.$ac_ext
+/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */
+#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE
+/* DATA imports from DLLs on WIN32 can't be const, because runtime
+ relocations are performed -- see ld's documentation on pseudo-relocs. */
+# define LT@&t@_DLSYM_CONST
+#elif defined __osf__
+/* This system does not cope well with relocations in const data. */
+# define LT@&t@_DLSYM_CONST
+#else
+# define LT@&t@_DLSYM_CONST const
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+_LT_EOF
+ # Now generate the symbol file.
+ eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext'
+
+ cat <<_LT_EOF >> conftest.$ac_ext
+
+/* The mapping between symbol names and symbols. */
+LT@&t@_DLSYM_CONST struct {
+ const char *name;
+ void *address;
+}
+lt__PROGRAM__LTX_preloaded_symbols[[]] =
+{
+ { "@PROGRAM@", (void *) 0 },
+_LT_EOF
+ $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext
+ cat <<\_LT_EOF >> conftest.$ac_ext
+ {0, (void *) 0}
+};
+
+/* This works around a problem in FreeBSD linker */
+#ifdef FREEBSD_WORKAROUND
+static const void *lt_preloaded_setup() {
+ return lt__PROGRAM__LTX_preloaded_symbols;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+_LT_EOF
+ # Now try linking the two files.
+ mv conftest.$ac_objext conftstm.$ac_objext
+ lt_globsym_save_LIBS=$LIBS
+ lt_globsym_save_CFLAGS=$CFLAGS
+ LIBS=conftstm.$ac_objext
+ CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)"
+ if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then
+ pipe_works=yes
+ fi
+ LIBS=$lt_globsym_save_LIBS
+ CFLAGS=$lt_globsym_save_CFLAGS
+ else
+ echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD
+ fi
+ else
+ echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD
+ fi
+ else
+ echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
+ fi
+ else
+ echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD
+ cat conftest.$ac_ext >&5
+ fi
+ rm -rf conftest* conftst*
+
+ # Do not use the global_symbol_pipe unless it works.
+ if test yes = "$pipe_works"; then
+ break
+ else
+ lt_cv_sys_global_symbol_pipe=
+ fi
+done
+])
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+ lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+ AC_MSG_RESULT(failed)
+else
+ AC_MSG_RESULT(ok)
+fi
+
+# Response file support.
+if test "$lt_cv_nm_interface" = "MS dumpbin"; then
+ nm_file_list_spec='@'
+elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then
+ nm_file_list_spec='@'
+fi
+
+_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1],
+ [Take the output of nm and produce a listing of raw symbols and C names])
+_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1],
+ [Transform the output of nm in a proper C declaration])
+_LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1],
+ [Transform the output of nm into a list of symbols to manually relocate])
+_LT_DECL([global_symbol_to_c_name_address],
+ [lt_cv_sys_global_symbol_to_c_name_address], [1],
+ [Transform the output of nm in a C name address pair])
+_LT_DECL([global_symbol_to_c_name_address_lib_prefix],
+ [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1],
+ [Transform the output of nm in a C name address pair when lib prefix is needed])
+_LT_DECL([nm_interface], [lt_cv_nm_interface], [1],
+ [The name lister interface])
+_LT_DECL([], [nm_file_list_spec], [1],
+ [Specify filename containing input files for $NM])
+]) # _LT_CMD_GLOBAL_SYMBOLS
+
+
+# _LT_COMPILER_PIC([TAGNAME])
+# ---------------------------
+m4_defun([_LT_COMPILER_PIC],
+[m4_require([_LT_TAG_COMPILER])dnl
+_LT_TAGVAR(lt_prog_compiler_wl, $1)=
+_LT_TAGVAR(lt_prog_compiler_pic, $1)=
+_LT_TAGVAR(lt_prog_compiler_static, $1)=
+
+m4_if([$1], [CXX], [
+ # C++ specific cases for pic, static, wl, etc.
+ if test yes = "$GXX"; then
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test ia64 = "$host_cpu"; then
+ # AIX 5 now supports IA64 processor
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ m68k)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the '-m68020' flag to GCC prevents building anything better,
+ # like '-m68040'.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+ ;;
+ esac
+ ;;
+
+ beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+ mingw* | cygwin* | os2* | pw32* | cegcc*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ # Although the cygwin gcc ignores -fPIC, still need this for old-style
+ # (--disable-auto-import) libraries
+ m4_if([$1], [GCJ], [],
+ [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+ case $host_os in
+ os2*)
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static'
+ ;;
+ esac
+ ;;
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+ ;;
+ *djgpp*)
+ # DJGPP does not support shared libraries at all
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+ ;;
+ haiku*)
+ # PIC is the default for Haiku.
+ # The "-static" flag exists, but is broken.
+ _LT_TAGVAR(lt_prog_compiler_static, $1)=
+ ;;
+ interix[[3-9]]*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+ fi
+ ;;
+ hpux*)
+ # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+ # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag
+ # sets the default TLS model and affects inlining.
+ case $host_cpu in
+ hppa*64*)
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ ;;
+ *qnx* | *nto*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ else
+ case $host_os in
+ aix[[4-9]]*)
+ # All AIX code is PIC.
+ if test ia64 = "$host_cpu"; then
+ # AIX 5 now supports IA64 processor
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ else
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+ chorus*)
+ case $cc_basename in
+ cxch68*)
+ # Green Hills C++ Compiler
+ # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
+ ;;
+ esac
+ ;;
+ mingw* | cygwin* | os2* | pw32* | cegcc*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ m4_if([$1], [GCJ], [],
+ [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+ ;;
+ dgux*)
+ case $cc_basename in
+ ec++*)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ ;;
+ ghcx*)
+ # Green Hills C++ Compiler
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ freebsd* | dragonfly*)
+ # FreeBSD uses GNU C++
+ ;;
+ hpux9* | hpux10* | hpux11*)
+ case $cc_basename in
+ CC*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive'
+ if test ia64 != "$host_cpu"; then
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+ fi
+ ;;
+ aCC*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive'
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+ ;;
+ esac
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ interix*)
+ # This is c89, which is MS Visual C++ (no shared libs)
+ # Anyone wants to do a port?
+ ;;
+ irix5* | irix6* | nonstopux*)
+ case $cc_basename in
+ CC*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ # CC pic flag -KPIC is the default.
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+ case $cc_basename in
+ KCC*)
+ # KAI C++ Compiler
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ ecpc* )
+ # old Intel C++ for x86_64, which still supported -KPIC.
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ icpc* )
+ # Intel C++, used to be incompatible with GCC.
+ # ICC 10 doesn't accept -KPIC any more.
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ pgCC* | pgcpp*)
+ # Portland Group C++ compiler
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ cxx*)
+ # Compaq C++
+ # Make sure the PIC flag is empty. It appears that all Alpha
+ # Linux and Compaq Tru64 Unix objects are PIC.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+ xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*)
+ # IBM XL 8.0, 9.0 on PPC and BlueGene
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
+ ;;
+ *)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*)
+ # Sun C++ 5.9
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ lynxos*)
+ ;;
+ m88k*)
+ ;;
+ mvs*)
+ case $cc_basename in
+ cxx*)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ netbsd*)
+ ;;
+ *qnx* | *nto*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+ ;;
+ osf3* | osf4* | osf5*)
+ case $cc_basename in
+ KCC*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ ;;
+ cxx*)
+ # Digital/Compaq C++
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # Make sure the PIC flag is empty. It appears that all Alpha
+ # Linux and Compaq Tru64 Unix objects are PIC.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ psos*)
+ ;;
+ solaris*)
+ case $cc_basename in
+ CC* | sunCC*)
+ # Sun C++ 4.2, 5.x and Centerline C++
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+ ;;
+ gcx*)
+ # Green Hills C++ Compiler
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ sunos4*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.x
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ lcc*)
+ # Lucid
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ case $cc_basename in
+ CC*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ esac
+ ;;
+ tandem*)
+ case $cc_basename in
+ NCC*)
+ # NonStop-UX NCC 3.20
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ vxworks*)
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ ;;
+ esac
+ fi
+],
+[
+ if test yes = "$GCC"; then
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+ case $host_os in
+ aix*)
+ # All AIX code is PIC.
+ if test ia64 = "$host_cpu"; then
+ # AIX 5 now supports IA64 processor
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ m68k)
+ # FIXME: we need at least 68020 code to build shared libraries, but
+ # adding the '-m68020' flag to GCC prevents building anything better,
+ # like '-m68040'.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+ ;;
+ esac
+ ;;
+
+ beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+ # PIC is the default for these OSes.
+ ;;
+
+ mingw* | cygwin* | pw32* | os2* | cegcc*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ # Although the cygwin gcc ignores -fPIC, still need this for old-style
+ # (--disable-auto-import) libraries
+ m4_if([$1], [GCJ], [],
+ [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+ case $host_os in
+ os2*)
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static'
+ ;;
+ esac
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+ ;;
+
+ haiku*)
+ # PIC is the default for Haiku.
+ # The "-static" flag exists, but is broken.
+ _LT_TAGVAR(lt_prog_compiler_static, $1)=
+ ;;
+
+ hpux*)
+ # PIC is the default for 64-bit PA HP-UX, but not for 32-bit
+ # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag
+ # sets the default TLS model and affects inlining.
+ case $host_cpu in
+ hppa*64*)
+ # +Z the default
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+ ;;
+
+ interix[[3-9]]*)
+ # Interix 3.x gcc -fpic/-fPIC options generate broken code.
+ # Instead, we relocate shared libraries at runtime.
+ ;;
+
+ msdosdjgpp*)
+ # Just because we use GCC doesn't mean we suddenly get shared libraries
+ # on systems that don't support them.
+ _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ enable_shared=no
+ ;;
+
+ *nto* | *qnx*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+ fi
+ ;;
+
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ ;;
+ esac
+
+ case $cc_basename in
+ nvcc*) # Cuda Compiler Driver 2.2
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker '
+ if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)"
+ fi
+ ;;
+ esac
+ else
+ # PORTME Check for flag to pass linker flags through the system compiler.
+ case $host_os in
+ aix*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ if test ia64 = "$host_cpu"; then
+ # AIX 5 now supports IA64 processor
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ else
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+ fi
+ ;;
+
+ darwin* | rhapsody*)
+ # PIC is the default on this platform
+ # Common symbols not allowed in MH_DYLIB files
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+ case $cc_basename in
+ nagfor*)
+ # NAG Fortran compiler
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ esac
+ ;;
+
+ mingw* | cygwin* | pw32* | os2* | cegcc*)
+ # This hack is so that the source file can tell whether it is being
+ # built for inclusion in a dll (and should export symbols for example).
+ m4_if([$1], [GCJ], [],
+ [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'])
+ case $host_os in
+ os2*)
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static'
+ ;;
+ esac
+ ;;
+
+ hpux9* | hpux10* | hpux11*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+ # not for PA HP-UX.
+ case $host_cpu in
+ hppa*64*|ia64*)
+ # +Z the default
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+ ;;
+ esac
+ # Is there a better lt_prog_compiler_static that works with the bundled CC?
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive'
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # PIC (with -KPIC) is the default.
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+
+ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+ case $cc_basename in
+ # old Intel for x86_64, which still supported -KPIC.
+ ecc*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ # icc used to be incompatible with GCC.
+ # ICC 10 doesn't accept -KPIC any more.
+ icc* | ifort*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ # Lahey Fortran 8.1.
+ lf95*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='--static'
+ ;;
+ nagfor*)
+ # NAG Fortran compiler
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ tcc*)
+ # Fabrice Bellard et al's Tiny C Compiler
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
+ # Portland Group compilers (*not* the Pentium gcc compiler,
+ # which looks to be a dead project)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ ccc*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # All Alpha code is PIC.
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+ xl* | bgxl* | bgf* | mpixl*)
+ # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
+ ;;
+ *)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*)
+ # Sun Fortran 8.3 passes all unrecognized flags to the linker
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)=''
+ ;;
+ *Sun\ F* | *Sun*Fortran*)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+ ;;
+ *Sun\ C*)
+ # Sun C 5.9
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ ;;
+ *Intel*\ [[CF]]*Compiler*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
+ ;;
+ *Portland\ Group*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+
+ newsos6)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ *nto* | *qnx*)
+ # QNX uses GNU C++, but need to define -shared option too, otherwise
+ # it will coredump.
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared'
+ ;;
+
+ osf3* | osf4* | osf5*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ # All OSF/1 code is PIC.
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+
+ rdos*)
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+ ;;
+
+ solaris*)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ case $cc_basename in
+ f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';;
+ esac
+ ;;
+
+ sunos4*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ sysv4 | sysv4.2uw2* | sysv4.3*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ fi
+ ;;
+
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ unicos*)
+ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+ _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ ;;
+
+ uts4*)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+ _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+ ;;
+
+ *)
+ _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+ ;;
+ esac
+ fi
+])
+case $host_os in
+ # For platforms that do not support PIC, -DPIC is meaningless:
+ *djgpp*)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)=
+ ;;
+ *)
+ _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])"
+ ;;
+esac
+
+AC_CACHE_CHECK([for $compiler option to produce PIC],
+ [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)],
+ [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)])
+_LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then
+ _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works],
+ [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)],
+ [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [],
+ [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in
+ "" | " "*) ;;
+ *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;;
+ esac],
+ [_LT_TAGVAR(lt_prog_compiler_pic, $1)=
+ _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
+fi
+_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1],
+ [Additional compiler flags for building library objects])
+
+_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1],
+ [How to pass a linker flag through the compiler])
+#
+# Check to make sure the static flag actually works.
+#
+wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\"
+_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works],
+ _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1),
+ $lt_tmp_static_flag,
+ [],
+ [_LT_TAGVAR(lt_prog_compiler_static, $1)=])
+_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1],
+ [Compiler flag to prevent dynamic linking])
+])# _LT_COMPILER_PIC
+
+
+# _LT_LINKER_SHLIBS([TAGNAME])
+# ----------------------------
+# See if the linker supports building shared libraries.
+m4_defun([_LT_LINKER_SHLIBS],
+[AC_REQUIRE([LT_PATH_LD])dnl
+AC_REQUIRE([LT_PATH_NM])dnl
+m4_require([_LT_PATH_MANIFEST_TOOL])dnl
+m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_DECL_SED])dnl
+m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl
+m4_require([_LT_TAG_COMPILER])dnl
+AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+m4_if([$1], [CXX], [
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
+ case $host_os in
+ aix[[4-9]]*)
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to GNU nm, but means don't demangle to AIX nm.
+ # Without the "-l" option, or with the "-B" option, AIX nm treats
+ # weak defined symbols like other global defined symbols, whereas
+ # GNU nm marks them as "W".
+ # While the 'weak' keyword is ignored in the Export File, we need
+ # it in the Import File for the 'aix-soname' feature, so we have
+ # to replace the "-B" option with "-P" for AIX nm.
+ if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
+ else
+ _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
+ fi
+ ;;
+ pw32*)
+ _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds
+ ;;
+ cygwin* | mingw* | cegcc*)
+ case $cc_basename in
+ cl*)
+ _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
+ ;;
+ *)
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
+ _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname']
+ ;;
+ esac
+ ;;
+ *)
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ ;;
+ esac
+], [
+ runpath_var=
+ _LT_TAGVAR(allow_undefined_flag, $1)=
+ _LT_TAGVAR(always_export_symbols, $1)=no
+ _LT_TAGVAR(archive_cmds, $1)=
+ _LT_TAGVAR(archive_expsym_cmds, $1)=
+ _LT_TAGVAR(compiler_needs_object, $1)=no
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)=
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+ _LT_TAGVAR(hardcode_automatic, $1)=no
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=no
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=
+ _LT_TAGVAR(hardcode_minus_L, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+ _LT_TAGVAR(inherit_rpath, $1)=no
+ _LT_TAGVAR(link_all_deplibs, $1)=unknown
+ _LT_TAGVAR(module_cmds, $1)=
+ _LT_TAGVAR(module_expsym_cmds, $1)=
+ _LT_TAGVAR(old_archive_from_new_cmds, $1)=
+ _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)=
+ _LT_TAGVAR(thread_safe_flag_spec, $1)=
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=
+ # include_expsyms should be a list of space-separated symbols to be *always*
+ # included in the symbol list
+ _LT_TAGVAR(include_expsyms, $1)=
+ # exclude_expsyms can be an extended regexp of symbols to exclude
+ # it will be wrapped by ' (' and ')$', so one must not match beginning or
+ # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc',
+ # as well as any symbol that contains 'd'.
+ _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*']
+ # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+ # platforms (ab)use it in PIC code, but their linkers get confused if
+ # the symbol is explicitly referenced. Since portable code cannot
+ # rely on this symbol name, it's probably fine to never include it in
+ # preloaded symbol tables.
+ # Exclude shared library initialization/finalization symbols.
+dnl Note also adjust exclude_expsyms for C++ above.
+ extract_expsyms_cmds=
+
+ case $host_os in
+ cygwin* | mingw* | pw32* | cegcc*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ if test yes != "$GCC"; then
+ with_gnu_ld=no
+ fi
+ ;;
+ interix*)
+ # we just hope/assume this is gcc and not c89 (= MSVC++)
+ with_gnu_ld=yes
+ ;;
+ openbsd* | bitrig*)
+ with_gnu_ld=no
+ ;;
+ esac
+
+ _LT_TAGVAR(ld_shlibs, $1)=yes
+
+ # On some targets, GNU ld is compatible enough with the native linker
+ # that we're better off using the native interface for both.
+ lt_use_gnu_ld_interface=no
+ if test yes = "$with_gnu_ld"; then
+ case $host_os in
+ aix*)
+ # The AIX port of GNU ld has always aspired to compatibility
+ # with the native linker. However, as the warning in the GNU ld
+ # block says, versions before 2.19.5* couldn't really create working
+ # shared libraries, regardless of the interface used.
+ case `$LD -v 2>&1` in
+ *\ \(GNU\ Binutils\)\ 2.19.5*) ;;
+ *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;;
+ *\ \(GNU\ Binutils\)\ [[3-9]]*) ;;
+ *)
+ lt_use_gnu_ld_interface=yes
+ ;;
+ esac
+ ;;
+ *)
+ lt_use_gnu_ld_interface=yes
+ ;;
+ esac
+ fi
+
+ if test yes = "$lt_use_gnu_ld_interface"; then
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ wlarc='$wl'
+
+ # Set some defaults for GNU ld with shared library support. These
+ # are reset later if shared libraries are not supported. Putting them
+ # here allows them to be overridden if necessary.
+ runpath_var=LD_RUN_PATH
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
+ else
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=
+ fi
+ supports_anon_versioning=no
+ case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in
+ *GNU\ gold*) supports_anon_versioning=yes ;;
+ *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
+ *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+ *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+ *\ 2.11.*) ;; # other 2.11 versions
+ *) supports_anon_versioning=yes ;;
+ esac
+
+ # See if GNU ld supports shared libraries.
+ case $host_os in
+ aix[[3-9]]*)
+ # On AIX/PPC, the GNU linker is very broken
+ if test ia64 != "$host_cpu"; then
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.19, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support. If you
+*** really care for shared libraries, you may want to install binutils
+*** 2.20 or above, or modify your PATH so that a non-GNU linker is found.
+*** You will then need to restart the configuration process.
+
+_LT_EOF
+ fi
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)=''
+ ;;
+ m68k)
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ ;;
+ esac
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ cygwin* | mingw* | pw32* | cegcc*)
+ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+ # as there is no search path for DLLs.
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols'
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_TAGVAR(always_export_symbols, $1)=no
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols'
+ _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname']
+
+ if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file, use it as
+ # is; otherwise, prepend EXPORTS...
+ _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ haiku*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+
+ os2*)
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ shrext_cmds=.dll
+ _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ prefix_cmds="$SED"~
+ if test EXPORTS = "`$SED 1q $export_symbols`"; then
+ prefix_cmds="$prefix_cmds -e 1d";
+ fi~
+ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ ;;
+
+ interix[[3-9]]*)
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+
+ gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
+ tmp_diet=no
+ if test linux-dietlibc = "$host_os"; then
+ case $cc_basename in
+ diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn)
+ esac
+ fi
+ if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \
+ && test no = "$tmp_diet"
+ then
+ tmp_addflag=' $pic_flag'
+ tmp_sharedflag='-shared'
+ case $cc_basename,$host_cpu in
+ pgcc*) # Portland Group C compiler
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+ tmp_addflag=' $pic_flag'
+ ;;
+ pgf77* | pgf90* | pgf95* | pgfortran*)
+ # Portland Group f77 and f90 compilers
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+ tmp_addflag=' $pic_flag -Mnomain' ;;
+ ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64
+ tmp_addflag=' -i_dynamic' ;;
+ efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64
+ tmp_addflag=' -i_dynamic -nofor_main' ;;
+ ifc* | ifort*) # Intel Fortran compiler
+ tmp_addflag=' -nofor_main' ;;
+ lf95*) # Lahey Fortran 8.1
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=
+ tmp_sharedflag='--shared' ;;
+ nagfor*) # NAGFOR 5.3
+ tmp_sharedflag='-Wl,-shared' ;;
+ xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below)
+ tmp_sharedflag='-qmkshrobj'
+ tmp_addflag= ;;
+ nvcc*) # Cuda Compiler Driver 2.2
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+ _LT_TAGVAR(compiler_needs_object, $1)=yes
+ ;;
+ esac
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*) # Sun C 5.9
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+ _LT_TAGVAR(compiler_needs_object, $1)=yes
+ tmp_sharedflag='-G' ;;
+ *Sun\ F*) # Sun Fortran 8.3
+ tmp_sharedflag='-G' ;;
+ esac
+ _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+
+ if test yes = "$supports_anon_versioning"; then
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
+ fi
+
+ case $cc_basename in
+ tcc*)
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic'
+ ;;
+ xlf* | bgf* | bgxlf* | mpixlf*)
+ # IBM XL Fortran 10.1 on PPC cannot create shared libs itself
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib'
+ if test yes = "$supports_anon_versioning"; then
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ echo "local: *; };" >> $output_objdir/$libname.ver~
+ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
+ fi
+ ;;
+ esac
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+ wlarc=
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+ fi
+ ;;
+
+ solaris*)
+ if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+ case `$LD -v 2>&1` in
+ *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*)
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ cat <<_LT_EOF 1>&2
+
+*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot
+*** reliably create shared libraries on SCO systems. Therefore, libtool
+*** is disabling shared libraries support. We urge you to upgrade GNU
+*** binutils to release 2.16.91.0.3 or newer. Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+_LT_EOF
+ ;;
+ *)
+ # For security reasons, it is highly recommended that you always
+ # use absolute paths for naming shared libraries, and exclude the
+ # DT_RUNPATH tag from executables and libraries. But doing so
+ # requires that you compile everything twice, which is a pain.
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+
+ sunos4*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ wlarc=
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ *)
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+
+ if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then
+ runpath_var=
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)=
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=
+ fi
+ else
+ # PORTME fill in a description of your system's linker (not GNU ld)
+ case $host_os in
+ aix3*)
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_TAGVAR(always_export_symbols, $1)=yes
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ _LT_TAGVAR(hardcode_direct, $1)=unsupported
+ fi
+ ;;
+
+ aix[[4-9]]*)
+ if test ia64 = "$host_cpu"; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=
+ else
+ # If we're using GNU nm, then we don't want the "-C" option.
+ # -C means demangle to GNU nm, but means don't demangle to AIX nm.
+ # Without the "-l" option, or with the "-B" option, AIX nm treats
+ # weak defined symbols like other global defined symbols, whereas
+ # GNU nm marks them as "W".
+ # While the 'weak' keyword is ignored in the Export File, we need
+ # it in the Import File for the 'aix-soname' feature, so we have
+ # to replace the "-B" option with "-P" for AIX nm.
+ if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
+ else
+ _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
+ fi
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # have runtime linking enabled, and use it for executables.
+ # For shared libraries, we enable/disable runtime linking
+ # depending on the kind of the shared library created -
+ # when "with_aix_soname,aix_use_runtimelinking" is:
+ # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables
+ # "aix,yes" lib.so shared, rtl:yes, for executables
+ # lib.a static archive
+ # "both,no" lib.so.V(shr.o) shared, rtl:yes
+ # lib.a(lib.so.V) shared, rtl:no, for executables
+ # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
+ # lib.a(lib.so.V) shared, rtl:no
+ # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables
+ # lib.a static archive
+ case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
+ for ld_flag in $LDFLAGS; do
+ if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
+ # With aix-soname=svr4, we create the lib.so.V shared archives only,
+ # so we don't have lib.a shared libs to link our executables.
+ # We have to force runtime linking in this case.
+ aix_use_runtimelinking=yes
+ LDFLAGS="$LDFLAGS -Wl,-brtl"
+ fi
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ _LT_TAGVAR(archive_cmds, $1)=''
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_TAGVAR(file_list_spec, $1)='$wl-f,'
+ case $with_aix_soname,$aix_use_runtimelinking in
+ aix,*) ;; # traditional, no import file
+ svr4,* | *,yes) # use import file
+ # The Import File defines what to hardcode.
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=no
+ ;;
+ esac
+
+ if test yes = "$GCC"; then
+ case $host_os in aix4.[[012]]|aix4.[[012]].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`$CC -print-prog-name=collect2`
+ if test -f "$collect2name" &&
+ strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ :
+ else
+ # We have old collect2
+ _LT_TAGVAR(hardcode_direct, $1)=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=
+ fi
+ ;;
+ esac
+ shared_flag='-shared'
+ if test yes = "$aix_use_runtimelinking"; then
+ shared_flag="$shared_flag "'$wl-G'
+ fi
+ # Need to ensure runtime linking is disabled for the traditional
+ # shared library, or the linker may eventually find shared libraries
+ # /with/ Import File - we do not want to mix them.
+ shared_flag_aix='-shared'
+ shared_flag_svr4='-shared $wl-G'
+ else
+ # not using gcc
+ if test ia64 = "$host_cpu"; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test yes = "$aix_use_runtimelinking"; then
+ shared_flag='$wl-G'
+ else
+ shared_flag='$wl-bM:SRE'
+ fi
+ shared_flag_aix='$wl-bM:SRE'
+ shared_flag_svr4='$wl-G'
+ fi
+ fi
+
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall'
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to export.
+ _LT_TAGVAR(always_export_symbols, $1)=yes
+ if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ _LT_TAGVAR(allow_undefined_flag, $1)='-berok'
+ # Determine the default libpath from the value encoded in an
+ # empty executable.
+ _LT_SYS_MODULE_PATH_AIX([$1])
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
+ else
+ if test ia64 = "$host_cpu"; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib'
+ _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+ _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an
+ # empty executable.
+ _LT_SYS_MODULE_PATH_AIX([$1])
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok'
+ _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok'
+ if test yes = "$with_gnu_ld"; then
+ # We only use this code for GNU lds that support --whole-archive.
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive'
+ else
+ # Exported symbols can be pulled into shared objects from archives
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+ fi
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d'
+ # -brtl affects multiple linker settings, -berok does not and is overridden later
+ compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`'
+ if test svr4 != "$with_aix_soname"; then
+ # This is similar to how AIX traditionally builds its shared libraries.
+ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
+ fi
+ if test aix != "$with_aix_soname"; then
+ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp'
+ else
+ # used by -dlpreopen to get the symbols
+ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir'
+ fi
+ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d'
+ fi
+ fi
+ ;;
+
+ amigaos*)
+ case $host_cpu in
+ powerpc)
+ # see comment about AmigaOS4 .so support
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)=''
+ ;;
+ m68k)
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ ;;
+ esac
+ ;;
+
+ bsdi[[45]]*)
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic
+ ;;
+
+ cygwin* | mingw* | pw32* | cegcc*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ case $cc_basename in
+ cl*)
+ # Native MSVC
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_TAGVAR(always_export_symbols, $1)=yes
+ _LT_TAGVAR(file_list_spec, $1)='@'
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=.dll
+ # FIXME: Setting linknames here is a bad hack.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
+ _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
+ cp "$export_symbols" "$output_objdir/$soname.def";
+ echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
+ else
+ $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp;
+ fi~
+ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
+ linknames='
+ # The linker will not automatically build a static lib if we build a DLL.
+ # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
+ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols'
+ # Don't use ranlib
+ _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib'
+ _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~
+ lt_tool_outputfile="@TOOL_OUTPUT@"~
+ case $lt_outputfile in
+ *.exe|*.EXE) ;;
+ *)
+ lt_outputfile=$lt_outputfile.exe
+ lt_tool_outputfile=$lt_tool_outputfile.exe
+ ;;
+ esac~
+ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then
+ $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
+ $RM "$lt_outputfile.manifest";
+ fi'
+ ;;
+ *)
+ # Assume MSVC wrapper
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=.dll
+ # FIXME: Setting linknames here is a bad hack.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames='
+ # The linker will automatically build a .lib file if we build a DLL.
+ _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
+ # FIXME: Should let the user specify the lib program.
+ _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs'
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ ;;
+ esac
+ ;;
+
+ darwin* | rhapsody*)
+ _LT_DARWIN_LINKER_FEATURES($1)
+ ;;
+
+ dgux*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+ # support. Future versions do this automatically, but an explicit c++rt0.o
+ # does not break anything, and helps significantly (at the cost of a little
+ # extra space).
+ freebsd2.2*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+ freebsd2.*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+ freebsd* | dragonfly*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ hpux9*)
+ if test yes = "$GCC"; then
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
+ fi
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+ ;;
+
+ hpux10*)
+ if test yes,no = "$GCC,$with_gnu_ld"; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ if test no = "$with_gnu_ld"; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ fi
+ ;;
+
+ hpux11*)
+ if test yes,no = "$GCC,$with_gnu_ld"; then
+ case $host_cpu in
+ hppa*64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ else
+ case $host_cpu in
+ hppa*64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ ia64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ m4_if($1, [], [
+ # Older versions of the 11.00 compiler do not understand -b yet
+ # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does)
+ _LT_LINKER_OPTION([if $CC understands -b],
+ _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b],
+ [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'],
+ [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])],
+ [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'])
+ ;;
+ esac
+ fi
+ if test no = "$with_gnu_ld"; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+ *)
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ ;;
+ esac
+ fi
+ ;;
+
+ irix5* | irix6* | nonstopux*)
+ if test yes = "$GCC"; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+ # Try to use the -exported_symbol ld option, if it does not
+ # work, assume that -exports_file does not work either and
+ # implicitly export all symbols.
+ # This should be the same for all languages, so no per-tag cache variable.
+ AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol],
+ [lt_cv_irix_exported_symbol],
+ [save_LDFLAGS=$LDFLAGS
+ LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null"
+ AC_LINK_IFELSE(
+ [AC_LANG_SOURCE(
+ [AC_LANG_CASE([C], [[int foo (void) { return 0; }]],
+ [C++], [[int foo (void) { return 0; }]],
+ [Fortran 77], [[
+ subroutine foo
+ end]],
+ [Fortran], [[
+ subroutine foo
+ end]])])],
+ [lt_cv_irix_exported_symbol=yes],
+ [lt_cv_irix_exported_symbol=no])
+ LDFLAGS=$save_LDFLAGS])
+ if test yes = "$lt_cv_irix_exported_symbol"; then
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib'
+ fi
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib'
+ fi
+ _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_TAGVAR(inherit_rpath, $1)=yes
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+
+ linux*)
+ case $cc_basename in
+ tcc*)
+ # Fabrice Bellard et al's Tiny C Compiler
+ _LT_TAGVAR(ld_shlibs, $1)=yes
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF
+ fi
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ newsos6)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ *nto* | *qnx*)
+ ;;
+
+ openbsd* | bitrig*)
+ if test -f /usr/libexec/ld.so; then
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+ fi
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ os2*)
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ shrext_cmds=.dll
+ _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ prefix_cmds="$SED"~
+ if test EXPORTS = "`$SED 1q $export_symbols`"; then
+ prefix_cmds="$prefix_cmds -e 1d";
+ fi~
+ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ ;;
+
+ osf3*)
+ if test yes = "$GCC"; then
+ _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+ else
+ _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+ fi
+ _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ ;;
+
+ osf4* | osf5*) # as osf3* with the addition of -msym flag
+ if test yes = "$GCC"; then
+ _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ else
+ _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~
+ $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp'
+
+ # Both c and cxx compiler support -rpath directly
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+ fi
+ _LT_TAGVAR(archive_cmds_need_lc, $1)='no'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ ;;
+
+ solaris*)
+ _LT_TAGVAR(no_undefined_flag, $1)=' -z defs'
+ if test yes = "$GCC"; then
+ wlarc='$wl'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+ else
+ case `$CC -V 2>&1` in
+ *"Compilers 5.0"*)
+ wlarc=''
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp'
+ ;;
+ *)
+ wlarc='$wl'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp'
+ ;;
+ esac
+ fi
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ case $host_os in
+ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+ *)
+ # The compiler driver will combine and reorder linker options,
+ # but understands '-z linker_flag'. GCC discards it without '$wl',
+ # but is careful enough not to reorder.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ if test yes = "$GCC"; then
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract'
+ else
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
+ fi
+ ;;
+ esac
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+
+ sunos4*)
+ if test sequent = "$host_vendor"; then
+ # Use $CC to link under sequent, because it throws in some extra .o
+ # files that make .init and .fini sections work.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+ fi
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ sysv4)
+ case $host_vendor in
+ sni)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true???
+ ;;
+ siemens)
+ ## LD is ld it makes a PLAMLIB
+ ## CC just makes a GrossModule.
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs'
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ ;;
+ motorola)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie
+ ;;
+ esac
+ runpath_var='LD_RUN_PATH'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ sysv4.3*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport'
+ ;;
+
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ runpath_var=LD_RUN_PATH
+ hardcode_runpath_var=yes
+ _LT_TAGVAR(ld_shlibs, $1)=yes
+ fi
+ ;;
+
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+ _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ runpath_var='LD_RUN_PATH'
+
+ if test yes = "$GCC"; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We CANNOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
+ _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs'
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ if test yes = "$GCC"; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ fi
+ ;;
+
+ uts4*)
+ _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+
+ *)
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+
+ if test sni = "$host_vendor"; then
+ case $host in
+ sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym'
+ ;;
+ esac
+ fi
+ fi
+])
+AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
+test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no
+
+_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld
+
+_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl
+_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl
+_LT_DECL([], [extract_expsyms_cmds], [2],
+ [The commands to extract the exported symbol list from a shared archive])
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in
+x|xyes)
+ # Assume -lc should be added
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+
+ if test yes,yes = "$GCC,$enable_shared"; then
+ case $_LT_TAGVAR(archive_cmds, $1) in
+ *'~'*)
+ # FIXME: we may have to deal with multi-command sequences.
+ ;;
+ '$CC '*)
+ # Test whether the compiler implicitly links with -lc since on some
+ # systems, -lgcc has to come before -lc. If gcc already passes -lc
+ # to ld, don't add -lc before -lgcc.
+ AC_CACHE_CHECK([whether -lc should be explicitly linked in],
+ [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1),
+ [$RM conftest*
+ echo "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+ if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
+ soname=conftest
+ lib=conftest
+ libobjs=conftest.$ac_objext
+ deplibs=
+ wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1)
+ pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1)
+ compiler_flags=-v
+ linker_flags=-v
+ verstring=
+ output_objdir=.
+ libname=conftest
+ lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1)
+ _LT_TAGVAR(allow_undefined_flag, $1)=
+ if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1)
+ then
+ lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ else
+ lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+ fi
+ _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
+ else
+ cat conftest.err 1>&5
+ fi
+ $RM conftest*
+ ])
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)
+ ;;
+ esac
+ fi
+ ;;
+esac
+
+_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0],
+ [Whether or not to add -lc for building shared libraries])
+_LT_TAGDECL([allow_libtool_libs_with_static_runtimes],
+ [enable_shared_with_static_runtimes], [0],
+ [Whether or not to disallow shared libs when runtime libs are static])
+_LT_TAGDECL([], [export_dynamic_flag_spec], [1],
+ [Compiler flag to allow reflexive dlopens])
+_LT_TAGDECL([], [whole_archive_flag_spec], [1],
+ [Compiler flag to generate shared objects directly from archives])
+_LT_TAGDECL([], [compiler_needs_object], [1],
+ [Whether the compiler copes with passing no objects directly])
+_LT_TAGDECL([], [old_archive_from_new_cmds], [2],
+ [Create an old-style archive from a shared archive])
+_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2],
+ [Create a temporary old-style archive to link instead of a shared archive])
+_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive])
+_LT_TAGDECL([], [archive_expsym_cmds], [2])
+_LT_TAGDECL([], [module_cmds], [2],
+ [Commands used to build a loadable module if different from building
+ a shared archive.])
+_LT_TAGDECL([], [module_expsym_cmds], [2])
+_LT_TAGDECL([], [with_gnu_ld], [1],
+ [Whether we are building with GNU ld or not])
+_LT_TAGDECL([], [allow_undefined_flag], [1],
+ [Flag that allows shared libraries with undefined symbols to be built])
+_LT_TAGDECL([], [no_undefined_flag], [1],
+ [Flag that enforces no undefined symbols])
+_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1],
+ [Flag to hardcode $libdir into a binary during linking.
+ This must work even if $libdir does not exist])
+_LT_TAGDECL([], [hardcode_libdir_separator], [1],
+ [Whether we need a single "-rpath" flag with a separated argument])
+_LT_TAGDECL([], [hardcode_direct], [0],
+ [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes
+ DIR into the resulting binary])
+_LT_TAGDECL([], [hardcode_direct_absolute], [0],
+ [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes
+ DIR into the resulting binary and the resulting library dependency is
+ "absolute", i.e impossible to change by setting $shlibpath_var if the
+ library is relocated])
+_LT_TAGDECL([], [hardcode_minus_L], [0],
+ [Set to "yes" if using the -LDIR flag during linking hardcodes DIR
+ into the resulting binary])
+_LT_TAGDECL([], [hardcode_shlibpath_var], [0],
+ [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR
+ into the resulting binary])
+_LT_TAGDECL([], [hardcode_automatic], [0],
+ [Set to "yes" if building a shared library automatically hardcodes DIR
+ into the library and all subsequent libraries and executables linked
+ against it])
+_LT_TAGDECL([], [inherit_rpath], [0],
+ [Set to yes if linker adds runtime paths of dependent libraries
+ to runtime path list])
+_LT_TAGDECL([], [link_all_deplibs], [0],
+ [Whether libtool must link a program against all its dependency libraries])
+_LT_TAGDECL([], [always_export_symbols], [0],
+ [Set to "yes" if exported symbols are required])
+_LT_TAGDECL([], [export_symbols_cmds], [2],
+ [The commands to list exported symbols])
+_LT_TAGDECL([], [exclude_expsyms], [1],
+ [Symbols that should not be listed in the preloaded symbols])
+_LT_TAGDECL([], [include_expsyms], [1],
+ [Symbols that must always be exported])
+_LT_TAGDECL([], [prelink_cmds], [2],
+ [Commands necessary for linking programs (against libraries) with templates])
+_LT_TAGDECL([], [postlink_cmds], [2],
+ [Commands necessary for finishing linking programs])
+_LT_TAGDECL([], [file_list_spec], [1],
+ [Specify filename containing input files])
+dnl FIXME: Not yet implemented
+dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1],
+dnl [Compiler flag to generate thread safe objects])
+])# _LT_LINKER_SHLIBS
+
+
+# _LT_LANG_C_CONFIG([TAG])
+# ------------------------
+# Ensure that the configuration variables for a C compiler are suitably
+# defined. These variables are subsequently used by _LT_CONFIG to write
+# the compiler configuration to 'libtool'.
+m4_defun([_LT_LANG_C_CONFIG],
+[m4_require([_LT_DECL_EGREP])dnl
+lt_save_CC=$CC
+AC_LANG_PUSH(C)
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}'
+
+_LT_TAG_COMPILER
+# Save the default compiler, since it gets overwritten when the other
+# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP.
+compiler_DEFAULT=$CC
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+ _LT_COMPILER_NO_RTTI($1)
+ _LT_COMPILER_PIC($1)
+ _LT_COMPILER_C_O($1)
+ _LT_COMPILER_FILE_LOCKS($1)
+ _LT_LINKER_SHLIBS($1)
+ _LT_SYS_DYNAMIC_LINKER($1)
+ _LT_LINKER_HARDCODE_LIBPATH($1)
+ LT_SYS_DLOPEN_SELF
+ _LT_CMD_STRIPLIB
+
+ # Report what library types will actually be built
+ AC_MSG_CHECKING([if libtool supports shared libraries])
+ AC_MSG_RESULT([$can_build_shared])
+
+ AC_MSG_CHECKING([whether to build shared libraries])
+ test no = "$can_build_shared" && enable_shared=no
+
+ # On AIX, shared libraries and static libraries use the same namespace, and
+ # are all built from PIC.
+ case $host_os in
+ aix3*)
+ test yes = "$enable_shared" && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+
+ aix[[4-9]]*)
+ if test ia64 != "$host_cpu"; then
+ case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
+ yes,aix,yes) ;; # shared object as lib.so file only
+ yes,svr4,*) ;; # shared object as lib.so archive member only
+ yes,*) enable_static=no ;; # shared object in lib.a archive as well
+ esac
+ fi
+ ;;
+ esac
+ AC_MSG_RESULT([$enable_shared])
+
+ AC_MSG_CHECKING([whether to build static libraries])
+ # Make sure either enable_shared or enable_static is yes.
+ test yes = "$enable_shared" || enable_static=yes
+ AC_MSG_RESULT([$enable_static])
+
+ _LT_CONFIG($1)
+fi
+AC_LANG_POP
+CC=$lt_save_CC
+])# _LT_LANG_C_CONFIG
+
+
+# _LT_LANG_CXX_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for a C++ compiler are suitably
+# defined. These variables are subsequently used by _LT_CONFIG to write
+# the compiler configuration to 'libtool'.
+m4_defun([_LT_LANG_CXX_CONFIG],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+m4_require([_LT_DECL_EGREP])dnl
+m4_require([_LT_PATH_MANIFEST_TOOL])dnl
+if test -n "$CXX" && ( test no != "$CXX" &&
+ ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) ||
+ (test g++ != "$CXX"))); then
+ AC_PROG_CXXCPP
+else
+ _lt_caught_CXX_error=yes
+fi
+
+AC_LANG_PUSH(C++)
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(compiler_needs_object, $1)=no
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for C++ test sources.
+ac_ext=cpp
+
+# Object file extension for compiled C++ test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the CXX compiler isn't working. Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test yes != "$_lt_caught_CXX_error"; then
+ # Code to be used in simple compile tests
+ lt_simple_compile_test_code="int some_variable = 0;"
+
+ # Code to be used in simple link tests
+ lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }'
+
+ # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+ _LT_TAG_COMPILER
+
+ # save warnings/boilerplate of simple test code
+ _LT_COMPILER_BOILERPLATE
+ _LT_LINKER_BOILERPLATE
+
+ # Allow CC to be a program name with arguments.
+ lt_save_CC=$CC
+ lt_save_CFLAGS=$CFLAGS
+ lt_save_LD=$LD
+ lt_save_GCC=$GCC
+ GCC=$GXX
+ lt_save_with_gnu_ld=$with_gnu_ld
+ lt_save_path_LD=$lt_cv_path_LD
+ if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
+ lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
+ else
+ $as_unset lt_cv_prog_gnu_ld
+ fi
+ if test -n "${lt_cv_path_LDCXX+set}"; then
+ lt_cv_path_LD=$lt_cv_path_LDCXX
+ else
+ $as_unset lt_cv_path_LD
+ fi
+ test -z "${LDCXX+set}" || LD=$LDCXX
+ CC=${CXX-"c++"}
+ CFLAGS=$CXXFLAGS
+ compiler=$CC
+ _LT_TAGVAR(compiler, $1)=$CC
+ _LT_CC_BASENAME([$compiler])
+
+ if test -n "$compiler"; then
+ # We don't want -fno-exception when compiling C++ code, so set the
+ # no_builtin_flag separately
+ if test yes = "$GXX"; then
+ _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+ else
+ _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+ fi
+
+ if test yes = "$GXX"; then
+ # Set up default GNU C++ configuration
+
+ LT_PATH_LD
+
+ # Check if GNU C++ uses GNU ld as the underlying linker, since the
+ # archiving commands below assume that GNU ld is being used.
+ if test yes = "$with_gnu_ld"; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
+
+ # If archive_cmds runs LD, not CC, wlarc should be empty
+ # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
+ # investigate it a little bit more. (MM)
+ wlarc='$wl'
+
+ # ancient GNU ld didn't support --whole-archive et. al.
+ if eval "`$CC -print-prog-name=ld` --help 2>&1" |
+ $GREP 'no-whole-archive' > /dev/null; then
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
+ else
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=
+ fi
+ else
+ with_gnu_ld=no
+ wlarc=
+
+ # A generic and very simple default shared library creation
+ # command for GNU C++ for the case where it uses the native
+ # linker, instead of GNU ld. If possible, this setting should
+ # overridden to take advantage of the native linker features on
+ # the platform it is being used on.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+ fi
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+
+ else
+ GXX=no
+ with_gnu_ld=no
+ wlarc=
+ fi
+
+ # PORTME: fill in a description of your system's C++ link characteristics
+ AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+ _LT_TAGVAR(ld_shlibs, $1)=yes
+ case $host_os in
+ aix3*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ aix[[4-9]]*)
+ if test ia64 = "$host_cpu"; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ exp_sym_flag='-Bexport'
+ no_entry_flag=
+ else
+ aix_use_runtimelinking=no
+
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # have runtime linking enabled, and use it for executables.
+ # For shared libraries, we enable/disable runtime linking
+ # depending on the kind of the shared library created -
+ # when "with_aix_soname,aix_use_runtimelinking" is:
+ # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables
+ # "aix,yes" lib.so shared, rtl:yes, for executables
+ # lib.a static archive
+ # "both,no" lib.so.V(shr.o) shared, rtl:yes
+ # lib.a(lib.so.V) shared, rtl:no, for executables
+ # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables
+ # lib.a(lib.so.V) shared, rtl:no
+ # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables
+ # lib.a static archive
+ case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*)
+ for ld_flag in $LDFLAGS; do
+ case $ld_flag in
+ *-brtl*)
+ aix_use_runtimelinking=yes
+ break
+ ;;
+ esac
+ done
+ if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then
+ # With aix-soname=svr4, we create the lib.so.V shared archives only,
+ # so we don't have lib.a shared libs to link our executables.
+ # We have to force runtime linking in this case.
+ aix_use_runtimelinking=yes
+ LDFLAGS="$LDFLAGS -Wl,-brtl"
+ fi
+ ;;
+ esac
+
+ exp_sym_flag='-bexport'
+ no_entry_flag='-bnoentry'
+ fi
+
+ # When large executables or shared objects are built, AIX ld can
+ # have problems creating the table of contents. If linking a library
+ # or program results in "error TOC overflow" add -mminimal-toc to
+ # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not
+ # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+ _LT_TAGVAR(archive_cmds, $1)=''
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_TAGVAR(file_list_spec, $1)='$wl-f,'
+ case $with_aix_soname,$aix_use_runtimelinking in
+ aix,*) ;; # no import file
+ svr4,* | *,yes) # use import file
+ # The Import File defines what to hardcode.
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=no
+ ;;
+ esac
+
+ if test yes = "$GXX"; then
+ case $host_os in aix4.[[012]]|aix4.[[012]].*)
+ # We only want to do this on AIX 4.2 and lower, the check
+ # below for broken collect2 doesn't work under 4.3+
+ collect2name=`$CC -print-prog-name=collect2`
+ if test -f "$collect2name" &&
+ strings "$collect2name" | $GREP resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ :
+ else
+ # We have old collect2
+ _LT_TAGVAR(hardcode_direct, $1)=unsupported
+ # It fails to find uninstalled libraries when the uninstalled
+ # path is not listed in the libpath. Setting hardcode_minus_L
+ # to unsupported forces relinking
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=
+ fi
+ esac
+ shared_flag='-shared'
+ if test yes = "$aix_use_runtimelinking"; then
+ shared_flag=$shared_flag' $wl-G'
+ fi
+ # Need to ensure runtime linking is disabled for the traditional
+ # shared library, or the linker may eventually find shared libraries
+ # /with/ Import File - we do not want to mix them.
+ shared_flag_aix='-shared'
+ shared_flag_svr4='-shared $wl-G'
+ else
+ # not using gcc
+ if test ia64 = "$host_cpu"; then
+ # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+ # chokes on -Wl,-G. The following line is correct:
+ shared_flag='-G'
+ else
+ if test yes = "$aix_use_runtimelinking"; then
+ shared_flag='$wl-G'
+ else
+ shared_flag='$wl-bM:SRE'
+ fi
+ shared_flag_aix='$wl-bM:SRE'
+ shared_flag_svr4='$wl-G'
+ fi
+ fi
+
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall'
+ # It seems that -bexpall does not export symbols beginning with
+ # underscore (_), so it is better to generate a list of symbols to
+ # export.
+ _LT_TAGVAR(always_export_symbols, $1)=yes
+ if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then
+ # Warning - without using the other runtime loading flags (-brtl),
+ # -berok will link without error, but may produce a broken library.
+ # The "-G" linker flag allows undefined symbols.
+ _LT_TAGVAR(no_undefined_flag, $1)='-bernotok'
+ # Determine the default libpath from the value encoded in an empty
+ # executable.
+ _LT_SYS_MODULE_PATH_AIX([$1])
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
+
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag
+ else
+ if test ia64 = "$host_cpu"; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib'
+ _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+ _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols"
+ else
+ # Determine the default libpath from the value encoded in an
+ # empty executable.
+ _LT_SYS_MODULE_PATH_AIX([$1])
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath"
+ # Warning - without using the other run time loading flags,
+ # -berok will link without error, but may produce a broken library.
+ _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok'
+ _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok'
+ if test yes = "$with_gnu_ld"; then
+ # We only use this code for GNU lds that support --whole-archive.
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive'
+ else
+ # Exported symbols can be pulled into shared objects from archives
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience'
+ fi
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=yes
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d'
+ # -brtl affects multiple linker settings, -berok does not and is overridden later
+ compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`'
+ if test svr4 != "$with_aix_soname"; then
+ # This is similar to how AIX traditionally builds its shared
+ # libraries. Need -bnortl late, we may have -brtl in LDFLAGS.
+ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname'
+ fi
+ if test aix != "$with_aix_soname"; then
+ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp'
+ else
+ # used by -dlpreopen to get the symbols
+ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir'
+ fi
+ _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d'
+ fi
+ fi
+ ;;
+
+ beos*)
+ if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+ # support --undefined. This deserves some investigation. FIXME
+ _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ chorus*)
+ case $cc_basename in
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+
+ cygwin* | mingw* | pw32* | cegcc*)
+ case $GXX,$cc_basename in
+ ,cl* | no,cl*)
+ # Native MSVC
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_TAGVAR(always_export_symbols, $1)=yes
+ _LT_TAGVAR(file_list_spec, $1)='@'
+ # Tell ltmain to make .lib files, not .a files.
+ libext=lib
+ # Tell ltmain to make .dll files, not .so files.
+ shrext_cmds=.dll
+ # FIXME: Setting linknames here is a bad hack.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames='
+ _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
+ cp "$export_symbols" "$output_objdir/$soname.def";
+ echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp";
+ else
+ $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp;
+ fi~
+ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~
+ linknames='
+ # The linker will not automatically build a static lib if we build a DLL.
+ # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true'
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ # Don't use ranlib
+ _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib'
+ _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~
+ lt_tool_outputfile="@TOOL_OUTPUT@"~
+ case $lt_outputfile in
+ *.exe|*.EXE) ;;
+ *)
+ lt_outputfile=$lt_outputfile.exe
+ lt_tool_outputfile=$lt_tool_outputfile.exe
+ ;;
+ esac~
+ func_to_tool_file "$lt_outputfile"~
+ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then
+ $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1;
+ $RM "$lt_outputfile.manifest";
+ fi'
+ ;;
+ *)
+ # g++
+ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+ # as there is no search path for DLLs.
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols'
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ _LT_TAGVAR(always_export_symbols, $1)=no
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+
+ if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ # If the export-symbols file already is a .def file, use it as
+ # is; otherwise, prepend EXPORTS...
+ _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then
+ cp $export_symbols $output_objdir/$soname.def;
+ else
+ echo EXPORTS > $output_objdir/$soname.def;
+ cat $export_symbols >> $output_objdir/$soname.def;
+ fi~
+ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib'
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+ darwin* | rhapsody*)
+ _LT_DARWIN_LINKER_FEATURES($1)
+ ;;
+
+ os2*)
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes
+ _LT_TAGVAR(allow_undefined_flag, $1)=unsupported
+ shrext_cmds=.dll
+ _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~
+ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~
+ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~
+ $ECHO EXPORTS >> $output_objdir/$libname.def~
+ prefix_cmds="$SED"~
+ if test EXPORTS = "`$SED 1q $export_symbols`"; then
+ prefix_cmds="$prefix_cmds -e 1d";
+ fi~
+ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~
+ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~
+ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~
+ emximp -o $lib $output_objdir/$libname.def'
+ _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
+ _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+ ;;
+
+ dgux*)
+ case $cc_basename in
+ ec++*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ ghcx*)
+ # Green Hills C++ Compiler
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+
+ freebsd2.*)
+ # C++ shared libraries reported to be fairly broken before
+ # switch to ELF
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ freebsd-elf*)
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ ;;
+
+ freebsd* | dragonfly*)
+ # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
+ # conventions
+ _LT_TAGVAR(ld_shlibs, $1)=yes
+ ;;
+
+ haiku*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+
+ hpux9*)
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+
+ case $cc_basename in
+ CC*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ aCC*)
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+ ;;
+ *)
+ if test yes = "$GXX"; then
+ _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib'
+ else
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+
+ hpux10*|hpux11*)
+ if test no = "$with_gnu_ld"; then
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ case $host_cpu in
+ hppa*64*|ia64*)
+ ;;
+ *)
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+ ;;
+ esac
+ fi
+ case $host_cpu in
+ hppa*64*|ia64*)
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ ;;
+ *)
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+ # but as the default
+ # location of the library.
+ ;;
+ esac
+
+ case $cc_basename in
+ CC*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ aCC*)
+ case $host_cpu in
+ hppa*64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ ia64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ esac
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+ ;;
+ *)
+ if test yes = "$GXX"; then
+ if test no = "$with_gnu_ld"; then
+ case $host_cpu in
+ hppa*64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ ia64*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ ;;
+ esac
+ fi
+ else
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+
+ interix[[3-9]]*)
+ _LT_TAGVAR(hardcode_direct, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+ # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc.
+ # Instead, shared libraries are loaded at an image base (0x10000000 by
+ # default) and relocated if they conflict, which is a slow very memory
+ # consuming and fragmenting process. To avoid this, we pick a random,
+ # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
+ # time. Moving up from 0x10000000 also allows more sbrk(2) space.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
+ ;;
+ irix5* | irix6*)
+ case $cc_basename in
+ CC*)
+ # SGI C++
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+
+ # Archives containing C++ object files must be created using
+ # "CC -ar", where "CC" is the IRIX C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs'
+ ;;
+ *)
+ if test yes = "$GXX"; then
+ if test no = "$with_gnu_ld"; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+ else
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib'
+ fi
+ fi
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ ;;
+ esac
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+ _LT_TAGVAR(inherit_rpath, $1)=yes
+ ;;
+
+ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib'
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
+
+ # Archives containing C++ object files must be created using
+ # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+ _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
+ ;;
+ icpc* | ecpc* )
+ # Intel C++
+ with_gnu_ld=yes
+ # version 8.0 and above of icpc choke on multiply defined symbols
+ # if we add $predep_objects and $postdep_objects, however 7.1 and
+ # earlier do not add the objects themselves.
+ case `$CC -V 2>&1` in
+ *"Version 7."*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ *) # Version 8.0 or newer
+ tmp_idyn=
+ case $host_cpu in
+ ia64*) tmp_idyn=' -i_dynamic';;
+ esac
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ esac
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive'
+ ;;
+ pgCC* | pgcpp*)
+ # Portland Group C++ compiler
+ case `$CC -V` in
+ *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*)
+ _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~
+ rm -rf $tpldir~
+ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~
+ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"'
+ _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~
+ rm -rf $tpldir~
+ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~
+ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~
+ $RANLIB $oldlib'
+ _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~
+ rm -rf $tpldir~
+ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~
+ rm -rf $tpldir~
+ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~
+ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ *) # Version 6 and above use weak symbols
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib'
+ ;;
+ esac
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+ ;;
+ cxx*)
+ # Compaq C++
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols'
+
+ runpath_var=LD_RUN_PATH
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed'
+ ;;
+ xl* | mpixl* | bgxl*)
+ # IBM XL 8.0 on PPC, with GNU ld
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
+ if test yes = "$supports_anon_versioning"; then
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
+ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+ echo "local: *; };" >> $output_objdir/$libname.ver~
+ $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
+ fi
+ ;;
+ *)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*)
+ # Sun C++ 5.9
+ _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
+ _LT_TAGVAR(compiler_needs_object, $1)=yes
+
+ # Not sure whether something based on
+ # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1
+ # would be better.
+ output_verbose_link_cmd='func_echo_all'
+
+ # Archives containing C++ object files must be created using
+ # "CC -xar", where "CC" is the Sun C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+
+ lynxos*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ m88k*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ mvs*)
+ case $cc_basename in
+ cxx*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+
+ netbsd*)
+ if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
+ wlarc=
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ fi
+ # Workaround some broken pre-1.5 toolchains
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
+ ;;
+
+ *nto* | *qnx*)
+ _LT_TAGVAR(ld_shlibs, $1)=yes
+ ;;
+
+ openbsd* | bitrig*)
+ if test -f /usr/libexec/ld.so; then
+ _LT_TAGVAR(hardcode_direct, $1)=yes
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(hardcode_direct_absolute, $1)=yes
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib'
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E'
+ _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive'
+ fi
+ output_verbose_link_cmd=func_echo_all
+ else
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+
+ osf3* | osf4* | osf5*)
+ case $cc_basename in
+ KCC*)
+ # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+ # KCC will only create a shared library if the output file
+ # ends with ".so" (or ".sl" for HP-UX), so rename the library
+ # to its proper name (with version) after linking.
+ _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Archives containing C++ object files must be created using
+ # the KAI C++ compiler.
+ case $host in
+ osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;;
+ *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;;
+ esac
+ ;;
+ RCC*)
+ # Rational C++ 2.4.1
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ cxx*)
+ case $host in
+ osf3*)
+ _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ ;;
+ *)
+ _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
+ echo "-hidden">> $lib.exp~
+ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~
+ $RM $lib.exp'
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+ ;;
+ esac
+
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ #
+ # There doesn't appear to be a way to prevent this compiler from
+ # explicitly linking system object files so we need to strip them
+ # from the output so that they don't get included in the library
+ # dependencies.
+ output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
+ ;;
+ *)
+ if test yes,no = "$GXX,$with_gnu_ld"; then
+ _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*'
+ case $host in
+ osf3*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib'
+ ;;
+ esac
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=:
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+
+ else
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ fi
+ ;;
+ esac
+ ;;
+
+ psos*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ sunos4*)
+ case $cc_basename in
+ CC*)
+ # Sun C++ 4.x
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ lcc*)
+ # Lucid
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+
+ solaris*)
+ case $cc_basename in
+ CC* | sunCC*)
+ # Sun C++ 4.2, 5.x and Centerline C++
+ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes
+ _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ case $host_os in
+ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+ *)
+ # The compiler driver will combine and reorder linker options,
+ # but understands '-z linker_flag'.
+ # Supported since Solaris 2.6 (maybe 2.5.1?)
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract'
+ ;;
+ esac
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+
+ output_verbose_link_cmd='func_echo_all'
+
+ # Archives containing C++ object files must be created using
+ # "CC -xar", where "CC" is the Sun C++ compiler. This is
+ # necessary to make sure instantiated templates are included
+ # in the archive.
+ _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+ ;;
+ gcx*)
+ # Green Hills C++ Compiler
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
+
+ # The C++ compiler must be used to create the archive.
+ _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
+ ;;
+ *)
+ # GNU C++ compiler with Solaris linker
+ if test yes,no = "$GXX,$with_gnu_ld"; then
+ _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs'
+ if $CC --version | $GREP -v '^2\.7' > /dev/null; then
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+ else
+ # g++ 2.7 appears to require '-G' NOT '-shared' on this
+ # platform.
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~
+ $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp'
+
+ # Commands to make compiler produce verbose output that lists
+ # what "hidden" libraries, object files and flags are used when
+ # linking a shared library.
+ output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
+ fi
+
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir'
+ case $host_os in
+ solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+ *)
+ _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract'
+ ;;
+ esac
+ fi
+ ;;
+ esac
+ ;;
+
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*)
+ _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ runpath_var='LD_RUN_PATH'
+
+ case $cc_basename in
+ CC*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+
+ sysv5* | sco3.2v5* | sco5v6*)
+ # Note: We CANNOT use -z defs as we might desire, because we do not
+ # link with -lc, and that would cause any symbols used from libc to
+ # always be unresolved, which means just about no library would
+ # ever link correctly. If we're not using GNU ld we use -z text
+ # though, which does catch some bad symbols but isn't as heavy-handed
+ # as -z defs.
+ _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text'
+ _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs'
+ _LT_TAGVAR(archive_cmds_need_lc, $1)=no
+ _LT_TAGVAR(hardcode_shlibpath_var, $1)=no
+ _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir'
+ _LT_TAGVAR(hardcode_libdir_separator, $1)=':'
+ _LT_TAGVAR(link_all_deplibs, $1)=yes
+ _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport'
+ runpath_var='LD_RUN_PATH'
+
+ case $cc_basename in
+ CC*)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~
+ '"$_LT_TAGVAR(old_archive_cmds, $1)"
+ _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~
+ '"$_LT_TAGVAR(reload_cmds, $1)"
+ ;;
+ *)
+ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags'
+ ;;
+ esac
+ ;;
+
+ tandem*)
+ case $cc_basename in
+ NCC*)
+ # NonStop-UX NCC 3.20
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+ ;;
+
+ vxworks*)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+
+ *)
+ # FIXME: insert proper C++ library support
+ _LT_TAGVAR(ld_shlibs, $1)=no
+ ;;
+ esac
+
+ AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)])
+ test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no
+
+ _LT_TAGVAR(GCC, $1)=$GXX
+ _LT_TAGVAR(LD, $1)=$LD
+
+ ## CAVEAT EMPTOR:
+ ## There is no encapsulation within the following macros, do not change
+ ## the running order or otherwise move them around unless you know exactly
+ ## what you are doing...
+ _LT_SYS_HIDDEN_LIBDEPS($1)
+ _LT_COMPILER_PIC($1)
+ _LT_COMPILER_C_O($1)
+ _LT_COMPILER_FILE_LOCKS($1)
+ _LT_LINKER_SHLIBS($1)
+ _LT_SYS_DYNAMIC_LINKER($1)
+ _LT_LINKER_HARDCODE_LIBPATH($1)
+
+ _LT_CONFIG($1)
+ fi # test -n "$compiler"
+
+ CC=$lt_save_CC
+ CFLAGS=$lt_save_CFLAGS
+ LDCXX=$LD
+ LD=$lt_save_LD
+ GCC=$lt_save_GCC
+ with_gnu_ld=$lt_save_with_gnu_ld
+ lt_cv_path_LDCXX=$lt_cv_path_LD
+ lt_cv_path_LD=$lt_save_path_LD
+ lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
+ lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
+fi # test yes != "$_lt_caught_CXX_error"
+
+AC_LANG_POP
+])# _LT_LANG_CXX_CONFIG
+
+
+# _LT_FUNC_STRIPNAME_CNF
+# ----------------------
+# func_stripname_cnf prefix suffix name
+# strip PREFIX and SUFFIX off of NAME.
+# PREFIX and SUFFIX must not contain globbing or regex special
+# characters, hashes, percent signs, but SUFFIX may contain a leading
+# dot (in which case that matches only a dot).
+#
+# This function is identical to the (non-XSI) version of func_stripname,
+# except this one can be used by m4 code that may be executed by configure,
+# rather than the libtool script.
+m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl
+AC_REQUIRE([_LT_DECL_SED])
+AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])
+func_stripname_cnf ()
+{
+ case @S|@2 in
+ .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;;
+ *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;;
+ esac
+} # func_stripname_cnf
+])# _LT_FUNC_STRIPNAME_CNF
+
+
+# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME])
+# ---------------------------------
+# Figure out "hidden" library dependencies from verbose
+# compiler output when linking a shared library.
+# Parse the compiler output and extract the necessary
+# objects, libraries and library flags.
+m4_defun([_LT_SYS_HIDDEN_LIBDEPS],
+[m4_require([_LT_FILEUTILS_DEFAULTS])dnl
+AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl
+# Dependencies to place before and after the object being linked:
+_LT_TAGVAR(predep_objects, $1)=
+_LT_TAGVAR(postdep_objects, $1)=
+_LT_TAGVAR(predeps, $1)=
+_LT_TAGVAR(postdeps, $1)=
+_LT_TAGVAR(compiler_lib_search_path, $1)=
+
+dnl we can't use the lt_simple_compile_test_code here,
+dnl because it contains code intended for an executable,
+dnl not a library. It's possible we should let each
+dnl tag define a new lt_????_link_test_code variable,
+dnl but it's only used here...
+m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF
+int a;
+void foo (void) { a = 0; }
+_LT_EOF
+], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF
+class Foo
+{
+public:
+ Foo (void) { a = 0; }
+private:
+ int a;
+};
+_LT_EOF
+], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF
+ subroutine foo
+ implicit none
+ integer*4 a
+ a=0
+ return
+ end
+_LT_EOF
+], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF
+ subroutine foo
+ implicit none
+ integer a
+ a=0
+ return
+ end
+_LT_EOF
+], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF
+public class foo {
+ private int a;
+ public void bar (void) {
+ a = 0;
+ }
+};
+_LT_EOF
+], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF
+package foo
+func foo() {
+}
+_LT_EOF
+])
+
+_lt_libdeps_save_CFLAGS=$CFLAGS
+case "$CC $CFLAGS " in #(
+*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;;
+*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;;
+*\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;;
+esac
+
+dnl Parse the compiler output and extract the necessary
+dnl objects, libraries and library flags.
+if AC_TRY_EVAL(ac_compile); then
+ # Parse the compiler output and extract the necessary
+ # objects, libraries and library flags.
+
+ # Sentinel used to keep track of whether or not we are before
+ # the conftest object file.
+ pre_test_object_deps_done=no
+
+ for p in `eval "$output_verbose_link_cmd"`; do
+ case $prev$p in
+
+ -L* | -R* | -l*)
+ # Some compilers place space between "-{L,R}" and the path.
+ # Remove the space.
+ if test x-L = "$p" ||
+ test x-R = "$p"; then
+ prev=$p
+ continue
+ fi
+
+ # Expand the sysroot to ease extracting the directories later.
+ if test -z "$prev"; then
+ case $p in
+ -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;;
+ -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;;
+ -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;;
+ esac
+ fi
+ case $p in
+ =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;;
+ esac
+ if test no = "$pre_test_object_deps_done"; then
+ case $prev in
+ -L | -R)
+ # Internal compiler library paths should come after those
+ # provided the user. The postdeps already come after the
+ # user supplied libs so there is no need to process them.
+ if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then
+ _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p
+ else
+ _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p"
+ fi
+ ;;
+ # The "-l" case would never come before the object being
+ # linked, so don't bother handling this case.
+ esac
+ else
+ if test -z "$_LT_TAGVAR(postdeps, $1)"; then
+ _LT_TAGVAR(postdeps, $1)=$prev$p
+ else
+ _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p"
+ fi
+ fi
+ prev=
+ ;;
+
+ *.lto.$objext) ;; # Ignore GCC LTO objects
+ *.$objext)
+ # This assumes that the test object file only shows up
+ # once in the compiler output.
+ if test "$p" = "conftest.$objext"; then
+ pre_test_object_deps_done=yes
+ continue
+ fi
+
+ if test no = "$pre_test_object_deps_done"; then
+ if test -z "$_LT_TAGVAR(predep_objects, $1)"; then
+ _LT_TAGVAR(predep_objects, $1)=$p
+ else
+ _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p"
+ fi
+ else
+ if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then
+ _LT_TAGVAR(postdep_objects, $1)=$p
+ else
+ _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p"
+ fi
+ fi
+ ;;
+
+ *) ;; # Ignore the rest.
+
+ esac
+ done
+
+ # Clean up.
+ rm -f a.out a.exe
+else
+ echo "libtool.m4: error: problem compiling $1 test program"
+fi
+
+$RM -f confest.$objext
+CFLAGS=$_lt_libdeps_save_CFLAGS
+
+# PORTME: override above test on systems where it is broken
+m4_if([$1], [CXX],
+[case $host_os in
+interix[[3-9]]*)
+ # Interix 3.5 installs completely hosed .la files for C++, so rather than
+ # hack all around it, let's just trust "g++" to DTRT.
+ _LT_TAGVAR(predep_objects,$1)=
+ _LT_TAGVAR(postdep_objects,$1)=
+ _LT_TAGVAR(postdeps,$1)=
+ ;;
+esac
+])
+
+case " $_LT_TAGVAR(postdeps, $1) " in
+*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;;
+esac
+ _LT_TAGVAR(compiler_lib_search_dirs, $1)=
+if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then
+ _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'`
+fi
+_LT_TAGDECL([], [compiler_lib_search_dirs], [1],
+ [The directories searched by this compiler when creating a shared library])
+_LT_TAGDECL([], [predep_objects], [1],
+ [Dependencies to place before and after the objects being linked to
+ create a shared library])
+_LT_TAGDECL([], [postdep_objects], [1])
+_LT_TAGDECL([], [predeps], [1])
+_LT_TAGDECL([], [postdeps], [1])
+_LT_TAGDECL([], [compiler_lib_search_path], [1],
+ [The library search path used internally by the compiler when linking
+ a shared library])
+])# _LT_SYS_HIDDEN_LIBDEPS
+
+
+# _LT_LANG_F77_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for a Fortran 77 compiler are
+# suitably defined. These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to 'libtool'.
+m4_defun([_LT_LANG_F77_CONFIG],
+[AC_LANG_PUSH(Fortran 77)
+if test -z "$F77" || test no = "$F77"; then
+ _lt_disable_F77=yes
+fi
+
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for f77 test sources.
+ac_ext=f
+
+# Object file extension for compiled f77 test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the F77 compiler isn't working. Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test yes != "$_lt_disable_F77"; then
+ # Code to be used in simple compile tests
+ lt_simple_compile_test_code="\
+ subroutine t
+ return
+ end
+"
+
+ # Code to be used in simple link tests
+ lt_simple_link_test_code="\
+ program t
+ end
+"
+
+ # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+ _LT_TAG_COMPILER
+
+ # save warnings/boilerplate of simple test code
+ _LT_COMPILER_BOILERPLATE
+ _LT_LINKER_BOILERPLATE
+
+ # Allow CC to be a program name with arguments.
+ lt_save_CC=$CC
+ lt_save_GCC=$GCC
+ lt_save_CFLAGS=$CFLAGS
+ CC=${F77-"f77"}
+ CFLAGS=$FFLAGS
+ compiler=$CC
+ _LT_TAGVAR(compiler, $1)=$CC
+ _LT_CC_BASENAME([$compiler])
+ GCC=$G77
+ if test -n "$compiler"; then
+ AC_MSG_CHECKING([if libtool supports shared libraries])
+ AC_MSG_RESULT([$can_build_shared])
+
+ AC_MSG_CHECKING([whether to build shared libraries])
+ test no = "$can_build_shared" && enable_shared=no
+
+ # On AIX, shared libraries and static libraries use the same namespace, and
+ # are all built from PIC.
+ case $host_os in
+ aix3*)
+ test yes = "$enable_shared" && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+ aix[[4-9]]*)
+ if test ia64 != "$host_cpu"; then
+ case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
+ yes,aix,yes) ;; # shared object as lib.so file only
+ yes,svr4,*) ;; # shared object as lib.so archive member only
+ yes,*) enable_static=no ;; # shared object in lib.a archive as well
+ esac
+ fi
+ ;;
+ esac
+ AC_MSG_RESULT([$enable_shared])
+
+ AC_MSG_CHECKING([whether to build static libraries])
+ # Make sure either enable_shared or enable_static is yes.
+ test yes = "$enable_shared" || enable_static=yes
+ AC_MSG_RESULT([$enable_static])
+
+ _LT_TAGVAR(GCC, $1)=$G77
+ _LT_TAGVAR(LD, $1)=$LD
+
+ ## CAVEAT EMPTOR:
+ ## There is no encapsulation within the following macros, do not change
+ ## the running order or otherwise move them around unless you know exactly
+ ## what you are doing...
+ _LT_COMPILER_PIC($1)
+ _LT_COMPILER_C_O($1)
+ _LT_COMPILER_FILE_LOCKS($1)
+ _LT_LINKER_SHLIBS($1)
+ _LT_SYS_DYNAMIC_LINKER($1)
+ _LT_LINKER_HARDCODE_LIBPATH($1)
+
+ _LT_CONFIG($1)
+ fi # test -n "$compiler"
+
+ GCC=$lt_save_GCC
+ CC=$lt_save_CC
+ CFLAGS=$lt_save_CFLAGS
+fi # test yes != "$_lt_disable_F77"
+
+AC_LANG_POP
+])# _LT_LANG_F77_CONFIG
+
+
+# _LT_LANG_FC_CONFIG([TAG])
+# -------------------------
+# Ensure that the configuration variables for a Fortran compiler are
+# suitably defined. These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to 'libtool'.
+m4_defun([_LT_LANG_FC_CONFIG],
+[AC_LANG_PUSH(Fortran)
+
+if test -z "$FC" || test no = "$FC"; then
+ _lt_disable_FC=yes
+fi
+
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_TAGVAR(allow_undefined_flag, $1)=
+_LT_TAGVAR(always_export_symbols, $1)=no
+_LT_TAGVAR(archive_expsym_cmds, $1)=
+_LT_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_TAGVAR(hardcode_direct, $1)=no
+_LT_TAGVAR(hardcode_direct_absolute, $1)=no
+_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_TAGVAR(hardcode_minus_L, $1)=no
+_LT_TAGVAR(hardcode_automatic, $1)=no
+_LT_TAGVAR(inherit_rpath, $1)=no
+_LT_TAGVAR(module_cmds, $1)=
+_LT_TAGVAR(module_expsym_cmds, $1)=
+_LT_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+_LT_TAGVAR(no_undefined_flag, $1)=
+_LT_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for fc test sources.
+ac_ext=${ac_fc_srcext-f}
+
+# Object file extension for compiled fc test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# No sense in running all these tests if we already determined that
+# the FC compiler isn't working. Some variables (like enable_shared)
+# are currently assumed to apply to all compilers on this platform,
+# and will be corrupted by setting them based on a non-working compiler.
+if test yes != "$_lt_disable_FC"; then
+ # Code to be used in simple compile tests
+ lt_simple_compile_test_code="\
+ subroutine t
+ return
+ end
+"
+
+ # Code to be used in simple link tests
+ lt_simple_link_test_code="\
+ program t
+ end
+"
+
+ # ltmain only uses $CC for tagged configurations so make sure $CC is set.
+ _LT_TAG_COMPILER
+
+ # save warnings/boilerplate of simple test code
+ _LT_COMPILER_BOILERPLATE
+ _LT_LINKER_BOILERPLATE
+
+ # Allow CC to be a program name with arguments.
+ lt_save_CC=$CC
+ lt_save_GCC=$GCC
+ lt_save_CFLAGS=$CFLAGS
+ CC=${FC-"f95"}
+ CFLAGS=$FCFLAGS
+ compiler=$CC
+ GCC=$ac_cv_fc_compiler_gnu
+
+ _LT_TAGVAR(compiler, $1)=$CC
+ _LT_CC_BASENAME([$compiler])
+
+ if test -n "$compiler"; then
+ AC_MSG_CHECKING([if libtool supports shared libraries])
+ AC_MSG_RESULT([$can_build_shared])
+
+ AC_MSG_CHECKING([whether to build shared libraries])
+ test no = "$can_build_shared" && enable_shared=no
+
+ # On AIX, shared libraries and static libraries use the same namespace, and
+ # are all built from PIC.
+ case $host_os in
+ aix3*)
+ test yes = "$enable_shared" && enable_static=no
+ if test -n "$RANLIB"; then
+ archive_cmds="$archive_cmds~\$RANLIB \$lib"
+ postinstall_cmds='$RANLIB $lib'
+ fi
+ ;;
+ aix[[4-9]]*)
+ if test ia64 != "$host_cpu"; then
+ case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in
+ yes,aix,yes) ;; # shared object as lib.so file only
+ yes,svr4,*) ;; # shared object as lib.so archive member only
+ yes,*) enable_static=no ;; # shared object in lib.a archive as well
+ esac
+ fi
+ ;;
+ esac
+ AC_MSG_RESULT([$enable_shared])
+
+ AC_MSG_CHECKING([whether to build static libraries])
+ # Make sure either enable_shared or enable_static is yes.
+ test yes = "$enable_shared" || enable_static=yes
+ AC_MSG_RESULT([$enable_static])
+
+ _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu
+ _LT_TAGVAR(LD, $1)=$LD
+
+ ## CAVEAT EMPTOR:
+ ## There is no encapsulation within the following macros, do not change
+ ## the running order or otherwise move them around unless you know exactly
+ ## what you are doing...
+ _LT_SYS_HIDDEN_LIBDEPS($1)
+ _LT_COMPILER_PIC($1)
+ _LT_COMPILER_C_O($1)
+ _LT_COMPILER_FILE_LOCKS($1)
+ _LT_LINKER_SHLIBS($1)
+ _LT_SYS_DYNAMIC_LINKER($1)
+ _LT_LINKER_HARDCODE_LIBPATH($1)
+
+ _LT_CONFIG($1)
+ fi # test -n "$compiler"
+
+ GCC=$lt_save_GCC
+ CC=$lt_save_CC
+ CFLAGS=$lt_save_CFLAGS
+fi # test yes != "$_lt_disable_FC"
+
+AC_LANG_POP
+])# _LT_LANG_FC_CONFIG
+
+
+# _LT_LANG_GCJ_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for the GNU Java Compiler compiler
+# are suitably defined. These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to 'libtool'.
+m4_defun([_LT_LANG_GCJ_CONFIG],
+[AC_REQUIRE([LT_PROG_GCJ])dnl
+AC_LANG_SAVE
+
+# Source file extension for Java test sources.
+ac_ext=java
+
+# Object file extension for compiled Java test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="class foo {}"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_CFLAGS=$CFLAGS
+lt_save_GCC=$GCC
+GCC=yes
+CC=${GCJ-"gcj"}
+CFLAGS=$GCJFLAGS
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_TAGVAR(LD, $1)=$LD
+_LT_CC_BASENAME([$compiler])
+
+# GCJ did not exist at the time GCC didn't implicitly link libc in.
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+ _LT_COMPILER_NO_RTTI($1)
+ _LT_COMPILER_PIC($1)
+ _LT_COMPILER_C_O($1)
+ _LT_COMPILER_FILE_LOCKS($1)
+ _LT_LINKER_SHLIBS($1)
+ _LT_LINKER_HARDCODE_LIBPATH($1)
+
+ _LT_CONFIG($1)
+fi
+
+AC_LANG_RESTORE
+
+GCC=$lt_save_GCC
+CC=$lt_save_CC
+CFLAGS=$lt_save_CFLAGS
+])# _LT_LANG_GCJ_CONFIG
+
+
+# _LT_LANG_GO_CONFIG([TAG])
+# --------------------------
+# Ensure that the configuration variables for the GNU Go compiler
+# are suitably defined. These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to 'libtool'.
+m4_defun([_LT_LANG_GO_CONFIG],
+[AC_REQUIRE([LT_PROG_GO])dnl
+AC_LANG_SAVE
+
+# Source file extension for Go test sources.
+ac_ext=go
+
+# Object file extension for compiled Go test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="package main; func main() { }"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='package main; func main() { }'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_CFLAGS=$CFLAGS
+lt_save_GCC=$GCC
+GCC=yes
+CC=${GOC-"gccgo"}
+CFLAGS=$GOFLAGS
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_TAGVAR(LD, $1)=$LD
+_LT_CC_BASENAME([$compiler])
+
+# Go did not exist at the time GCC didn't implicitly link libc in.
+_LT_TAGVAR(archive_cmds_need_lc, $1)=no
+
+_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_TAGVAR(reload_flag, $1)=$reload_flag
+_LT_TAGVAR(reload_cmds, $1)=$reload_cmds
+
+## CAVEAT EMPTOR:
+## There is no encapsulation within the following macros, do not change
+## the running order or otherwise move them around unless you know exactly
+## what you are doing...
+if test -n "$compiler"; then
+ _LT_COMPILER_NO_RTTI($1)
+ _LT_COMPILER_PIC($1)
+ _LT_COMPILER_C_O($1)
+ _LT_COMPILER_FILE_LOCKS($1)
+ _LT_LINKER_SHLIBS($1)
+ _LT_LINKER_HARDCODE_LIBPATH($1)
+
+ _LT_CONFIG($1)
+fi
+
+AC_LANG_RESTORE
+
+GCC=$lt_save_GCC
+CC=$lt_save_CC
+CFLAGS=$lt_save_CFLAGS
+])# _LT_LANG_GO_CONFIG
+
+
+# _LT_LANG_RC_CONFIG([TAG])
+# -------------------------
+# Ensure that the configuration variables for the Windows resource compiler
+# are suitably defined. These variables are subsequently used by _LT_CONFIG
+# to write the compiler configuration to 'libtool'.
+m4_defun([_LT_LANG_RC_CONFIG],
+[AC_REQUIRE([LT_PROG_RC])dnl
+AC_LANG_SAVE
+
+# Source file extension for RC test sources.
+ac_ext=rc
+
+# Object file extension for compiled RC test sources.
+objext=o
+_LT_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }'
+
+# Code to be used in simple link tests
+lt_simple_link_test_code=$lt_simple_compile_test_code
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_TAG_COMPILER
+
+# save warnings/boilerplate of simple test code
+_LT_COMPILER_BOILERPLATE
+_LT_LINKER_BOILERPLATE
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_CFLAGS=$CFLAGS
+lt_save_GCC=$GCC
+GCC=
+CC=${RC-"windres"}
+CFLAGS=
+compiler=$CC
+_LT_TAGVAR(compiler, $1)=$CC
+_LT_CC_BASENAME([$compiler])
+_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+
+if test -n "$compiler"; then
+ :
+ _LT_CONFIG($1)
+fi
+
+GCC=$lt_save_GCC
+AC_LANG_RESTORE
+CC=$lt_save_CC
+CFLAGS=$lt_save_CFLAGS
+])# _LT_LANG_RC_CONFIG
+
+
+# LT_PROG_GCJ
+# -----------
+AC_DEFUN([LT_PROG_GCJ],
+[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ],
+ [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ],
+ [AC_CHECK_TOOL(GCJ, gcj,)
+ test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2"
+ AC_SUBST(GCJFLAGS)])])[]dnl
+])
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_GCJ], [])
+
+
+# LT_PROG_GO
+# ----------
+AC_DEFUN([LT_PROG_GO],
+[AC_CHECK_TOOL(GOC, gccgo,)
+])
+
+
+# LT_PROG_RC
+# ----------
+AC_DEFUN([LT_PROG_RC],
+[AC_CHECK_TOOL(RC, windres,)
+])
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_RC], [])
+
+
+# _LT_DECL_EGREP
+# --------------
+# If we don't have a new enough Autoconf to choose the best grep
+# available, choose the one first in the user's PATH.
+m4_defun([_LT_DECL_EGREP],
+[AC_REQUIRE([AC_PROG_EGREP])dnl
+AC_REQUIRE([AC_PROG_FGREP])dnl
+test -z "$GREP" && GREP=grep
+_LT_DECL([], [GREP], [1], [A grep program that handles long lines])
+_LT_DECL([], [EGREP], [1], [An ERE matcher])
+_LT_DECL([], [FGREP], [1], [A literal string matcher])
+dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too
+AC_SUBST([GREP])
+])
+
+
+# _LT_DECL_OBJDUMP
+# --------------
+# If we don't have a new enough Autoconf to choose the best objdump
+# available, choose the one first in the user's PATH.
+m4_defun([_LT_DECL_OBJDUMP],
+[AC_CHECK_TOOL(OBJDUMP, objdump, false)
+test -z "$OBJDUMP" && OBJDUMP=objdump
+_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper])
+AC_SUBST([OBJDUMP])
+])
+
+# _LT_DECL_DLLTOOL
+# ----------------
+# Ensure DLLTOOL variable is set.
+m4_defun([_LT_DECL_DLLTOOL],
+[AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+_LT_DECL([], [DLLTOOL], [1], [DLL creation program])
+AC_SUBST([DLLTOOL])
+])
+
+# _LT_DECL_SED
+# ------------
+# Check for a fully-functional sed program, that truncates
+# as few characters as possible. Prefer GNU sed if found.
+m4_defun([_LT_DECL_SED],
+[AC_PROG_SED
+test -z "$SED" && SED=sed
+Xsed="$SED -e 1s/^X//"
+_LT_DECL([], [SED], [1], [A sed program that does not truncate output])
+_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"],
+ [Sed that helps us avoid accidentally triggering echo(1) options like -n])
+])# _LT_DECL_SED
+
+m4_ifndef([AC_PROG_SED], [
+############################################################
+# NOTE: This macro has been submitted for inclusion into #
+# GNU Autoconf as AC_PROG_SED. When it is available in #
+# a released version of Autoconf we should remove this #
+# macro and use it instead. #
+############################################################
+
+m4_defun([AC_PROG_SED],
+[AC_MSG_CHECKING([for a sed that does not truncate output])
+AC_CACHE_VAL(lt_cv_path_SED,
+[# Loop through the user's path and test for sed and gsed.
+# Then use that list of sed's as ones to test for truncation.
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for lt_ac_prog in sed gsed; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
+ lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
+ fi
+ done
+ done
+done
+IFS=$as_save_IFS
+lt_ac_max=0
+lt_ac_count=0
+# Add /usr/xpg4/bin/sed as it is typically found on Solaris
+# along with /bin/sed that truncates output.
+for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
+ test ! -f "$lt_ac_sed" && continue
+ cat /dev/null > conftest.in
+ lt_ac_count=0
+ echo $ECHO_N "0123456789$ECHO_C" >conftest.in
+ # Check for GNU sed and select it if it is found.
+ if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
+ lt_cv_path_SED=$lt_ac_sed
+ break
+ fi
+ while true; do
+ cat conftest.in conftest.in >conftest.tmp
+ mv conftest.tmp conftest.in
+ cp conftest.in conftest.nl
+ echo >>conftest.nl
+ $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
+ cmp -s conftest.out conftest.nl || break
+ # 10000 chars as input seems more than enough
+ test 10 -lt "$lt_ac_count" && break
+ lt_ac_count=`expr $lt_ac_count + 1`
+ if test "$lt_ac_count" -gt "$lt_ac_max"; then
+ lt_ac_max=$lt_ac_count
+ lt_cv_path_SED=$lt_ac_sed
+ fi
+ done
+done
+])
+SED=$lt_cv_path_SED
+AC_SUBST([SED])
+AC_MSG_RESULT([$SED])
+])#AC_PROG_SED
+])#m4_ifndef
+
+# Old name:
+AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED])
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([LT_AC_PROG_SED], [])
+
+
+# _LT_CHECK_SHELL_FEATURES
+# ------------------------
+# Find out whether the shell is Bourne or XSI compatible,
+# or has some other useful features.
+m4_defun([_LT_CHECK_SHELL_FEATURES],
+[if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+ lt_unset=unset
+else
+ lt_unset=false
+fi
+_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl
+
+# test EBCDIC or ASCII
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+ # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+ lt_SP2NL='tr \040 \012'
+ lt_NL2SP='tr \015\012 \040\040'
+ ;;
+ *) # EBCDIC based system
+ lt_SP2NL='tr \100 \n'
+ lt_NL2SP='tr \r\n \100\100'
+ ;;
+esac
+_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl
+_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl
+])# _LT_CHECK_SHELL_FEATURES
+
+
+# _LT_PATH_CONVERSION_FUNCTIONS
+# -----------------------------
+# Determine what file name conversion functions should be used by
+# func_to_host_file (and, implicitly, by func_to_host_path). These are needed
+# for certain cross-compile configurations and native mingw.
+m4_defun([_LT_PATH_CONVERSION_FUNCTIONS],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_MSG_CHECKING([how to convert $build file names to $host format])
+AC_CACHE_VAL(lt_cv_to_host_file_cmd,
+[case $host in
+ *-*-mingw* )
+ case $build in
+ *-*-mingw* ) # actually msys
+ lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32
+ ;;
+ *-*-cygwin* )
+ lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32
+ ;;
+ * ) # otherwise, assume *nix
+ lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32
+ ;;
+ esac
+ ;;
+ *-*-cygwin* )
+ case $build in
+ *-*-mingw* ) # actually msys
+ lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin
+ ;;
+ *-*-cygwin* )
+ lt_cv_to_host_file_cmd=func_convert_file_noop
+ ;;
+ * ) # otherwise, assume *nix
+ lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin
+ ;;
+ esac
+ ;;
+ * ) # unhandled hosts (and "normal" native builds)
+ lt_cv_to_host_file_cmd=func_convert_file_noop
+ ;;
+esac
+])
+to_host_file_cmd=$lt_cv_to_host_file_cmd
+AC_MSG_RESULT([$lt_cv_to_host_file_cmd])
+_LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd],
+ [0], [convert $build file names to $host format])dnl
+
+AC_MSG_CHECKING([how to convert $build file names to toolchain format])
+AC_CACHE_VAL(lt_cv_to_tool_file_cmd,
+[#assume ordinary cross tools, or native build.
+lt_cv_to_tool_file_cmd=func_convert_file_noop
+case $host in
+ *-*-mingw* )
+ case $build in
+ *-*-mingw* ) # actually msys
+ lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32
+ ;;
+ esac
+ ;;
+esac
+])
+to_tool_file_cmd=$lt_cv_to_tool_file_cmd
+AC_MSG_RESULT([$lt_cv_to_tool_file_cmd])
+_LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd],
+ [0], [convert $build files to toolchain format])dnl
+])# _LT_PATH_CONVERSION_FUNCTIONS
--- /dev/null
+# Helper functions for option handling. -*- Autoconf -*-
+#
+# Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software
+# Foundation, Inc.
+# Written by Gary V. Vaughan, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 8 ltoptions.m4
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])])
+
+
+# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME)
+# ------------------------------------------
+m4_define([_LT_MANGLE_OPTION],
+[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])])
+
+
+# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME)
+# ---------------------------------------
+# Set option OPTION-NAME for macro MACRO-NAME, and if there is a
+# matching handler defined, dispatch to it. Other OPTION-NAMEs are
+# saved as a flag.
+m4_define([_LT_SET_OPTION],
+[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl
+m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]),
+ _LT_MANGLE_DEFUN([$1], [$2]),
+ [m4_warning([Unknown $1 option '$2'])])[]dnl
+])
+
+
+# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET])
+# ------------------------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+m4_define([_LT_IF_OPTION],
+[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])])
+
+
+# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET)
+# -------------------------------------------------------
+# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME
+# are set.
+m4_define([_LT_UNLESS_OPTIONS],
+[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
+ [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option),
+ [m4_define([$0_found])])])[]dnl
+m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3
+])[]dnl
+])
+
+
+# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST)
+# ----------------------------------------
+# OPTION-LIST is a space-separated list of Libtool options associated
+# with MACRO-NAME. If any OPTION has a matching handler declared with
+# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about
+# the unknown option and exit.
+m4_defun([_LT_SET_OPTIONS],
+[# Set options
+m4_foreach([_LT_Option], m4_split(m4_normalize([$2])),
+ [_LT_SET_OPTION([$1], _LT_Option)])
+
+m4_if([$1],[LT_INIT],[
+ dnl
+ dnl Simply set some default values (i.e off) if boolean options were not
+ dnl specified:
+ _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no
+ ])
+ _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no
+ ])
+ dnl
+ dnl If no reference was made to various pairs of opposing options, then
+ dnl we run the default mode handler for the pair. For example, if neither
+ dnl 'shared' nor 'disable-shared' was passed, we enable building of shared
+ dnl archives by default:
+ _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED])
+ _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC])
+ _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC])
+ _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install],
+ [_LT_ENABLE_FAST_INSTALL])
+ _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4],
+ [_LT_WITH_AIX_SONAME([aix])])
+ ])
+])# _LT_SET_OPTIONS
+
+
+## --------------------------------- ##
+## Macros to handle LT_INIT options. ##
+## --------------------------------- ##
+
+# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME)
+# -----------------------------------------
+m4_define([_LT_MANGLE_DEFUN],
+[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])])
+
+
+# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE)
+# -----------------------------------------------
+m4_define([LT_OPTION_DEFINE],
+[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl
+])# LT_OPTION_DEFINE
+
+
+# dlopen
+# ------
+LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes
+])
+
+AU_DEFUN([AC_LIBTOOL_DLOPEN],
+[_LT_SET_OPTION([LT_INIT], [dlopen])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the 'dlopen' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], [])
+
+
+# win32-dll
+# ---------
+# Declare package support for building win32 dll's.
+LT_OPTION_DEFINE([LT_INIT], [win32-dll],
+[enable_win32_dll=yes
+
+case $host in
+*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*)
+ AC_CHECK_TOOL(AS, as, false)
+ AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+ AC_CHECK_TOOL(OBJDUMP, objdump, false)
+ ;;
+esac
+
+test -z "$AS" && AS=as
+_LT_DECL([], [AS], [1], [Assembler program])dnl
+
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl
+
+test -z "$OBJDUMP" && OBJDUMP=objdump
+_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl
+])# win32-dll
+
+AU_DEFUN([AC_LIBTOOL_WIN32_DLL],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+_LT_SET_OPTION([LT_INIT], [win32-dll])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the 'win32-dll' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], [])
+
+
+# _LT_ENABLE_SHARED([DEFAULT])
+# ----------------------------
+# implement the --enable-shared flag, and supports the 'shared' and
+# 'disable-shared' LT_INIT options.
+# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'.
+m4_define([_LT_ENABLE_SHARED],
+[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([shared],
+ [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
+ [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])],
+ [p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_shared=yes ;;
+ no) enable_shared=no ;;
+ *)
+ enable_shared=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+ for pkg in $enableval; do
+ IFS=$lt_save_ifs
+ if test "X$pkg" = "X$p"; then
+ enable_shared=yes
+ fi
+ done
+ IFS=$lt_save_ifs
+ ;;
+ esac],
+ [enable_shared=]_LT_ENABLE_SHARED_DEFAULT)
+
+ _LT_DECL([build_libtool_libs], [enable_shared], [0],
+ [Whether or not to build shared libraries])
+])# _LT_ENABLE_SHARED
+
+LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])])
+
+# Old names:
+AC_DEFUN([AC_ENABLE_SHARED],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared])
+])
+
+AC_DEFUN([AC_DISABLE_SHARED],
+[_LT_SET_OPTION([LT_INIT], [disable-shared])
+])
+
+AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)])
+AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_ENABLE_SHARED], [])
+dnl AC_DEFUN([AM_DISABLE_SHARED], [])
+
+
+
+# _LT_ENABLE_STATIC([DEFAULT])
+# ----------------------------
+# implement the --enable-static flag, and support the 'static' and
+# 'disable-static' LT_INIT options.
+# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'.
+m4_define([_LT_ENABLE_STATIC],
+[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([static],
+ [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@],
+ [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])],
+ [p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_static=yes ;;
+ no) enable_static=no ;;
+ *)
+ enable_static=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+ for pkg in $enableval; do
+ IFS=$lt_save_ifs
+ if test "X$pkg" = "X$p"; then
+ enable_static=yes
+ fi
+ done
+ IFS=$lt_save_ifs
+ ;;
+ esac],
+ [enable_static=]_LT_ENABLE_STATIC_DEFAULT)
+
+ _LT_DECL([build_old_libs], [enable_static], [0],
+ [Whether or not to build static libraries])
+])# _LT_ENABLE_STATIC
+
+LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])])
+
+# Old names:
+AC_DEFUN([AC_ENABLE_STATIC],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static])
+])
+
+AC_DEFUN([AC_DISABLE_STATIC],
+[_LT_SET_OPTION([LT_INIT], [disable-static])
+])
+
+AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)])
+AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AM_ENABLE_STATIC], [])
+dnl AC_DEFUN([AM_DISABLE_STATIC], [])
+
+
+
+# _LT_ENABLE_FAST_INSTALL([DEFAULT])
+# ----------------------------------
+# implement the --enable-fast-install flag, and support the 'fast-install'
+# and 'disable-fast-install' LT_INIT options.
+# DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'.
+m4_define([_LT_ENABLE_FAST_INSTALL],
+[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl
+AC_ARG_ENABLE([fast-install],
+ [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
+ [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
+ [p=${PACKAGE-default}
+ case $enableval in
+ yes) enable_fast_install=yes ;;
+ no) enable_fast_install=no ;;
+ *)
+ enable_fast_install=no
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+ for pkg in $enableval; do
+ IFS=$lt_save_ifs
+ if test "X$pkg" = "X$p"; then
+ enable_fast_install=yes
+ fi
+ done
+ IFS=$lt_save_ifs
+ ;;
+ esac],
+ [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT)
+
+_LT_DECL([fast_install], [enable_fast_install], [0],
+ [Whether or not to optimize for fast installation])dnl
+])# _LT_ENABLE_FAST_INSTALL
+
+LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])])
+LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])])
+
+# Old names:
+AU_DEFUN([AC_ENABLE_FAST_INSTALL],
+[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you put
+the 'fast-install' option into LT_INIT's first parameter.])
+])
+
+AU_DEFUN([AC_DISABLE_FAST_INSTALL],
+[_LT_SET_OPTION([LT_INIT], [disable-fast-install])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you put
+the 'disable-fast-install' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], [])
+dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], [])
+
+
+# _LT_WITH_AIX_SONAME([DEFAULT])
+# ----------------------------------
+# implement the --with-aix-soname flag, and support the `aix-soname=aix'
+# and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT
+# is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'.
+m4_define([_LT_WITH_AIX_SONAME],
+[m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl
+shared_archive_member_spec=
+case $host,$enable_shared in
+power*-*-aix[[5-9]]*,yes)
+ AC_MSG_CHECKING([which variant of shared library versioning to provide])
+ AC_ARG_WITH([aix-soname],
+ [AS_HELP_STRING([--with-aix-soname=aix|svr4|both],
+ [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])],
+ [case $withval in
+ aix|svr4|both)
+ ;;
+ *)
+ AC_MSG_ERROR([Unknown argument to --with-aix-soname])
+ ;;
+ esac
+ lt_cv_with_aix_soname=$with_aix_soname],
+ [AC_CACHE_VAL([lt_cv_with_aix_soname],
+ [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT)
+ with_aix_soname=$lt_cv_with_aix_soname])
+ AC_MSG_RESULT([$with_aix_soname])
+ if test aix != "$with_aix_soname"; then
+ # For the AIX way of multilib, we name the shared archive member
+ # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o',
+ # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File.
+ # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag,
+ # the AIX toolchain works better with OBJECT_MODE set (default 32).
+ if test 64 = "${OBJECT_MODE-32}"; then
+ shared_archive_member_spec=shr_64
+ else
+ shared_archive_member_spec=shr
+ fi
+ fi
+ ;;
+*)
+ with_aix_soname=aix
+ ;;
+esac
+
+_LT_DECL([], [shared_archive_member_spec], [0],
+ [Shared archive member basename, for filename based shared library versioning on AIX])dnl
+])# _LT_WITH_AIX_SONAME
+
+LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])])
+LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])])
+LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])])
+
+
+# _LT_WITH_PIC([MODE])
+# --------------------
+# implement the --with-pic flag, and support the 'pic-only' and 'no-pic'
+# LT_INIT options.
+# MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'.
+m4_define([_LT_WITH_PIC],
+[AC_ARG_WITH([pic],
+ [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@],
+ [try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
+ [lt_p=${PACKAGE-default}
+ case $withval in
+ yes|no) pic_mode=$withval ;;
+ *)
+ pic_mode=default
+ # Look at the argument we got. We use all the common list separators.
+ lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR,
+ for lt_pkg in $withval; do
+ IFS=$lt_save_ifs
+ if test "X$lt_pkg" = "X$lt_p"; then
+ pic_mode=yes
+ fi
+ done
+ IFS=$lt_save_ifs
+ ;;
+ esac],
+ [pic_mode=m4_default([$1], [default])])
+
+_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl
+])# _LT_WITH_PIC
+
+LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])])
+LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])])
+
+# Old name:
+AU_DEFUN([AC_LIBTOOL_PICMODE],
+[_LT_SET_OPTION([LT_INIT], [pic-only])
+AC_DIAGNOSE([obsolete],
+[$0: Remove this warning and the call to _LT_SET_OPTION when you
+put the 'pic-only' option into LT_INIT's first parameter.])
+])
+
+dnl aclocal-1.4 backwards compatibility:
+dnl AC_DEFUN([AC_LIBTOOL_PICMODE], [])
+
+## ----------------- ##
+## LTDL_INIT Options ##
+## ----------------- ##
+
+m4_define([_LTDL_MODE], [])
+LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive],
+ [m4_define([_LTDL_MODE], [nonrecursive])])
+LT_OPTION_DEFINE([LTDL_INIT], [recursive],
+ [m4_define([_LTDL_MODE], [recursive])])
+LT_OPTION_DEFINE([LTDL_INIT], [subproject],
+ [m4_define([_LTDL_MODE], [subproject])])
+
+m4_define([_LTDL_TYPE], [])
+LT_OPTION_DEFINE([LTDL_INIT], [installable],
+ [m4_define([_LTDL_TYPE], [installable])])
+LT_OPTION_DEFINE([LTDL_INIT], [convenience],
+ [m4_define([_LTDL_TYPE], [convenience])])
--- /dev/null
+# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*-
+#
+# Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software
+# Foundation, Inc.
+# Written by Gary V. Vaughan, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 6 ltsugar.m4
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])])
+
+
+# lt_join(SEP, ARG1, [ARG2...])
+# -----------------------------
+# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their
+# associated separator.
+# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier
+# versions in m4sugar had bugs.
+m4_define([lt_join],
+[m4_if([$#], [1], [],
+ [$#], [2], [[$2]],
+ [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])])
+m4_define([_lt_join],
+[m4_if([$#$2], [2], [],
+ [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])])
+
+
+# lt_car(LIST)
+# lt_cdr(LIST)
+# ------------
+# Manipulate m4 lists.
+# These macros are necessary as long as will still need to support
+# Autoconf-2.59, which quotes differently.
+m4_define([lt_car], [[$1]])
+m4_define([lt_cdr],
+[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])],
+ [$#], 1, [],
+ [m4_dquote(m4_shift($@))])])
+m4_define([lt_unquote], $1)
+
+
+# lt_append(MACRO-NAME, STRING, [SEPARATOR])
+# ------------------------------------------
+# Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'.
+# Note that neither SEPARATOR nor STRING are expanded; they are appended
+# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked).
+# No SEPARATOR is output if MACRO-NAME was previously undefined (different
+# than defined and empty).
+#
+# This macro is needed until we can rely on Autoconf 2.62, since earlier
+# versions of m4sugar mistakenly expanded SEPARATOR but not STRING.
+m4_define([lt_append],
+[m4_define([$1],
+ m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])])
+
+
+
+# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...])
+# ----------------------------------------------------------
+# Produce a SEP delimited list of all paired combinations of elements of
+# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list
+# has the form PREFIXmINFIXSUFFIXn.
+# Needed until we can rely on m4_combine added in Autoconf 2.62.
+m4_define([lt_combine],
+[m4_if(m4_eval([$# > 3]), [1],
+ [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl
+[[m4_foreach([_Lt_prefix], [$2],
+ [m4_foreach([_Lt_suffix],
+ ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[,
+ [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])])
+
+
+# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ])
+# -----------------------------------------------------------------------
+# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited
+# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ.
+m4_define([lt_if_append_uniq],
+[m4_ifdef([$1],
+ [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1],
+ [lt_append([$1], [$2], [$3])$4],
+ [$5])],
+ [lt_append([$1], [$2], [$3])$4])])
+
+
+# lt_dict_add(DICT, KEY, VALUE)
+# -----------------------------
+m4_define([lt_dict_add],
+[m4_define([$1($2)], [$3])])
+
+
+# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE)
+# --------------------------------------------
+m4_define([lt_dict_add_subkey],
+[m4_define([$1($2:$3)], [$4])])
+
+
+# lt_dict_fetch(DICT, KEY, [SUBKEY])
+# ----------------------------------
+m4_define([lt_dict_fetch],
+[m4_ifval([$3],
+ m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]),
+ m4_ifdef([$1($2)], [m4_defn([$1($2)])]))])
+
+
+# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE])
+# -----------------------------------------------------------------
+m4_define([lt_if_dict_fetch],
+[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4],
+ [$5],
+ [$6])])
+
+
+# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...])
+# --------------------------------------------------------------
+m4_define([lt_dict_filter],
+[m4_if([$5], [], [],
+ [lt_join(m4_quote(m4_default([$4], [[, ]])),
+ lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]),
+ [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl
+])
--- /dev/null
+# ltversion.m4 -- version numbers -*- Autoconf -*-
+#
+# Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc.
+# Written by Scott James Remnant, 2004
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# @configure_input@
+
+# serial 4179 ltversion.m4
+# This file is part of GNU Libtool
+
+m4_define([LT_PACKAGE_VERSION], [2.4.6])
+m4_define([LT_PACKAGE_REVISION], [2.4.6])
+
+AC_DEFUN([LTVERSION_VERSION],
+[macro_version='2.4.6'
+macro_revision='2.4.6'
+_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
+_LT_DECL(, macro_revision, 0)
+])
--- /dev/null
+# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*-
+#
+# Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software
+# Foundation, Inc.
+# Written by Scott James Remnant, 2004.
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+
+# serial 5 lt~obsolete.m4
+
+# These exist entirely to fool aclocal when bootstrapping libtool.
+#
+# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN),
+# which have later been changed to m4_define as they aren't part of the
+# exported API, or moved to Autoconf or Automake where they belong.
+#
+# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN
+# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us
+# using a macro with the same name in our local m4/libtool.m4 it'll
+# pull the old libtool.m4 in (it doesn't see our shiny new m4_define
+# and doesn't know about Autoconf macros at all.)
+#
+# So we provide this file, which has a silly filename so it's always
+# included after everything else. This provides aclocal with the
+# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
+# because those macros already exist, or will be overwritten later.
+# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6.
+#
+# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
+# Yes, that means every name once taken will need to remain here until
+# we give up compatibility with versions before 1.7, at which point
+# we need to keep only those names which we still refer to.
+
+# This is to help aclocal find these macros, as it can't see m4_define.
+AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])])
+
+m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])])
+m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])])
+m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])])
+m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])])
+m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])])
+m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])])
+m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])])
+m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])])
+m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])])
+m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])])
+m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])])
+m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])])
+m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])])
+m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])])
+m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])])
+m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])])
+m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])])
+m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])])
+m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])])
+m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])])
+m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])])
+m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])])
+m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])])
+m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])])
+m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])])
+m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])])
+m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])])
+m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])])
+m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])])
+m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])])
+m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])])
+m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])])
+m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])])
+m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])])
+m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])])
+m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])])
+m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])])
+m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])])
+m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])])
+m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])])
+m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])])
+m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])])
+m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])])
+m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])])
+m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])])
+m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])])
+m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])])
+m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])])
+m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])])
+m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])])
+m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])])
+m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])])
+m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])])
+m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])])
+m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])])
+m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])])
+m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])])
+m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])])
--- /dev/null
+project('libnice', 'c',
+ version: '0.1.16',
+ meson_version : '>= 0.49.1',
+ default_options : ['warning_level=1', 'buildtype=debugoptimized'])
+
+nice_version = meson.project_version()
+version_arr = nice_version.split('.')
+version_major = version_arr[0]
+version_minor = version_arr[1]
+version_micro = version_arr[2]
+if version_arr.length() == 4
+ version_nano = version_arr[3]
+else
+ version_nano = 0
+endif
+
+# maintain compatibility with the previous libtool versioning
+soversion = 10
+libversion = '10.9.0'
+
+glib_req = '>= 2.48'
+gnutls_req = '>= 2.12.0'
+gupnp_igd_req = '>= 0.2.4'
+gst_req = '>= 1.0.0'
+
+nice_datadir = join_paths(get_option('prefix'), get_option('datadir'))
+
+cc = meson.get_compiler('c')
+
+syslibs = []
+
+if host_machine.system() == 'windows'
+ syslibs += [cc.find_library('iphlpapi')]
+ syslibs += [cc.find_library('ws2_32')]
+elif host_machine.system() == 'sunos'
+ add_project_arguments('-D_XOPEN_SOURCE=600', language: 'c')
+ add_project_arguments('-D__EXTENSIONS__=1', language: 'c')
+ # inet_pton() is only used by the tests
+ syslibs += [cc.find_library('nsl')]
+ if not cc.has_function('inet_pton')
+ libnsl = cc.find_library('nsl', required: false)
+ if libnsl.found() and cc.has_function('inet_pton', dependencies: libnsl)
+ syslibs += [libnsl]
+ endif
+ endif
+ if not cc.has_function('socket')
+ libsocket = cc.find_library('socket', required: false)
+ libinet = cc.find_library('inet', required: false)
+ if cc.has_function('socket', dependencies: libsocket)
+ syslibs += [libsocket]
+ elif cc.has_function('socket', dependencies: libinet)
+ syslibs += [libinet]
+ else
+ error('Could not find right library for socket() on Solaris')
+ endif
+ endif
+endif
+
+if not cc.has_function('clock_gettime')
+ librt = cc.find_library('rt', required: false)
+ if cc.has_function('clock_gettime', dependencies: librt)
+ syslibs += [librt]
+ endif
+endif
+
+glib_req_minmax_str = glib_req.split().get(1).underscorify()
+add_project_arguments('-D_GNU_SOURCE',
+ '-DHAVE_CONFIG_H',
+ '-DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_' + glib_req_minmax_str,
+ '-DGLIB_VERSION_MAX_ALLOWED=GLIB_VERSION_' + glib_req_minmax_str,
+ language: 'c')
+
+cdata = configuration_data()
+
+cdata.set_quoted('PACKAGE_STRING', meson.project_name())
+cdata.set_quoted('PACKAGE_NAME', meson.project_name())
+cdata.set_quoted('PACKAGE', meson.project_name())
+cdata.set_quoted('VERSION', meson.project_version())
+
+cdata.set('NICEAPI_EXPORT', true,
+ description: 'Public library function implementation')
+
+# headers
+foreach h : ['arpa/inet.h', 'net/in.h', 'netdb.h', 'ifaddrs.h', 'unistd.h']
+ if cc.has_header(h)
+ define = 'HAVE_' + h.underscorify().to_upper()
+ cdata.set(define, 1)
+ endif
+endforeach
+
+# functions
+foreach f : ['poll', 'getifaddrs']
+ if cc.has_function(f)
+ define = 'HAVE_' + f.underscorify().to_upper()
+ cdata.set(define, 1)
+ endif
+endforeach
+
+if cc.has_argument('-fno-strict-aliasing')
+ add_project_arguments('-fno-strict-aliasing', language: 'c')
+endif
+
+# Extra compiler warnings (FIXME: not sure this makes sense to keep like this)
+warning_level = get_option('warning_level').to_int()
+werror = get_option('werror')
+
+warnings = []
+
+message('warning level: @0@'.format(warning_level))
+message('werror enabled: @0@'.format(werror))
+
+if warning_level >= 2
+ warnings += [
+ '-Wextra',
+ '-Wundef',
+ '-Wnested-externs',
+ '-Wwrite-strings',
+ '-Wpointer-arith',
+ '-Wmissing-declarations',
+ '-Wmissing-prototypes',
+ '-Wstrict-prototypes',
+ '-Wredundant-decls',
+ '-Wno-unused-parameter',
+ '-Wno-missing-field-initializers',
+ '-Wdeclaration-after-statement',
+ '-Wformat=2',
+ '-Wold-style-definition',
+ '-Wcast-align',
+ '-Wformat-nonliteral',
+ '-Wformat-security',
+ ]
+endif
+if warning_level >= 3
+ warnings += [
+ '-Wsign-compare',
+ '-Wstrict-aliasing',
+ '-Wshadow',
+ '-Winline',
+ '-Wpacked',
+ '-Wmissing-format-attribute',
+ '-Winit-self',
+ '-Wredundant-decls',
+ '-Wmissing-include-dirs',
+ '-Wunused-but-set-variable',
+ '-Warray-bounds',
+ ]
+ warnings += [
+ '-Wswitch-default',
+ '-Waggregate-return',
+ ]
+endif
+if werror
+ warnings += [
+ '-Wno-suggest-attribute=format',
+ '-Wno-cast-function-type',
+ ]
+endif
+
+foreach w : warnings
+ if cc.has_argument(w)
+ add_project_arguments(w, language: 'c')
+ endif
+endforeach
+
+# Dependencies
+gio_dep = dependency('gio-2.0', version: glib_req,
+ fallback: ['glib', 'libgio_dep'])
+gio_deps = [gio_dep]
+if gio_dep.type_name() == 'internal'
+ # A workaround for libgio_dep not having its dependencies correctly declared.
+ # Should be fixed in GLib 2.60.
+ gio_deps += [
+ dependency('', fallback: ['glib', 'libglib_dep']),
+ dependency('', fallback: ['glib', 'libgmodule_dep']),
+ dependency('', fallback: ['glib', 'libgobject_dep'])
+ ]
+endif
+gthread_dep = dependency('gthread-2.0',
+ fallback: ['glib', 'libgthread_dep'])
+
+# Cryto library
+opt_cryptolib = get_option('crypto-library')
+message('Crypto library: ' + opt_cryptolib)
+if opt_cryptolib != 'openssl'
+ crypto_dep = dependency('gnutls', version: gnutls_req, required: false)
+ cdata.set('HAVE_GNUTLS', crypto_dep.found())
+ if not crypto_dep.found()
+ if opt_cryptolib != 'auto'
+ error('GnuTLS requested as crypto library, but not found')
+ endif
+ crypto_dep = dependency('openssl', required: false,
+ fallback: ['openssl', 'openssl_dep'])
+ cdata.set('HAVE_OPENSSL', crypto_dep.found())
+ endif
+else
+ crypto_dep = dependency('openssl', required: false)
+ cdata.set('HAVE_OPENSSL', crypto_dep.found())
+ if not crypto_dep.found()
+ if opt_cryptolib != 'auto'
+ error('OpenSSL requested as crypto library, but not found')
+ endif
+ crypto_dep = dependency('gnutls', version: gnutls_req, required: false)
+ cdata.set('HAVE_GNUTLS', crypto_dep.found())
+ endif
+endif
+
+if not crypto_dep.found()
+ error('Either GnuTLS or OpenSSL is required as crypto library, but neither was found')
+endif
+
+# GStreamer
+gst_dep = dependency('gstreamer-base-1.0', version: gst_req,
+ required: get_option('gstreamer'),
+ fallback : ['gstreamer', 'gst_base_dep'])
+
+cdata.set('HAVE_GSTREAMER', gst_dep.found(), description: 'Build GStreamer plugin')
+
+# GUPnP IGD
+gupnp_igd_dep = dependency('gupnp-igd-1.0', version: gupnp_igd_req, required: get_option('gupnp'))
+cdata.set('HAVE_GUPNP', gupnp_igd_dep.found(), description: 'Use the GUPnP IGD library')
+
+libm = cc.find_library('m', required: false)
+
+nice_incs = include_directories('.', 'agent', 'random', 'socket', 'stun')
+
+nice_deps = gio_deps + [gthread_dep, crypto_dep, gupnp_igd_dep] + syslibs
+
+ignored_iface_prefix = get_option('ignored-network-interface-prefix')
+if ignored_iface_prefix != ''
+ cdata.set_quoted('IGNORED_IFACE_PREFIX', ignored_iface_prefix)
+endif
+
+gir = find_program('g-ir-scanner', required : get_option('introspection'))
+
+subdir('agent')
+subdir('stun')
+subdir('socket')
+subdir('random')
+subdir('nice')
+
+if gst_dep.found()
+ subdir('gst')
+endif
+
+if build_machine.system() == 'windows'
+ message('Disabling gtk-doc while building on Windows')
+else
+ if find_program('gtkdoc-scan', required: get_option('gtk_doc')).found()
+ subdir('docs/reference/libnice')
+ else
+ message('Not building documentation as gtk-doc was not found or disabled')
+ endif
+endif
+
+if not get_option('tests').disabled()
+ subdir('tests')
+endif
+
+if not get_option('examples').disabled()
+ subdir('examples')
+endif
+
+configure_file(output : 'config.h', configuration : cdata)
--- /dev/null
+option('gupnp', type: 'feature', value: 'auto',
+ description: 'Enable or disable GUPnP IGD support')
+option('gstreamer', type: 'feature', value: 'auto',
+ description: 'Enable or disable build of GStreamer plugins')
+option('ignored-network-interface-prefix', type: 'string', value: '',
+ description: 'Ignore network interfaces whose name starts with this string in the ICE connection check algorithm. For example, "virbr" to ignore virtual bridge interfaces added by virtd, which do not help in finding connectivity.')
+option('crypto-library', type: 'combo', choices : ['auto', 'gnutls', 'openssl'], value : 'auto')
+
+# Common feature options
+option('examples', type : 'feature', value : 'auto', yield : true,
+ description: 'Build examples')
+option('tests', type : 'feature', value : 'auto', yield : true,
+ description: 'Enable or disable unit tests')
+option('gtk_doc', type : 'feature', value : 'disabled', yield : true,
+ description: 'Generate API documentation with gtk-doc')
+option('introspection', type : 'feature', value : 'auto', yield : true,
+ description : 'Generate gobject-introspection bindings')
--- /dev/null
+#! /bin/sh
+# Common wrapper for a few potentially missing GNU programs.
+
+scriptversion=2018-03-07.03; # UTC
+
+# Copyright (C) 1996-2018 Free Software Foundation, Inc.
+# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+if test $# -eq 0; then
+ echo 1>&2 "Try '$0 --help' for more information"
+ exit 1
+fi
+
+case $1 in
+
+ --is-lightweight)
+ # Used by our autoconf macros to check whether the available missing
+ # script is modern enough.
+ exit 0
+ ;;
+
+ --run)
+ # Back-compat with the calling convention used by older automake.
+ shift
+ ;;
+
+ -h|--h|--he|--hel|--help)
+ echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due
+to PROGRAM being missing or too old.
+
+Options:
+ -h, --help display this help and exit
+ -v, --version output version information and exit
+
+Supported PROGRAM values:
+ aclocal autoconf autoheader autom4te automake makeinfo
+ bison yacc flex lex help2man
+
+Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and
+'g' are ignored when checking the name.
+
+Send bug reports to <bug-automake@gnu.org>."
+ exit $?
+ ;;
+
+ -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+ echo "missing $scriptversion (GNU Automake)"
+ exit $?
+ ;;
+
+ -*)
+ echo 1>&2 "$0: unknown '$1' option"
+ echo 1>&2 "Try '$0 --help' for more information"
+ exit 1
+ ;;
+
+esac
+
+# Run the given program, remember its exit status.
+"$@"; st=$?
+
+# If it succeeded, we are done.
+test $st -eq 0 && exit 0
+
+# Also exit now if we it failed (or wasn't found), and '--version' was
+# passed; such an option is passed most likely to detect whether the
+# program is present and works.
+case $2 in --version|--help) exit $st;; esac
+
+# Exit code 63 means version mismatch. This often happens when the user
+# tries to use an ancient version of a tool on a file that requires a
+# minimum version.
+if test $st -eq 63; then
+ msg="probably too old"
+elif test $st -eq 127; then
+ # Program was missing.
+ msg="missing on your system"
+else
+ # Program was found and executed, but failed. Give up.
+ exit $st
+fi
+
+perl_URL=https://www.perl.org/
+flex_URL=https://github.com/westes/flex
+gnu_software_URL=https://www.gnu.org/software
+
+program_details ()
+{
+ case $1 in
+ aclocal|automake)
+ echo "The '$1' program is part of the GNU Automake package:"
+ echo "<$gnu_software_URL/automake>"
+ echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:"
+ echo "<$gnu_software_URL/autoconf>"
+ echo "<$gnu_software_URL/m4/>"
+ echo "<$perl_URL>"
+ ;;
+ autoconf|autom4te|autoheader)
+ echo "The '$1' program is part of the GNU Autoconf package:"
+ echo "<$gnu_software_URL/autoconf/>"
+ echo "It also requires GNU m4 and Perl in order to run:"
+ echo "<$gnu_software_URL/m4/>"
+ echo "<$perl_URL>"
+ ;;
+ esac
+}
+
+give_advice ()
+{
+ # Normalize program name to check for.
+ normalized_program=`echo "$1" | sed '
+ s/^gnu-//; t
+ s/^gnu//; t
+ s/^g//; t'`
+
+ printf '%s\n' "'$1' is $msg."
+
+ configure_deps="'configure.ac' or m4 files included by 'configure.ac'"
+ case $normalized_program in
+ autoconf*)
+ echo "You should only need it if you modified 'configure.ac',"
+ echo "or m4 files included by it."
+ program_details 'autoconf'
+ ;;
+ autoheader*)
+ echo "You should only need it if you modified 'acconfig.h' or"
+ echo "$configure_deps."
+ program_details 'autoheader'
+ ;;
+ automake*)
+ echo "You should only need it if you modified 'Makefile.am' or"
+ echo "$configure_deps."
+ program_details 'automake'
+ ;;
+ aclocal*)
+ echo "You should only need it if you modified 'acinclude.m4' or"
+ echo "$configure_deps."
+ program_details 'aclocal'
+ ;;
+ autom4te*)
+ echo "You might have modified some maintainer files that require"
+ echo "the 'autom4te' program to be rebuilt."
+ program_details 'autom4te'
+ ;;
+ bison*|yacc*)
+ echo "You should only need it if you modified a '.y' file."
+ echo "You may want to install the GNU Bison package:"
+ echo "<$gnu_software_URL/bison/>"
+ ;;
+ lex*|flex*)
+ echo "You should only need it if you modified a '.l' file."
+ echo "You may want to install the Fast Lexical Analyzer package:"
+ echo "<$flex_URL>"
+ ;;
+ help2man*)
+ echo "You should only need it if you modified a dependency" \
+ "of a man page."
+ echo "You may want to install the GNU Help2man package:"
+ echo "<$gnu_software_URL/help2man/>"
+ ;;
+ makeinfo*)
+ echo "You should only need it if you modified a '.texi' file, or"
+ echo "any other file indirectly affecting the aspect of the manual."
+ echo "You might want to install the Texinfo package:"
+ echo "<$gnu_software_URL/texinfo/>"
+ echo "The spurious makeinfo call might also be the consequence of"
+ echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might"
+ echo "want to install GNU make:"
+ echo "<$gnu_software_URL/make/>"
+ ;;
+ *)
+ echo "You might have modified some files without having the proper"
+ echo "tools for further handling them. Check the 'README' file, it"
+ echo "often tells you about the needed prerequisites for installing"
+ echo "this package. You may also peek at any GNU archive site, in"
+ echo "case some other package contains this missing '$1' program."
+ ;;
+ esac
+}
+
+give_advice "$1" | sed -e '1s/^/WARNING: /' \
+ -e '2,$s/^/ /' >&2
+
+# Propagate the correct exit status (expected to be 127 for a program
+# not found, 63 for a program that failed due to version mismatch).
+exit $st
+
+# Local variables:
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC0"
+# time-stamp-end: "; # UTC"
+# End:
--- /dev/null
+#
+# Makefile.am for the Nice Glib ICE library
+#
+# (C) 2006, 2007 Collabora Ltd.
+# (C) 2006, 2007 Nokia Corporation. All rights reserved.
+#
+# Licensed under MPL 1.1/LGPL 2.1. See file COPYING.
+
+include $(top_srcdir)/common.mk
+
+lib_LTLIBRARIES = libnice.la
+
+libnice_la_SOURCES =
+libnice_la_DEPENDENCIES = \
+ $(top_builddir)/agent/libagent.la \
+ libnice.sym
+
+libnice_la_LIBADD = \
+ $(GLIB_LIBS) \
+ $(GUPNP_LIBS) \
+ $(top_builddir)/agent/libagent.la
+
+libnice_la_LDFLAGS = \
+ -export-symbols $(srcdir)/libnice.sym \
+ $(LIBNICE_LT_LDFLAGS)
+
+
+AM_CFLAGS = \
+ $(LIBNICE_CFLAGS) \
+ $(GLIB_CFLAGS) \
+ -I $(top_srcdir) \
+ -I $(top_srcdir)/agent \
+ -I $(top_srcdir)/random \
+ -I $(top_srcdir)/socket \
+ -I $(top_srcdir)/stun
+
+test-symbols.sh::
+ chmod +x $(srcdir)/$@
+
+libnice-symbols-test.c: libnice.sym
+ rm -f $@
+ while read s; do echo "void $$s(void) { }" ; done < $? > $@
+
+libnice-symbols-test.o: libnice-symbols-test.c
+ $(CC) $(CFLAGS) -c -o $@ $?
+
+libnice.symbols: libnice-symbols-test.o
+ rm -f $@
+ $(top_srcdir)/scripts/make-symbol-list.sh $? > $@
+
+CLEANFILES += libnice.symbols libnice-symbols-test.c libnice-symbols-test.o
+
+check_SCRIPTS = test-symbols.sh
+check_DATA = libnice.symbols
+
+TESTS = $(check_SCRIPTS)
+
+EXTRA_DIST = $(check_SCRIPTS) \
+ libnice.sym libnice.ver \
+ meson.build gen-map.py gen-def.py
+
+pkginclude_HEADERS = nice.h
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = nice.pc
+
--- /dev/null
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+#
+# Makefile.am for the Nice Glib ICE library
+#
+# (C) 2006, 2007 Collabora Ltd.
+# (C) 2006, 2007 Nokia Corporation. All rights reserved.
+#
+# Licensed under MPL 1.1/LGPL 2.1. See file COPYING.
+
+
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = nice
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/as-compiler-flag.m4 \
+ $(top_srcdir)/m4/ax_check_openssl.m4 \
+ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/introspection.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(pkginclude_HEADERS) \
+ $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES = nice.pc
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" \
+ "$(DESTDIR)$(pkgincludedir)"
+LTLIBRARIES = $(lib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+am_libnice_la_OBJECTS =
+libnice_la_OBJECTS = $(am_libnice_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+libnice_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libnice_la_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(libnice_la_SOURCES)
+DIST_SOURCES = $(libnice_la_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+DATA = $(pkgconfig_DATA)
+HEADERS = $(pkginclude_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__tty_colors_dummy = \
+ mgn= red= grn= lgn= blu= brg= std=; \
+ am__color_tests=no
+am__tty_colors = { \
+ $(am__tty_colors_dummy); \
+ if test "X$(AM_COLOR_TESTS)" = Xno; then \
+ am__color_tests=no; \
+ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
+ am__color_tests=yes; \
+ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
+ am__color_tests=yes; \
+ fi; \
+ if test $$am__color_tests = yes; then \
+ red='\e[0;31m'; \
+ grn='\e[0;32m'; \
+ lgn='\e[1;32m'; \
+ blu='\e[1;34m'; \
+ mgn='\e[0;35m'; \
+ brg='\e[1m'; \
+ std='\e[m'; \
+ fi; \
+}
+am__recheck_rx = ^[ ]*:recheck:[ ]*
+am__global_test_result_rx = ^[ ]*:global-test-result:[ ]*
+am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]*
+# A command that, given a newline-separated list of test names on the
+# standard input, print the name of the tests that are to be re-run
+# upon "make recheck".
+am__list_recheck_tests = $(AWK) '{ \
+ recheck = 1; \
+ while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+ { \
+ if (rc < 0) \
+ { \
+ if ((getline line2 < ($$0 ".log")) < 0) \
+ recheck = 0; \
+ break; \
+ } \
+ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \
+ { \
+ recheck = 0; \
+ break; \
+ } \
+ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \
+ { \
+ break; \
+ } \
+ }; \
+ if (recheck) \
+ print $$0; \
+ close ($$0 ".trs"); \
+ close ($$0 ".log"); \
+}'
+# A command that, given a newline-separated list of test names on the
+# standard input, create the global log from their .trs and .log files.
+am__create_global_log = $(AWK) ' \
+function fatal(msg) \
+{ \
+ print "fatal: making $@: " msg | "cat >&2"; \
+ exit 1; \
+} \
+function rst_section(header) \
+{ \
+ print header; \
+ len = length(header); \
+ for (i = 1; i <= len; i = i + 1) \
+ printf "="; \
+ printf "\n\n"; \
+} \
+{ \
+ copy_in_global_log = 1; \
+ global_test_result = "RUN"; \
+ while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+ { \
+ if (rc < 0) \
+ fatal("failed to read from " $$0 ".trs"); \
+ if (line ~ /$(am__global_test_result_rx)/) \
+ { \
+ sub("$(am__global_test_result_rx)", "", line); \
+ sub("[ ]*$$", "", line); \
+ global_test_result = line; \
+ } \
+ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \
+ copy_in_global_log = 0; \
+ }; \
+ if (copy_in_global_log) \
+ { \
+ rst_section(global_test_result ": " $$0); \
+ while ((rc = (getline line < ($$0 ".log"))) != 0) \
+ { \
+ if (rc < 0) \
+ fatal("failed to read from " $$0 ".log"); \
+ print line; \
+ }; \
+ printf "\n"; \
+ }; \
+ close ($$0 ".trs"); \
+ close ($$0 ".log"); \
+}'
+# Restructured Text title.
+am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; }
+# Solaris 10 'make', and several other traditional 'make' implementations,
+# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it
+# by disabling -e (using the XSI extension "set +e") if it's set.
+am__sh_e_setup = case $$- in *e*) set +e;; esac
+# Default flags passed to test drivers.
+am__common_driver_flags = \
+ --color-tests "$$am__color_tests" \
+ --enable-hard-errors "$$am__enable_hard_errors" \
+ --expect-failure "$$am__expect_failure"
+# To be inserted before the command running the test. Creates the
+# directory for the log if needed. Stores in $dir the directory
+# containing $f, in $tst the test, in $log the log. Executes the
+# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and
+# passes TESTS_ENVIRONMENT. Set up options for the wrapper that
+# will run the test scripts (or their associated LOG_COMPILER, if
+# thy have one).
+am__check_pre = \
+$(am__sh_e_setup); \
+$(am__vpath_adj_setup) $(am__vpath_adj) \
+$(am__tty_colors); \
+srcdir=$(srcdir); export srcdir; \
+case "$@" in \
+ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \
+ *) am__odir=.;; \
+esac; \
+test "x$$am__odir" = x"." || test -d "$$am__odir" \
+ || $(MKDIR_P) "$$am__odir" || exit $$?; \
+if test -f "./$$f"; then dir=./; \
+elif test -f "$$f"; then dir=; \
+else dir="$(srcdir)/"; fi; \
+tst=$$dir$$f; log='$@'; \
+if test -n '$(DISABLE_HARD_ERRORS)'; then \
+ am__enable_hard_errors=no; \
+else \
+ am__enable_hard_errors=yes; \
+fi; \
+case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \
+ am__expect_failure=yes;; \
+ *) \
+ am__expect_failure=no;; \
+esac; \
+$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT)
+# A shell command to get the names of the tests scripts with any registered
+# extension removed (i.e., equivalently, the names of the test logs, with
+# the '.log' extension removed). The result is saved in the shell variable
+# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly,
+# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)",
+# since that might cause problem with VPATH rewrites for suffix-less tests.
+# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'.
+am__set_TESTS_bases = \
+ bases='$(TEST_LOGS)'; \
+ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \
+ bases=`echo $$bases`
+RECHECK_LOGS = $(TEST_LOGS)
+AM_RECURSIVE_TARGETS = check recheck
+TEST_SUITE_LOG = test-suite.log
+TEST_EXTENSIONS = @EXEEXT@ .test
+LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS)
+am__set_b = \
+ case '$@' in \
+ */*) \
+ case '$*' in \
+ */*) b='$*';; \
+ *) b=`echo '$@' | sed 's/\.log$$//'`; \
+ esac;; \
+ *) \
+ b='$*';; \
+ esac
+am__test_logs1 = $(TESTS:=.log)
+am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log)
+TEST_LOGS = $(am__test_logs2:.test.log=.log)
+TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver
+TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \
+ $(TEST_LOG_FLAGS)
+am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/nice.pc.in \
+ $(top_srcdir)/common.mk $(top_srcdir)/test-driver
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+pkgincludedir = $(includedir)/nice
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCACHE_DISABLE = @CCACHE_DISABLE@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GST010_CFLAGS = @GST010_CFLAGS@
+GST010_LIBS = @GST010_LIBS@
+GST_CFLAGS = @GST_CFLAGS@
+GST_CHECK_CFLAGS = @GST_CHECK_CFLAGS@
+GST_CHECK_LIBS = @GST_CHECK_LIBS@
+GST_LIBS = @GST_LIBS@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@
+GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@
+GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@
+GTKDOC_MKPDF = @GTKDOC_MKPDF@
+GTKDOC_REBASE = @GTKDOC_REBASE@
+GUPNP_CFLAGS = @GUPNP_CFLAGS@
+GUPNP_LIBS = @GUPNP_LIBS@
+GUPNP_PACKAGES = @GUPNP_PACKAGES@
+GUPNP_PACKAGES_PRIVATE = @GUPNP_PACKAGES_PRIVATE@
+GUPNP_PACKAGES_PUBLIC = @GUPNP_PACKAGES_PUBLIC@
+HAVE_GUPNP = @HAVE_GUPNP@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@
+INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@
+INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@
+INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@
+INTROSPECTION_LIBS = @INTROSPECTION_LIBS@
+INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@
+INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
+INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBNICE_CFLAGS = @LIBNICE_CFLAGS@
+LIBNICE_LT_LDFLAGS = @LIBNICE_LT_LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBRT = @LIBRT@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NICE_PACKAGES_PRIVATE = @NICE_PACKAGES_PRIVATE@
+NICE_PACKAGES_PUBLIC = @NICE_PACKAGES_PUBLIC@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_INCLUDES = @OPENSSL_INCLUDES@
+OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+UPNP_ENABLED = @UPNP_ENABLED@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gstplugin010dir = @gstplugin010dir@
+gstplugindir = @gstplugindir@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+CLEANFILES = *.gcno *.gcda libnice.symbols libnice-symbols-test.c \
+ libnice-symbols-test.o
+LOG_DRIVER = $(top_srcdir)/scripts/valgrind-test-driver
+lib_LTLIBRARIES = libnice.la
+libnice_la_SOURCES =
+libnice_la_DEPENDENCIES = \
+ $(top_builddir)/agent/libagent.la \
+ libnice.sym
+
+libnice_la_LIBADD = \
+ $(GLIB_LIBS) \
+ $(GUPNP_LIBS) \
+ $(top_builddir)/agent/libagent.la
+
+libnice_la_LDFLAGS = \
+ -export-symbols $(srcdir)/libnice.sym \
+ $(LIBNICE_LT_LDFLAGS)
+
+AM_CFLAGS = \
+ $(LIBNICE_CFLAGS) \
+ $(GLIB_CFLAGS) \
+ -I $(top_srcdir) \
+ -I $(top_srcdir)/agent \
+ -I $(top_srcdir)/random \
+ -I $(top_srcdir)/socket \
+ -I $(top_srcdir)/stun
+
+check_SCRIPTS = test-symbols.sh
+check_DATA = libnice.symbols
+TESTS = $(check_SCRIPTS)
+EXTRA_DIST = $(check_SCRIPTS) \
+ libnice.sym libnice.ver \
+ meson.build gen-map.py gen-def.py
+
+pkginclude_HEADERS = nice.h
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = nice.pc
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .log .test .test$(EXEEXT) .trs
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/common.mk $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu nice/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu nice/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+$(top_srcdir)/common.mk $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+nice.pc: $(top_builddir)/config.status $(srcdir)/nice.pc.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+ }
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+libnice.la: $(libnice_la_OBJECTS) $(libnice_la_DEPENDENCIES) $(EXTRA_libnice_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libnice_la_LINK) -rpath $(libdir) $(libnice_la_OBJECTS) $(libnice_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-pkgconfigDATA: $(pkgconfig_DATA)
+ @$(NORMAL_INSTALL)
+ @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \
+ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \
+ done
+
+uninstall-pkgconfigDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir)
+install-pkgincludeHEADERS: $(pkginclude_HEADERS)
+ @$(NORMAL_INSTALL)
+ @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(pkgincludedir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkgincludedir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkgincludedir)" || exit $$?; \
+ done
+
+uninstall-pkgincludeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(pkgincludedir)'; $(am__uninstall_files_from_dir)
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+# Recover from deleted '.trs' file; this should ensure that
+# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create
+# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells
+# to avoid problems with "make -n".
+.log.trs:
+ rm -f $< $@
+ $(MAKE) $(AM_MAKEFLAGS) $<
+
+# Leading 'am--fnord' is there to ensure the list of targets does not
+# expand to empty, as could happen e.g. with make check TESTS=''.
+am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck)
+am--force-recheck:
+ @:
+
+$(TEST_SUITE_LOG): $(TEST_LOGS)
+ @$(am__set_TESTS_bases); \
+ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \
+ redo_bases=`for i in $$bases; do \
+ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \
+ done`; \
+ if test -n "$$redo_bases"; then \
+ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \
+ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \
+ if $(am__make_dryrun); then :; else \
+ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \
+ fi; \
+ fi; \
+ if test -n "$$am__remaking_logs"; then \
+ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \
+ "recursion detected" >&2; \
+ elif test -n "$$redo_logs"; then \
+ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \
+ fi; \
+ if $(am__make_dryrun); then :; else \
+ st=0; \
+ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \
+ for i in $$redo_bases; do \
+ test -f $$i.trs && test -r $$i.trs \
+ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \
+ test -f $$i.log && test -r $$i.log \
+ || { echo "$$errmsg $$i.log" >&2; st=1; }; \
+ done; \
+ test $$st -eq 0 || exit 1; \
+ fi
+ @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \
+ ws='[ ]'; \
+ results=`for b in $$bases; do echo $$b.trs; done`; \
+ test -n "$$results" || results=/dev/null; \
+ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \
+ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \
+ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \
+ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \
+ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \
+ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \
+ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \
+ if test `expr $$fail + $$xpass + $$error` -eq 0; then \
+ success=true; \
+ else \
+ success=false; \
+ fi; \
+ br='==================='; br=$$br$$br$$br$$br; \
+ result_count () \
+ { \
+ if test x"$$1" = x"--maybe-color"; then \
+ maybe_colorize=yes; \
+ elif test x"$$1" = x"--no-color"; then \
+ maybe_colorize=no; \
+ else \
+ echo "$@: invalid 'result_count' usage" >&2; exit 4; \
+ fi; \
+ shift; \
+ desc=$$1 count=$$2; \
+ if test $$maybe_colorize = yes && test $$count -gt 0; then \
+ color_start=$$3 color_end=$$std; \
+ else \
+ color_start= color_end=; \
+ fi; \
+ echo "$${color_start}# $$desc $$count$${color_end}"; \
+ }; \
+ create_testsuite_report () \
+ { \
+ result_count $$1 "TOTAL:" $$all "$$brg"; \
+ result_count $$1 "PASS: " $$pass "$$grn"; \
+ result_count $$1 "SKIP: " $$skip "$$blu"; \
+ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \
+ result_count $$1 "FAIL: " $$fail "$$red"; \
+ result_count $$1 "XPASS:" $$xpass "$$red"; \
+ result_count $$1 "ERROR:" $$error "$$mgn"; \
+ }; \
+ { \
+ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \
+ $(am__rst_title); \
+ create_testsuite_report --no-color; \
+ echo; \
+ echo ".. contents:: :depth: 2"; \
+ echo; \
+ for b in $$bases; do echo $$b; done \
+ | $(am__create_global_log); \
+ } >$(TEST_SUITE_LOG).tmp || exit 1; \
+ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \
+ if $$success; then \
+ col="$$grn"; \
+ else \
+ col="$$red"; \
+ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \
+ fi; \
+ echo "$${col}$$br$${std}"; \
+ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \
+ echo "$${col}$$br$${std}"; \
+ create_testsuite_report --maybe-color; \
+ echo "$$col$$br$$std"; \
+ if $$success; then :; else \
+ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \
+ if test -n "$(PACKAGE_BUGREPORT)"; then \
+ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \
+ fi; \
+ echo "$$col$$br$$std"; \
+ fi; \
+ $$success || exit 1
+
+check-TESTS: $(check_SCRIPTS) $(check_DATA)
+ @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list
+ @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list
+ @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+ @set +e; $(am__set_TESTS_bases); \
+ log_list=`for i in $$bases; do echo $$i.log; done`; \
+ trs_list=`for i in $$bases; do echo $$i.trs; done`; \
+ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \
+ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \
+ exit $$?;
+recheck: all $(check_SCRIPTS) $(check_DATA)
+ @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+ @set +e; $(am__set_TESTS_bases); \
+ bases=`for i in $$bases; do echo $$i; done \
+ | $(am__list_recheck_tests)` || exit 1; \
+ log_list=`for i in $$bases; do echo $$i.log; done`; \
+ log_list=`echo $$log_list`; \
+ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \
+ am__force_recheck=am--force-recheck \
+ TEST_LOGS="$$log_list"; \
+ exit $$?
+test-symbols.sh.log: test-symbols.sh
+ @p='test-symbols.sh'; \
+ b='test-symbols.sh'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+.test.log:
+ @p='$<'; \
+ $(am__set_b); \
+ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+@am__EXEEXT_TRUE@.test$(EXEEXT).log:
+@am__EXEEXT_TRUE@ @p='$<'; \
+@am__EXEEXT_TRUE@ $(am__set_b); \
+@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \
+@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT)
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) $(check_SCRIPTS) $(check_DATA)
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(pkgincludedir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+ -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS)
+ -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs)
+ -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pkgconfigDATA install-pkgincludeHEADERS
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-libLTLIBRARIES uninstall-pkgconfigDATA \
+ uninstall-pkgincludeHEADERS
+
+.MAKE: check-am install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \
+ clean-generic clean-libLTLIBRARIES clean-libtool cscopelist-am \
+ ctags ctags-am distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-libLTLIBRARIES install-man install-pdf \
+ install-pdf-am install-pkgconfigDATA install-pkgincludeHEADERS \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ recheck tags tags-am uninstall uninstall-am \
+ uninstall-libLTLIBRARIES uninstall-pkgconfigDATA \
+ uninstall-pkgincludeHEADERS
+
+.PRECIOUS: Makefile
+
+
+check-valgrind:
+ $(MAKE) TESTS_ENVIRONMENT="USE_VALGRIND=1 " check
+
+.PHONY: check-valgrind
+
+test-symbols.sh::
+ chmod +x $(srcdir)/$@
+
+libnice-symbols-test.c: libnice.sym
+ rm -f $@
+ while read s; do echo "void $$s(void) { }" ; done < $? > $@
+
+libnice-symbols-test.o: libnice-symbols-test.c
+ $(CC) $(CFLAGS) -c -o $@ $?
+
+libnice.symbols: libnice-symbols-test.o
+ rm -f $@
+ $(top_srcdir)/scripts/make-symbol-list.sh $? > $@
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null
+#!/usr/bin/env python3
+#
+# gen-def.py LIBNICE.SYM
+import os
+import sys
+
+try:
+ sym_file = sys.argv[1]
+except:
+ print('Usage: gen-def.py SYM-FILE')
+ exit(-1)
+
+f = open(os.path.join(sym_file), 'r')
+
+print('EXPORTS')
+for line in f:
+ print(' ' + line.strip())
+
+f.close()
--- /dev/null
+#!/usr/bin/env python3
+#
+# gen-map.py LIBNICE.SYM
+import os
+import sys
+
+try:
+ sym_file = sys.argv[1]
+except:
+ print('Usage: gen-map.py SYM-FILE')
+ exit(-1)
+
+f = open(os.path.join(sym_file), 'r')
+
+print('''{
+global:''')
+
+for line in f:
+ print('\t' + line.strip() + ';')
+
+print('''local:
+ *;
+};''')
+
+f.close()
--- /dev/null
+nice_address_copy_to_sockaddr
+nice_address_dup
+nice_address_equal
+nice_address_equal_no_port
+nice_address_free
+nice_address_get_port
+nice_address_init
+nice_address_ip_version
+nice_address_is_private
+nice_address_is_valid
+nice_address_new
+nice_address_set_from_sockaddr
+nice_address_set_from_string
+nice_address_set_ipv4
+nice_address_set_ipv6
+nice_address_set_port
+nice_address_to_string
+nice_agent_add_local_address
+nice_agent_add_stream
+nice_agent_close_async
+nice_agent_recv
+nice_agent_recv_messages
+nice_agent_recv_nonblocking
+nice_agent_recv_messages_nonblocking
+nice_agent_attach_recv
+nice_agent_forget_relays
+nice_agent_gather_candidates
+nice_agent_generate_local_candidate_sdp
+nice_agent_generate_local_sdp
+nice_agent_generate_local_stream_sdp
+nice_agent_get_component_state
+nice_agent_get_default_local_candidate
+nice_agent_get_io_stream
+nice_agent_get_local_candidates
+nice_agent_get_local_credentials
+nice_agent_get_remote_candidates
+nice_agent_get_selected_pair
+nice_agent_get_selected_socket
+nice_agent_get_stream_name
+nice_agent_get_type
+nice_agent_new
+nice_agent_new_full
+nice_agent_new_reliable
+nice_agent_option_get_type
+nice_agent_parse_remote_candidate_sdp
+nice_agent_parse_remote_sdp
+nice_agent_parse_remote_stream_sdp
+nice_agent_peer_candidate_gathering_done
+nice_agent_remove_stream
+nice_agent_restart
+nice_agent_restart_stream
+nice_agent_send
+nice_agent_send_messages_nonblocking
+nice_agent_set_port_range
+nice_agent_set_relay_info
+nice_agent_set_remote_candidates
+nice_agent_set_remote_credentials
+nice_agent_set_local_credentials
+nice_agent_set_selected_pair
+nice_agent_set_selected_remote_candidate
+nice_agent_set_software
+nice_agent_set_stream_name
+nice_agent_set_stream_tos
+nice_candidate_copy
+nice_candidate_equal_target
+nice_candidate_free
+nice_candidate_get_type
+nice_candidate_new
+nice_candidate_transport_get_type
+nice_candidate_type_get_type
+nice_compatibility_get_type
+nice_component_state_get_type
+nice_component_state_to_string
+nice_component_type_get_type
+nice_debug_disable
+nice_debug_enable
+nice_interfaces_get_ip_for_interface
+nice_interfaces_get_local_interfaces
+nice_interfaces_get_local_ips
+nice_io_stream_new
+nice_input_stream_new
+nice_nomination_mode_get_type
+nice_output_stream_new
+nice_proxy_type_get_type
+nice_relay_type_get_type
+pseudo_tcp_debug_level_get_type
+pseudo_tcp_set_debug_level
+pseudo_tcp_shutdown_get_type
+pseudo_tcp_socket_close
+pseudo_tcp_socket_connect
+pseudo_tcp_socket_get_error
+pseudo_tcp_socket_get_next_clock
+pseudo_tcp_socket_get_type
+pseudo_tcp_socket_is_closed
+pseudo_tcp_socket_is_closed_remotely
+pseudo_tcp_socket_new
+pseudo_tcp_socket_notify_clock
+pseudo_tcp_socket_notify_mtu
+pseudo_tcp_socket_notify_packet
+pseudo_tcp_socket_recv
+pseudo_tcp_socket_send
+pseudo_tcp_socket_shutdown
+pseudo_tcp_state_get_type
+pseudo_tcp_write_result_get_type
+stun_agent_build_unknown_attributes_error
+stun_agent_default_validater
+stun_agent_finish_message
+stun_agent_forget_transaction
+stun_agent_init
+stun_agent_init_error
+stun_agent_init_indication
+stun_agent_init_request
+stun_agent_init_response
+stun_agent_set_software
+stun_agent_validate
+stun_debug_disable
+stun_debug_enable
+stun_message_append
+stun_message_append32
+stun_message_append64
+stun_message_append_addr
+stun_message_append_bytes
+stun_message_append_error
+stun_message_append_flag
+stun_message_append_string
+stun_message_append_xor_addr
+stun_message_append_xor_addr_full
+stun_message_find
+stun_message_find32
+stun_message_find64
+stun_message_find_addr
+stun_message_find_error
+stun_message_find_flag
+stun_message_find_string
+stun_message_find_xor_addr
+stun_message_find_xor_addr_full
+stun_message_get_class
+stun_message_get_method
+stun_message_has_attribute
+stun_message_has_cookie
+stun_message_id
+stun_message_init
+stun_message_length
+stun_message_validate_buffer_length
+stun_optional
+stun_strerror
+stun_timer_refresh
+stun_timer_remainder
+stun_timer_start
+stun_timer_start_reliable
+stun_usage_bind_create
+stun_usage_bind_keepalive
+stun_usage_bind_process
+stun_usage_bind_run
+stun_usage_ice_conncheck_create
+stun_usage_ice_conncheck_create_reply
+stun_usage_ice_conncheck_priority
+stun_usage_ice_conncheck_process
+stun_usage_ice_conncheck_use_candidate
+stun_usage_turn_create
+stun_usage_turn_create_refresh
+stun_usage_turn_process
+stun_usage_turn_refresh_process
--- /dev/null
+
+libnice {
+global:
+ nice_*;
+};
+
+HIDDEN {
+local:
+ *;
+};
+
--- /dev/null
+nice_gen_sources = []
+nice_link_args = []
+
+# libnice.def
+libnice_def = custom_target('libnice.def',
+ command: [find_program('gen-def.py'), '@INPUT@'],
+ input: 'libnice.sym',
+ output: 'libnice.def',
+ capture: true)
+
+# map file
+mapfile = custom_target('libnice.map',
+ command: [find_program('gen-map.py'), '@INPUT@'],
+ input: 'libnice.sym',
+ output: 'libnice.map',
+ capture: true)
+# We need to check with a file that exists at configure time!
+if cc.has_link_argument('-Wl,--version-script,@0@/libnice.ver'.format(meson.current_source_dir()))
+ nice_link_args += ['-Wl,--version-script,@0@'.format(mapfile.full_path())]
+endif
+
+libnice = library('nice',
+ link_whole: [libagent, libsocket, libstun, librandom],
+ dependencies: nice_deps,
+ version : libversion,
+ soversion : soversion,
+ vs_module_defs: libnice_def,
+ link_args: nice_link_args,
+ link_depends: mapfile,
+ install: true)
+
+install_headers('nice.h', subdir: 'nice')
+nice_include = include_directories('.')
+
+# introspection
+build_gir = gir.found() and not get_option('introspection').disabled()
+if build_gir
+ nice_gen_sources += [
+ gnome.generate_gir(libnice,
+ sources : [agent_headers, agent_sources],
+ namespace : 'Nice',
+ nsversion : '0.1',
+ identifier_prefix : 'Nice',
+ symbol_prefix: 'nice',
+ export_packages: 'nice',
+ includes: ['GObject-2.0', 'Gio-2.0'],
+ extra_args: ['--accept-unprefixed'],
+ install: true)
+ ]
+endif
+
+libnice_dep = declare_dependency(link_with : libnice,
+ include_directories : [agent_include, nice_include],
+ # Everything that uses libnice needs this built to compile
+ sources : nice_gen_sources,
+ dependencies: nice_deps)
+
+# pkg-config file
+pkg = import('pkgconfig')
+upnp_enabled_string = gupnp_igd_dep.found() ? 'true' : 'false'
+pkg.generate(libnice,
+ name: 'libnice',
+ filebase: 'nice',
+ subdirs: 'nice',
+ description: 'ICE library',
+ libraries: gio_dep,
+ variables: ['upnp_enabled=@0@'.format(upnp_enabled_string)])
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2006-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2006-2009 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Dafydd Harries, Collabora Ltd.
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef _NICE_H
+#define _NICE_H
+
+#include "agent.h"
+#include "interfaces.h"
+
+#endif /* _NICE_H */
+
--- /dev/null
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+upnp_enabled=@UPNP_ENABLED@
+
+Name: libnice
+Description: ICE library
+Version: @VERSION@
+Requires: @NICE_PACKAGES_PUBLIC@ @GUPNP_PACKAGES_PUBLIC@
+Requires.private: @NICE_PACKAGES_PRIVATE@ @GUPNP_PACKAGES_PRIVATE@
+Libs: -L${libdir} -lnice
+Cflags: -I${includedir}/nice -I${includedir}
--- /dev/null
+#!/bin/sh
+
+set -e
+
+if test -z "$srcdir"; then
+ srcdir=$(dirname $0)
+fi
+
+check_symbols=$srcdir/../scripts/check-symbols.sh
+
+if ! test -f $check_symbols; then
+ echo "cannot find check-symbols.sh"
+ exit 1
+fi
+
+if ! test -f .libs/libnice.so; then
+ echo "no shared object found" >&2
+ exit 77
+fi
+
+sh $check_symbols .libs/libnice.so libnice.symbols
--- /dev/null
+#
+# Makefile.am for the Nice Glib ICE library
+#
+# (C) 2006, 2007 Collabora Ltd.
+# (C) 2006, 2007 Nokia Corporation. All rights reserved.
+#
+# Licensed under MPL 1.1/LGPL 2.1. See file COPYING.
+
+include $(top_srcdir)/common.mk
+
+AM_CFLAGS = $(LIBNICE_CFLAGS) $(GLIB_CFLAGS)
+
+noinst_LTLIBRARIES = libnice-random.la
+
+libnice_random_la_SOURCES = \
+ random.h \
+ random.c \
+ random-glib.h \
+ random-glib.c
+
+check_PROGRAMS = test
+
+test_LDADD = libnice-random.la $(GLIB_LIBS)
+
+TESTS = $(check_PROGRAMS)
+
+EXTRA_DIST = meson.build
--- /dev/null
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+#
+# Makefile.am for the Nice Glib ICE library
+#
+# (C) 2006, 2007 Collabora Ltd.
+# (C) 2006, 2007 Nokia Corporation. All rights reserved.
+#
+# Licensed under MPL 1.1/LGPL 2.1. See file COPYING.
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+check_PROGRAMS = test$(EXEEXT)
+subdir = random
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/as-compiler-flag.m4 \
+ $(top_srcdir)/m4/ax_check_openssl.m4 \
+ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/introspection.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libnice_random_la_LIBADD =
+am_libnice_random_la_OBJECTS = random.lo random-glib.lo
+libnice_random_la_OBJECTS = $(am_libnice_random_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+test_SOURCES = test.c
+test_OBJECTS = test.$(OBJEXT)
+am__DEPENDENCIES_1 =
+test_DEPENDENCIES = libnice-random.la $(am__DEPENDENCIES_1)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/random-glib.Plo \
+ ./$(DEPDIR)/random.Plo ./$(DEPDIR)/test.Po
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(libnice_random_la_SOURCES) test.c
+DIST_SOURCES = $(libnice_random_la_SOURCES) test.c
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__tty_colors_dummy = \
+ mgn= red= grn= lgn= blu= brg= std=; \
+ am__color_tests=no
+am__tty_colors = { \
+ $(am__tty_colors_dummy); \
+ if test "X$(AM_COLOR_TESTS)" = Xno; then \
+ am__color_tests=no; \
+ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
+ am__color_tests=yes; \
+ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
+ am__color_tests=yes; \
+ fi; \
+ if test $$am__color_tests = yes; then \
+ red='\e[0;31m'; \
+ grn='\e[0;32m'; \
+ lgn='\e[1;32m'; \
+ blu='\e[1;34m'; \
+ mgn='\e[0;35m'; \
+ brg='\e[1m'; \
+ std='\e[m'; \
+ fi; \
+}
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__recheck_rx = ^[ ]*:recheck:[ ]*
+am__global_test_result_rx = ^[ ]*:global-test-result:[ ]*
+am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]*
+# A command that, given a newline-separated list of test names on the
+# standard input, print the name of the tests that are to be re-run
+# upon "make recheck".
+am__list_recheck_tests = $(AWK) '{ \
+ recheck = 1; \
+ while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+ { \
+ if (rc < 0) \
+ { \
+ if ((getline line2 < ($$0 ".log")) < 0) \
+ recheck = 0; \
+ break; \
+ } \
+ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \
+ { \
+ recheck = 0; \
+ break; \
+ } \
+ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \
+ { \
+ break; \
+ } \
+ }; \
+ if (recheck) \
+ print $$0; \
+ close ($$0 ".trs"); \
+ close ($$0 ".log"); \
+}'
+# A command that, given a newline-separated list of test names on the
+# standard input, create the global log from their .trs and .log files.
+am__create_global_log = $(AWK) ' \
+function fatal(msg) \
+{ \
+ print "fatal: making $@: " msg | "cat >&2"; \
+ exit 1; \
+} \
+function rst_section(header) \
+{ \
+ print header; \
+ len = length(header); \
+ for (i = 1; i <= len; i = i + 1) \
+ printf "="; \
+ printf "\n\n"; \
+} \
+{ \
+ copy_in_global_log = 1; \
+ global_test_result = "RUN"; \
+ while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+ { \
+ if (rc < 0) \
+ fatal("failed to read from " $$0 ".trs"); \
+ if (line ~ /$(am__global_test_result_rx)/) \
+ { \
+ sub("$(am__global_test_result_rx)", "", line); \
+ sub("[ ]*$$", "", line); \
+ global_test_result = line; \
+ } \
+ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \
+ copy_in_global_log = 0; \
+ }; \
+ if (copy_in_global_log) \
+ { \
+ rst_section(global_test_result ": " $$0); \
+ while ((rc = (getline line < ($$0 ".log"))) != 0) \
+ { \
+ if (rc < 0) \
+ fatal("failed to read from " $$0 ".log"); \
+ print line; \
+ }; \
+ printf "\n"; \
+ }; \
+ close ($$0 ".trs"); \
+ close ($$0 ".log"); \
+}'
+# Restructured Text title.
+am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; }
+# Solaris 10 'make', and several other traditional 'make' implementations,
+# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it
+# by disabling -e (using the XSI extension "set +e") if it's set.
+am__sh_e_setup = case $$- in *e*) set +e;; esac
+# Default flags passed to test drivers.
+am__common_driver_flags = \
+ --color-tests "$$am__color_tests" \
+ --enable-hard-errors "$$am__enable_hard_errors" \
+ --expect-failure "$$am__expect_failure"
+# To be inserted before the command running the test. Creates the
+# directory for the log if needed. Stores in $dir the directory
+# containing $f, in $tst the test, in $log the log. Executes the
+# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and
+# passes TESTS_ENVIRONMENT. Set up options for the wrapper that
+# will run the test scripts (or their associated LOG_COMPILER, if
+# thy have one).
+am__check_pre = \
+$(am__sh_e_setup); \
+$(am__vpath_adj_setup) $(am__vpath_adj) \
+$(am__tty_colors); \
+srcdir=$(srcdir); export srcdir; \
+case "$@" in \
+ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \
+ *) am__odir=.;; \
+esac; \
+test "x$$am__odir" = x"." || test -d "$$am__odir" \
+ || $(MKDIR_P) "$$am__odir" || exit $$?; \
+if test -f "./$$f"; then dir=./; \
+elif test -f "$$f"; then dir=; \
+else dir="$(srcdir)/"; fi; \
+tst=$$dir$$f; log='$@'; \
+if test -n '$(DISABLE_HARD_ERRORS)'; then \
+ am__enable_hard_errors=no; \
+else \
+ am__enable_hard_errors=yes; \
+fi; \
+case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \
+ am__expect_failure=yes;; \
+ *) \
+ am__expect_failure=no;; \
+esac; \
+$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT)
+# A shell command to get the names of the tests scripts with any registered
+# extension removed (i.e., equivalently, the names of the test logs, with
+# the '.log' extension removed). The result is saved in the shell variable
+# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly,
+# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)",
+# since that might cause problem with VPATH rewrites for suffix-less tests.
+# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'.
+am__set_TESTS_bases = \
+ bases='$(TEST_LOGS)'; \
+ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \
+ bases=`echo $$bases`
+RECHECK_LOGS = $(TEST_LOGS)
+AM_RECURSIVE_TARGETS = check recheck
+TEST_SUITE_LOG = test-suite.log
+TEST_EXTENSIONS = @EXEEXT@ .test
+LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS)
+am__set_b = \
+ case '$@' in \
+ */*) \
+ case '$*' in \
+ */*) b='$*';; \
+ *) b=`echo '$@' | sed 's/\.log$$//'`; \
+ esac;; \
+ *) \
+ b='$*';; \
+ esac
+am__test_logs1 = $(TESTS:=.log)
+am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log)
+TEST_LOGS = $(am__test_logs2:.test.log=.log)
+TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver
+TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \
+ $(TEST_LOG_FLAGS)
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/common.mk \
+ $(top_srcdir)/depcomp $(top_srcdir)/test-driver
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+pkgincludedir = $(includedir)/nice
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCACHE_DISABLE = @CCACHE_DISABLE@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GST010_CFLAGS = @GST010_CFLAGS@
+GST010_LIBS = @GST010_LIBS@
+GST_CFLAGS = @GST_CFLAGS@
+GST_CHECK_CFLAGS = @GST_CHECK_CFLAGS@
+GST_CHECK_LIBS = @GST_CHECK_LIBS@
+GST_LIBS = @GST_LIBS@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@
+GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@
+GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@
+GTKDOC_MKPDF = @GTKDOC_MKPDF@
+GTKDOC_REBASE = @GTKDOC_REBASE@
+GUPNP_CFLAGS = @GUPNP_CFLAGS@
+GUPNP_LIBS = @GUPNP_LIBS@
+GUPNP_PACKAGES = @GUPNP_PACKAGES@
+GUPNP_PACKAGES_PRIVATE = @GUPNP_PACKAGES_PRIVATE@
+GUPNP_PACKAGES_PUBLIC = @GUPNP_PACKAGES_PUBLIC@
+HAVE_GUPNP = @HAVE_GUPNP@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@
+INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@
+INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@
+INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@
+INTROSPECTION_LIBS = @INTROSPECTION_LIBS@
+INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@
+INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
+INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBNICE_CFLAGS = @LIBNICE_CFLAGS@
+LIBNICE_LT_LDFLAGS = @LIBNICE_LT_LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBRT = @LIBRT@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NICE_PACKAGES_PRIVATE = @NICE_PACKAGES_PRIVATE@
+NICE_PACKAGES_PUBLIC = @NICE_PACKAGES_PUBLIC@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_INCLUDES = @OPENSSL_INCLUDES@
+OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+UPNP_ENABLED = @UPNP_ENABLED@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gstplugin010dir = @gstplugin010dir@
+gstplugindir = @gstplugindir@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+CLEANFILES = *.gcno *.gcda
+LOG_DRIVER = $(top_srcdir)/scripts/valgrind-test-driver
+AM_CFLAGS = $(LIBNICE_CFLAGS) $(GLIB_CFLAGS)
+noinst_LTLIBRARIES = libnice-random.la
+libnice_random_la_SOURCES = \
+ random.h \
+ random.c \
+ random-glib.h \
+ random-glib.c
+
+test_LDADD = libnice-random.la $(GLIB_LIBS)
+TESTS = $(check_PROGRAMS)
+EXTRA_DIST = meson.build
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/common.mk $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu random/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu random/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+$(top_srcdir)/common.mk $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-checkPROGRAMS:
+ @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+libnice-random.la: $(libnice_random_la_OBJECTS) $(libnice_random_la_DEPENDENCIES) $(EXTRA_libnice_random_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(LINK) $(libnice_random_la_OBJECTS) $(libnice_random_la_LIBADD) $(LIBS)
+
+test$(EXEEXT): $(test_OBJECTS) $(test_DEPENDENCIES) $(EXTRA_test_DEPENDENCIES)
+ @rm -f test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_OBJECTS) $(test_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/random-glib.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/random.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test.Po@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+# Recover from deleted '.trs' file; this should ensure that
+# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create
+# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells
+# to avoid problems with "make -n".
+.log.trs:
+ rm -f $< $@
+ $(MAKE) $(AM_MAKEFLAGS) $<
+
+# Leading 'am--fnord' is there to ensure the list of targets does not
+# expand to empty, as could happen e.g. with make check TESTS=''.
+am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck)
+am--force-recheck:
+ @:
+
+$(TEST_SUITE_LOG): $(TEST_LOGS)
+ @$(am__set_TESTS_bases); \
+ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \
+ redo_bases=`for i in $$bases; do \
+ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \
+ done`; \
+ if test -n "$$redo_bases"; then \
+ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \
+ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \
+ if $(am__make_dryrun); then :; else \
+ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \
+ fi; \
+ fi; \
+ if test -n "$$am__remaking_logs"; then \
+ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \
+ "recursion detected" >&2; \
+ elif test -n "$$redo_logs"; then \
+ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \
+ fi; \
+ if $(am__make_dryrun); then :; else \
+ st=0; \
+ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \
+ for i in $$redo_bases; do \
+ test -f $$i.trs && test -r $$i.trs \
+ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \
+ test -f $$i.log && test -r $$i.log \
+ || { echo "$$errmsg $$i.log" >&2; st=1; }; \
+ done; \
+ test $$st -eq 0 || exit 1; \
+ fi
+ @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \
+ ws='[ ]'; \
+ results=`for b in $$bases; do echo $$b.trs; done`; \
+ test -n "$$results" || results=/dev/null; \
+ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \
+ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \
+ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \
+ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \
+ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \
+ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \
+ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \
+ if test `expr $$fail + $$xpass + $$error` -eq 0; then \
+ success=true; \
+ else \
+ success=false; \
+ fi; \
+ br='==================='; br=$$br$$br$$br$$br; \
+ result_count () \
+ { \
+ if test x"$$1" = x"--maybe-color"; then \
+ maybe_colorize=yes; \
+ elif test x"$$1" = x"--no-color"; then \
+ maybe_colorize=no; \
+ else \
+ echo "$@: invalid 'result_count' usage" >&2; exit 4; \
+ fi; \
+ shift; \
+ desc=$$1 count=$$2; \
+ if test $$maybe_colorize = yes && test $$count -gt 0; then \
+ color_start=$$3 color_end=$$std; \
+ else \
+ color_start= color_end=; \
+ fi; \
+ echo "$${color_start}# $$desc $$count$${color_end}"; \
+ }; \
+ create_testsuite_report () \
+ { \
+ result_count $$1 "TOTAL:" $$all "$$brg"; \
+ result_count $$1 "PASS: " $$pass "$$grn"; \
+ result_count $$1 "SKIP: " $$skip "$$blu"; \
+ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \
+ result_count $$1 "FAIL: " $$fail "$$red"; \
+ result_count $$1 "XPASS:" $$xpass "$$red"; \
+ result_count $$1 "ERROR:" $$error "$$mgn"; \
+ }; \
+ { \
+ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \
+ $(am__rst_title); \
+ create_testsuite_report --no-color; \
+ echo; \
+ echo ".. contents:: :depth: 2"; \
+ echo; \
+ for b in $$bases; do echo $$b; done \
+ | $(am__create_global_log); \
+ } >$(TEST_SUITE_LOG).tmp || exit 1; \
+ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \
+ if $$success; then \
+ col="$$grn"; \
+ else \
+ col="$$red"; \
+ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \
+ fi; \
+ echo "$${col}$$br$${std}"; \
+ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \
+ echo "$${col}$$br$${std}"; \
+ create_testsuite_report --maybe-color; \
+ echo "$$col$$br$$std"; \
+ if $$success; then :; else \
+ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \
+ if test -n "$(PACKAGE_BUGREPORT)"; then \
+ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \
+ fi; \
+ echo "$$col$$br$$std"; \
+ fi; \
+ $$success || exit 1
+
+check-TESTS: $(check_PROGRAMS)
+ @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list
+ @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list
+ @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+ @set +e; $(am__set_TESTS_bases); \
+ log_list=`for i in $$bases; do echo $$i.log; done`; \
+ trs_list=`for i in $$bases; do echo $$i.trs; done`; \
+ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \
+ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \
+ exit $$?;
+recheck: all $(check_PROGRAMS)
+ @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+ @set +e; $(am__set_TESTS_bases); \
+ bases=`for i in $$bases; do echo $$i; done \
+ | $(am__list_recheck_tests)` || exit 1; \
+ log_list=`for i in $$bases; do echo $$i.log; done`; \
+ log_list=`echo $$log_list`; \
+ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \
+ am__force_recheck=am--force-recheck \
+ TEST_LOGS="$$log_list"; \
+ exit $$?
+test.log: test$(EXEEXT)
+ @p='test$(EXEEXT)'; \
+ b='test'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+.test.log:
+ @p='$<'; \
+ $(am__set_b); \
+ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+@am__EXEEXT_TRUE@.test$(EXEEXT).log:
+@am__EXEEXT_TRUE@ @p='$<'; \
+@am__EXEEXT_TRUE@ $(am__set_b); \
+@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \
+@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT)
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+ -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS)
+ -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs)
+ -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-checkPROGRAMS clean-generic clean-libtool \
+ clean-noinstLTLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/random-glib.Plo
+ -rm -f ./$(DEPDIR)/random.Plo
+ -rm -f ./$(DEPDIR)/test.Po
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f ./$(DEPDIR)/random-glib.Plo
+ -rm -f ./$(DEPDIR)/random.Plo
+ -rm -f ./$(DEPDIR)/test.Po
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: check-am install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \
+ check-am clean clean-checkPROGRAMS clean-generic clean-libtool \
+ clean-noinstLTLIBRARIES cscopelist-am ctags ctags-am distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am recheck tags tags-am uninstall \
+ uninstall-am
+
+.PRECIOUS: Makefile
+
+
+check-valgrind:
+ $(MAKE) TESTS_ENVIRONMENT="USE_VALGRIND=1 " check
+
+.PHONY: check-valgrind
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null
+librandom = static_library('nice-random',
+ 'random.c', 'random-glib.c',
+ c_args: ['-DG_LOG_DOMAIN="libnice-random"'],
+ include_directories: nice_incs,
+ dependencies: gio_deps + [gthread_dep],
+ install: false)
+
+if not get_option('tests').disabled()
+ test_exe = executable('nice-random-test', 'test.c',
+ include_directories: nice_incs,
+ dependencies: gio_deps + [gthread_dep],
+ link_with: librandom)
+
+ test('nice-random', test_exe)
+endif
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2006-2008 Collabora Ltd.
+ * Contact: Dafydd Harries
+ * (C) 2006-2008 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Dafydd Harries, Collabora Ltd.
+ * Youness Alaoui, Collabora Ltd.
+ * Kai Vehmanen, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "random-glib.h"
+
+static void
+rng_seed (
+ G_GNUC_UNUSED
+ NiceRNG *rng, guint32 seed)
+{
+ (void)rng;
+ g_random_set_seed (seed);
+}
+
+static void
+rng_generate_bytes (
+ G_GNUC_UNUSED
+ NiceRNG *rng,
+ guint len,
+ gchar *buf)
+{
+ guint i;
+
+ (void)rng;
+
+ for (i = 0; i < len; i++)
+ buf[i] = g_random_int_range (0, 256);
+}
+
+static guint
+rng_generate_int (
+ G_GNUC_UNUSED
+ NiceRNG *rng,
+ guint low,
+ guint high)
+{
+ (void)rng;
+ return g_random_int_range (low, high);
+}
+
+static void
+rng_free (NiceRNG *rng)
+{
+ g_slice_free (NiceRNG, rng);
+}
+
+NiceRNG *
+nice_rng_glib_new (void)
+{
+ NiceRNG *ret;
+
+ ret = g_slice_new0 (NiceRNG);
+ ret->seed = rng_seed;
+ ret->generate_bytes = rng_generate_bytes;
+ ret->generate_int = rng_generate_int;
+ ret->free = rng_free;
+ return ret;
+}
+
+NiceRNG *
+nice_rng_glib_new_predictable (void)
+{
+ NiceRNG *rng;
+
+ rng = nice_rng_glib_new ();
+ rng->seed (rng, 0);
+ return rng;
+}
+
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2006-2007 Collabora Ltd.
+ * Contact: Dafydd Harries
+ * (C) 2006-2007 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Dafydd Harries, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef _RANDOM_GLIB_H
+#define _RANDOM_GLIB_H
+
+#include <glib.h>
+
+#include "random.h"
+
+G_BEGIN_DECLS
+
+NiceRNG *
+nice_rng_glib_new (void);
+
+NiceRNG *
+nice_rng_glib_new_predictable (void);
+
+G_END_DECLS
+
+#endif /* _RANDOM_GLIB_H */
+
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2006-2008 Collabora Ltd.
+ * Contact: Dafydd Harries
+ * (C) 2006-2008 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Dafydd Harries, Collabora Ltd.
+ * Youness Alaoui, Collabora Ltd.
+ * Kai Vehmanen, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+
+#include "random.h"
+#include "random-glib.h"
+
+static NiceRNG * (*nice_rng_new_func) (void) = NULL;
+
+/*
+ * Creates a new random number generator instance.
+ */
+NiceRNG *
+nice_rng_new (void)
+{
+ if (nice_rng_new_func == NULL)
+ return nice_rng_glib_new ();
+ else
+ return nice_rng_new_func ();
+}
+
+/*
+ * Sets a new generator function.
+ */
+void
+nice_rng_set_new_func (NiceRNG * (*func) (void))
+{
+ nice_rng_new_func = func;
+}
+
+/*
+ * Frees the random number generator instance.
+ *
+ * @param rng context
+ */
+void
+nice_rng_free (NiceRNG *rng)
+{
+ rng->free (rng);
+}
+
+/*
+ * Generates random octets.
+ *
+ * @param rng context
+ * @param len number of octets to product
+ * @param buf buffer to store the results
+ */
+void
+nice_rng_generate_bytes (NiceRNG *rng, guint len, gchar *buf)
+{
+ rng->generate_bytes (rng, len, buf);
+}
+
+/*
+ * Generates a random unsigned integer.
+ *
+ * @param rng context
+ * @param low closed lower bound
+ * @param high open upper bound
+ */
+guint
+nice_rng_generate_int (NiceRNG *rng, guint low, guint high)
+{
+ return rng->generate_int (rng, low, high);
+}
+
+/*
+ * Generates a stream of octets containing only characters
+ * with ASCII codecs of 0x41-5A (A-Z), 0x61-7A (a-z),
+ * 0x30-39 (0-9), 0x2b (+) and 0x2f (/). This matches
+ * the definition of 'ice-char' in ICE Ispecification,
+ * section 15.1 (ID-16).
+ *
+ * @param rng context
+ * @param len number of octets to product
+ * @param buf buffer to store the results
+ */
+void
+nice_rng_generate_bytes_print (NiceRNG *rng, guint len, gchar *buf)
+{
+ guint i;
+ const gchar *chars =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789"
+ "+/";
+
+ for (i = 0; i < len; i++)
+ buf[i] = chars[nice_rng_generate_int (rng, 0, strlen (chars))];
+}
+
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2006-2007 Collabora Ltd.
+ * Contact: Dafydd Harries
+ * (C) 2006-2007 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Dafydd Harries, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef _RANDOM_H
+#define _RANDOM_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct _NiceRNG NiceRNG;
+
+struct _NiceRNG {
+ void (*seed) (NiceRNG *src, guint32 seed);
+ void (*generate_bytes) (NiceRNG *src, guint len, gchar *buf);
+ guint (*generate_int) (NiceRNG *src, guint low, guint high);
+ void (*free) (NiceRNG *src);
+ gpointer priv;
+};
+
+NiceRNG *
+nice_rng_new (void);
+
+void
+nice_rng_set_new_func (NiceRNG * (*func) (void));
+
+void
+nice_rng_seed (NiceRNG *rng, guint32 seed);
+
+void
+nice_rng_generate_bytes (NiceRNG *rng, guint len, gchar *buf);
+
+void
+nice_rng_generate_bytes_print (NiceRNG *rng, guint len, gchar *buf);
+
+guint
+nice_rng_generate_int (NiceRNG *rng, guint low, guint high);
+
+void
+nice_rng_free (NiceRNG *rng);
+
+G_END_DECLS
+
+#endif // _RANDOM_H
+
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2006-2007 Collabora Ltd.
+ * Contact: Dafydd Harries
+ * (C) 2006-2007 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Dafydd Harries, Collabora Ltd.
+ * Kai Vehmanen, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+
+#include "random-glib.h"
+
+#define TEST_RNGSIZE 256
+
+int
+main (void)
+{
+ NiceRNG *rng;
+ gchar buf[TEST_RNGSIZE];
+
+ buf[TEST_RNGSIZE - 1] = '\0';
+
+ nice_rng_set_new_func (nice_rng_glib_new_predictable);
+ rng = nice_rng_new ();
+
+ nice_rng_generate_bytes_print (rng, TEST_RNGSIZE - 1, buf);
+ /* g_debug ("%s", buf); */
+ g_assert (0 == strcmp (buf, "sv1AD7DnJTVykXGYYM6BmnXuYRlZNIJUzQzF+PvASjYxzdTTOngBJ5/gfK0Xj+Ly3ciAAk1Fmo0RPEpq6f4BBnp5jm3LuSbAOj1M5qULEGEv/0DMk0oOPUj6XPN1VwxFpjAfFeAxykiwdDiqNwnVJ/AKyr6/X7C5i+je7DSujURybOp6BkKWroLCzQg2AmTuqz48oNeY9CDeirNwoITfIaC40Ds9OgEDtL8WN5tL4QYdVuZQ85219Thogk775GV"));
+
+ nice_rng_generate_bytes (rng, 4, buf);
+ buf[4] = 0;
+ g_assert (0 == strcmp (buf, "\x1f\x0d\x47\xb8"));
+
+ nice_rng_free (rng);
+ return 0;
+}
+
--- /dev/null
+#!/bin/sh
+
+usage()
+{
+ echo "usage: $0 library symbol-file"
+ exit 1
+}
+
+test -n "$1" || usage
+lib="$1"
+test -n "$2" || usage
+symbol_file="$2"
+
+make_symbol_list=`dirname $0`/make-symbol-list.sh
+test -f "$make_symbol_list" || exit 1
+
+if ! test -f "$symbol_file"; then
+ echo "$symbol_file doesn't exist"
+ exit 1
+fi
+
+diff=`sh $make_symbol_list "$lib" | \
+ diff -uB "$symbol_file" - | tail -n +3`
+
+# stop if there are no differences
+test -z "$diff" && exit 0
+
+echo "symbols for $lib changed"
+
+if echo "$diff" | grep -q '^-'; then
+ echo " missing:"
+ echo "$diff" | grep '^-' | cut -b 2- | \
+ xargs -i echo " " "{}"
+fi
+
+if echo "$diff" | grep -q '^+'; then
+ echo " extra:"
+ echo "$diff" | grep '^+' | cut -b 2- | \
+ xargs -i echo " " "{}"
+fi
+
+exit 1
+
--- /dev/null
+
+# ccache breaks -fprofile-arcs
+export CCACHE_DISABLE=1
+
+OUT=lcov
+
+lcov-clean:
+ $(MAKE) clean
+ find -name "*.gcno" -o -name "*.gcda" -exec rm '{}' ';'
+ rm -rf $(OUT)
+
+lcov-build:
+ $(MAKE) CFLAGS="-O0 -fprofile-arcs -ftest-coverage" LDFLAGS="-lgcov" check
+
+lcov-report:
+ # hack: move gcov file from libraries back to source directory
+ for dir in `find -name .libs`; do \
+ (cd `dirname $$dir`; mv .libs/*.gc?? . || true) 2>/dev/null; \
+ done
+
+ mkdir -p $(OUT)
+ lcov -d . -c >$(OUT)/lcov.info 2>/dev/null
+ lcov -l $(OUT)/lcov.info 2>/dev/null |\
+ egrep '(^/usr|/test.*\.c)' |\
+ cut -d: -f1 >$(OUT)/lcov.remove
+ lcov -r $(OUT)/lcov.info `cat $(OUT)/lcov.remove` 2>/dev/null >$(OUT)/lcov.info.clean
+ genhtml -o lcov $(OUT)/lcov.info.clean
+
--- /dev/null
+#!/bin/sh
+make -f scripts/lcov.mk lcov-clean && \
+make -f scripts/lcov.mk lcov-build && \
+make -f scripts/lcov.mk lcov-report
--- /dev/null
+#!/bin/sh
+test -n "$1" || exit 1
+nm --print-file-name --defined-only --extern-only "$1" | \
+ cut -d ' ' -f 2,3 | \
+ grep -v '^[rA]' | \
+ sort
--- /dev/null
+#! /bin/sh
+# test-driver - basic testsuite driver script.
+
+scriptversion=2017-04-04.22; # UTC
+
+# Copyright (C) 2011-2014 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+# Make unconditional expansion of undefined variables an error. This
+# helps a lot in preventing typo-related bugs.
+set -u
+
+usage_error ()
+{
+ echo "$0: $*" >&2
+ print_usage >&2
+ exit 2
+}
+
+print_usage ()
+{
+ cat <<END
+Usage:
+ test-driver --test-name=NAME --log-file=PATH --trs-file=PATH
+ [--expect-failure={yes|no}] [--color-tests={yes|no}]
+ [--enable-hard-errors={yes|no}] [--]
+ TEST-SCRIPT [TEST-SCRIPT-ARGUMENTS]
+The '--test-name', '--log-file' and '--trs-file' options are mandatory.
+END
+}
+
+test_name= # Used for reporting.
+log_file= # Where to save the output of the test script.
+trs_file= # Where to save the metadata of the test run.
+expect_failure=no
+color_tests=no
+enable_hard_errors=yes
+while test $# -gt 0; do
+ case $1 in
+ --help) print_usage; exit $?;;
+ --version) echo "test-driver $scriptversion"; exit $?;;
+ --test-name) test_name=$2; shift;;
+ --log-file) log_file=$2; shift;;
+ --trs-file) trs_file=$2; shift;;
+ --color-tests) color_tests=$2; shift;;
+ --expect-failure) expect_failure=$2; shift;;
+ --enable-hard-errors) enable_hard_errors=$2; shift;;
+ --) shift; break;;
+ -*) usage_error "invalid option: '$1'";;
+ *) break;;
+ esac
+ shift
+done
+
+missing_opts=
+test x"$test_name" = x && missing_opts="$missing_opts --test-name"
+test x"$log_file" = x && missing_opts="$missing_opts --log-file"
+test x"$trs_file" = x && missing_opts="$missing_opts --trs-file"
+if test x"$missing_opts" != x; then
+ usage_error "the following mandatory options are missing:$missing_opts"
+fi
+
+if test $# -eq 0; then
+ usage_error "missing argument"
+fi
+
+if test $color_tests = yes; then
+ # Keep this in sync with 'lib/am/check.am:$(am__tty_colors)'.
+ red='\e[0;31m' # Red.
+ grn='\e[0;32m' # Green.
+ lgn='\e[1;32m' # Light green.
+ blu='\e[1;34m' # Blue.
+ mgn='\e[0;35m' # Magenta.
+ std='\e[m' # No color.
+else
+ red= grn= lgn= blu= mgn= std=
+fi
+
+do_exit='rm -f $log_file $trs_file; (exit $st); exit $st'
+trap "st=129; $do_exit" 1
+trap "st=130; $do_exit" 2
+trap "st=141; $do_exit" 13
+trap "st=143; $do_exit" 15
+
+# Test script is run here.
+top_srcdir="`dirname $0`/.."
+tests_dir="${top_srcdir}/tests"
+
+USE_VALGRIND="`printenv USE_VALGRIND`"
+
+if test "x${USE_VALGRIND}" = "x1"; then
+ ${top_srcdir}/libtool --mode=execute valgrind \
+ --leak-check=full \
+ --show-reachable=no \
+ --error-exitcode=1 \
+ --suppressions=$tests_dir/libnice.supp \
+ --num-callers=30 "$@" >$log_file 2>&1
+else
+ "$@" >$log_file 2>&1
+fi
+estatus=$?
+
+if test $enable_hard_errors = no && test $estatus -eq 99; then
+ tweaked_estatus=1
+else
+ tweaked_estatus=$estatus
+fi
+
+case $tweaked_estatus:$expect_failure in
+ 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;;
+ 0:*) col=$grn res=PASS recheck=no gcopy=no;;
+ 77:*) col=$blu res=SKIP recheck=no gcopy=yes;;
+ 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;;
+ *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;;
+ *:*) col=$red res=FAIL recheck=yes gcopy=yes;;
+esac
+
+# Report the test outcome and exit status in the logs, so that one can
+# know whether the test passed or failed simply by looking at the '.log'
+# file, without the need of also peaking into the corresponding '.trs'
+# file (automake bug#11814).
+echo "$res $test_name (exit status: $estatus)" >>$log_file
+
+# Report outcome to console.
+echo "${col}${res}${std}: $test_name"
+
+# Register the test result, and other relevant metadata.
+echo ":test-result: $res" > $trs_file
+echo ":global-test-result: $res" >> $trs_file
+echo ":recheck: $recheck" >> $trs_file
+echo ":copy-in-global-log: $gcopy" >> $trs_file
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
--- /dev/null
+#
+# Makefile.am for the Nice Glib ICE library
+#
+# (C) 2006, 2007 Collabora Ltd.
+# (C) 2006, 2007 Nokia Corporation. All rights reserved.
+#
+# Licensed under MPL 1.1/LGPL 2.1. See file COPYING.
+
+include $(top_srcdir)/common.mk
+
+AM_CFLAGS = \
+ -DG_LOG_DOMAIN=\"libnice-socket\" \
+ $(LIBNICE_CFLAGS) \
+ $(GLIB_CFLAGS) \
+ $(GUPNP_CFLAGS) \
+ -I $(top_srcdir)/random \
+ -I $(top_srcdir)/agent \
+ -I $(top_srcdir)/
+
+noinst_LTLIBRARIES = libsocket.la
+
+libsocket_la_SOURCES = \
+ socket.h \
+ socket-priv.h \
+ socket.c \
+ udp-bsd.h \
+ udp-bsd.c \
+ tcp-bsd.h \
+ tcp-bsd.c \
+ tcp-active.h \
+ tcp-active.c \
+ tcp-passive.h \
+ tcp-passive.c \
+ pseudossl.h \
+ pseudossl.c \
+ socks5.h \
+ socks5.c \
+ http.h \
+ http.c \
+ udp-turn.h \
+ udp-turn.c \
+ udp-turn-over-tcp.h \
+ udp-turn-over-tcp.c
+
+EXTRA_DIST = meson.build
--- /dev/null
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+#
+# Makefile.am for the Nice Glib ICE library
+#
+# (C) 2006, 2007 Collabora Ltd.
+# (C) 2006, 2007 Nokia Corporation. All rights reserved.
+#
+# Licensed under MPL 1.1/LGPL 2.1. See file COPYING.
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = socket
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/as-compiler-flag.m4 \
+ $(top_srcdir)/m4/ax_check_openssl.m4 \
+ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/introspection.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libsocket_la_LIBADD =
+am_libsocket_la_OBJECTS = socket.lo udp-bsd.lo tcp-bsd.lo \
+ tcp-active.lo tcp-passive.lo pseudossl.lo socks5.lo http.lo \
+ udp-turn.lo udp-turn-over-tcp.lo
+libsocket_la_OBJECTS = $(am_libsocket_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/http.Plo ./$(DEPDIR)/pseudossl.Plo \
+ ./$(DEPDIR)/socket.Plo ./$(DEPDIR)/socks5.Plo \
+ ./$(DEPDIR)/tcp-active.Plo ./$(DEPDIR)/tcp-bsd.Plo \
+ ./$(DEPDIR)/tcp-passive.Plo ./$(DEPDIR)/udp-bsd.Plo \
+ ./$(DEPDIR)/udp-turn-over-tcp.Plo ./$(DEPDIR)/udp-turn.Plo
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(libsocket_la_SOURCES)
+DIST_SOURCES = $(libsocket_la_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/common.mk \
+ $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+pkgincludedir = $(includedir)/nice
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCACHE_DISABLE = @CCACHE_DISABLE@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GST010_CFLAGS = @GST010_CFLAGS@
+GST010_LIBS = @GST010_LIBS@
+GST_CFLAGS = @GST_CFLAGS@
+GST_CHECK_CFLAGS = @GST_CHECK_CFLAGS@
+GST_CHECK_LIBS = @GST_CHECK_LIBS@
+GST_LIBS = @GST_LIBS@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@
+GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@
+GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@
+GTKDOC_MKPDF = @GTKDOC_MKPDF@
+GTKDOC_REBASE = @GTKDOC_REBASE@
+GUPNP_CFLAGS = @GUPNP_CFLAGS@
+GUPNP_LIBS = @GUPNP_LIBS@
+GUPNP_PACKAGES = @GUPNP_PACKAGES@
+GUPNP_PACKAGES_PRIVATE = @GUPNP_PACKAGES_PRIVATE@
+GUPNP_PACKAGES_PUBLIC = @GUPNP_PACKAGES_PUBLIC@
+HAVE_GUPNP = @HAVE_GUPNP@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@
+INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@
+INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@
+INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@
+INTROSPECTION_LIBS = @INTROSPECTION_LIBS@
+INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@
+INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
+INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBNICE_CFLAGS = @LIBNICE_CFLAGS@
+LIBNICE_LT_LDFLAGS = @LIBNICE_LT_LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBRT = @LIBRT@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NICE_PACKAGES_PRIVATE = @NICE_PACKAGES_PRIVATE@
+NICE_PACKAGES_PUBLIC = @NICE_PACKAGES_PUBLIC@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_INCLUDES = @OPENSSL_INCLUDES@
+OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+UPNP_ENABLED = @UPNP_ENABLED@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gstplugin010dir = @gstplugin010dir@
+gstplugindir = @gstplugindir@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+CLEANFILES = *.gcno *.gcda
+LOG_DRIVER = $(top_srcdir)/scripts/valgrind-test-driver
+AM_CFLAGS = \
+ -DG_LOG_DOMAIN=\"libnice-socket\" \
+ $(LIBNICE_CFLAGS) \
+ $(GLIB_CFLAGS) \
+ $(GUPNP_CFLAGS) \
+ -I $(top_srcdir)/random \
+ -I $(top_srcdir)/agent \
+ -I $(top_srcdir)/
+
+noinst_LTLIBRARIES = libsocket.la
+libsocket_la_SOURCES = \
+ socket.h \
+ socket-priv.h \
+ socket.c \
+ udp-bsd.h \
+ udp-bsd.c \
+ tcp-bsd.h \
+ tcp-bsd.c \
+ tcp-active.h \
+ tcp-active.c \
+ tcp-passive.h \
+ tcp-passive.c \
+ pseudossl.h \
+ pseudossl.c \
+ socks5.h \
+ socks5.c \
+ http.h \
+ http.c \
+ udp-turn.h \
+ udp-turn.c \
+ udp-turn-over-tcp.h \
+ udp-turn-over-tcp.c
+
+EXTRA_DIST = meson.build
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/common.mk $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu socket/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu socket/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+$(top_srcdir)/common.mk $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+libsocket.la: $(libsocket_la_OBJECTS) $(libsocket_la_DEPENDENCIES) $(EXTRA_libsocket_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(LINK) $(libsocket_la_OBJECTS) $(libsocket_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/http.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pseudossl.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socks5.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcp-active.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcp-bsd.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcp-passive.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/udp-bsd.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/udp-turn-over-tcp.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/udp-turn.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/http.Plo
+ -rm -f ./$(DEPDIR)/pseudossl.Plo
+ -rm -f ./$(DEPDIR)/socket.Plo
+ -rm -f ./$(DEPDIR)/socks5.Plo
+ -rm -f ./$(DEPDIR)/tcp-active.Plo
+ -rm -f ./$(DEPDIR)/tcp-bsd.Plo
+ -rm -f ./$(DEPDIR)/tcp-passive.Plo
+ -rm -f ./$(DEPDIR)/udp-bsd.Plo
+ -rm -f ./$(DEPDIR)/udp-turn-over-tcp.Plo
+ -rm -f ./$(DEPDIR)/udp-turn.Plo
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f ./$(DEPDIR)/http.Plo
+ -rm -f ./$(DEPDIR)/pseudossl.Plo
+ -rm -f ./$(DEPDIR)/socket.Plo
+ -rm -f ./$(DEPDIR)/socks5.Plo
+ -rm -f ./$(DEPDIR)/tcp-active.Plo
+ -rm -f ./$(DEPDIR)/tcp-bsd.Plo
+ -rm -f ./$(DEPDIR)/tcp-passive.Plo
+ -rm -f ./$(DEPDIR)/udp-bsd.Plo
+ -rm -f ./$(DEPDIR)/udp-turn-over-tcp.Plo
+ -rm -f ./$(DEPDIR)/udp-turn.Plo
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ cscopelist-am ctags ctags-am distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags tags-am uninstall uninstall-am
+
+.PRECIOUS: Makefile
+
+
+check-valgrind:
+ $(MAKE) TESTS_ENVIRONMENT="USE_VALGRIND=1 " check
+
+.PHONY: check-valgrind
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2008 Nokia Corporation. All rights reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+/*
+ * Implementation of TCP relay socket interface using TCP Berkeley sockets. (See
+ * http://en.wikipedia.org/wiki/Berkeley_sockets.)
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "http.h"
+#include "agent-priv.h"
+#include "socket-priv.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+
+#ifndef G_OS_WIN32
+#include <unistd.h>
+#endif
+
+
+#define HTTP_USER_AGENT "libnice"
+
+typedef enum {
+ HTTP_STATE_INIT,
+ HTTP_STATE_HEADERS,
+ HTTP_STATE_BODY,
+ HTTP_STATE_CONNECTED,
+ HTTP_STATE_ERROR
+} HttpState;
+
+typedef struct {
+ HttpState state;
+ NiceSocket *base_socket;
+ NiceAddress addr;
+ gchar *username;
+ gchar *password;
+ GQueue send_queue;
+
+ /* Ring buffer for receiving HTTP headers into before they’re parsed. */
+ guint8 *recv_buf;
+ gsize recv_buf_length; /* allocation size of @recv_buf */
+ gsize recv_buf_pos; /* offset from @recv_buf of the 0th byte in the buffer */
+ gsize recv_buf_fill; /* number of bytes occupied in the buffer */
+
+ /* Parsed from the Content-Length header provided by the other endpoint. */
+ gsize content_length;
+} HttpPriv;
+
+
+static void socket_close (NiceSocket *sock);
+static gint socket_recv_messages (NiceSocket *sock,
+ NiceInputMessage *recv_messages, guint n_recv_messages);
+static gint socket_send_messages (NiceSocket *sock, const NiceAddress *to,
+ const NiceOutputMessage *messages, guint n_messages);
+static gint socket_send_messages_reliable (NiceSocket *sock,
+ const NiceAddress *to, const NiceOutputMessage *messages, guint n_messages);
+static gboolean socket_is_reliable (NiceSocket *sock);
+static gboolean socket_can_send (NiceSocket *sock, NiceAddress *addr);
+static void socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data);
+static gboolean socket_is_based_on (NiceSocket *sock, NiceSocket *other);
+
+NiceSocket *
+nice_http_socket_new (NiceSocket *base_socket,
+ NiceAddress *addr, gchar *username, gchar *password)
+{
+ HttpPriv *priv;
+ NiceSocket *sock = NULL;
+
+ if (addr) {
+ sock = g_slice_new0 (NiceSocket);
+ sock->priv = priv = g_slice_new0 (HttpPriv);
+
+ priv->base_socket = base_socket;
+ priv->addr = *addr;
+ priv->username = g_strdup (username);
+ priv->password = g_strdup (password);
+ priv->recv_buf = NULL;
+ priv->recv_buf_length = 0;
+ priv->recv_buf_pos = 0;
+ priv->recv_buf_fill = 0;
+ priv->content_length = 0;
+
+ sock->type = NICE_SOCKET_TYPE_HTTP;
+ sock->fileno = priv->base_socket->fileno;
+ sock->addr = priv->base_socket->addr;
+ sock->send_messages = socket_send_messages;
+ sock->send_messages_reliable = socket_send_messages_reliable;
+ sock->recv_messages = socket_recv_messages;
+ sock->is_reliable = socket_is_reliable;
+ sock->can_send = socket_can_send;
+ sock->set_writable_callback = socket_set_writable_callback;
+ sock->is_based_on = socket_is_based_on;
+ sock->close = socket_close;
+
+ /* Send HTTP CONNECT */
+ {
+ gchar *msg = NULL;
+ gchar *credential = NULL;
+ gchar host[INET6_ADDRSTRLEN];
+ gint port = nice_address_get_port (&priv->addr);
+ GOutputVector local_bufs;
+ NiceOutputMessage local_messages;
+
+ nice_address_to_string (&priv->addr, host);
+
+ if (username) {
+ gchar * userpass = g_strdup_printf ("%s:%s", username,
+ password ? password : "");
+ gchar * auth = g_base64_encode ((guchar *)userpass, strlen (userpass));
+ credential = g_strdup_printf ("Proxy-Authorization: Basic %s\r\n", auth);
+ g_free (auth);
+ g_free (userpass);
+ }
+ msg = g_strdup_printf ("CONNECT %s:%d HTTP/1.0\r\n"
+ "Host: %s\r\n"
+ "User-Agent: %s\r\n"
+ "Content-Length: 0\r\n"
+ "Proxy-Connection: Keep-Alive\r\n"
+ "Connection: Keep-Alive\r\n"
+ "Cache-Control: no-cache\r\n"
+ "Pragma: no-cache\r\n"
+ "%s\r\n", host, port, host, HTTP_USER_AGENT,
+ credential? credential : "" );
+ g_free (credential);
+
+ local_bufs.buffer = msg;
+ local_bufs.size = strlen (msg);
+ local_messages.buffers = &local_bufs;
+ local_messages.n_buffers = 1;
+
+ nice_socket_send_messages_reliable (priv->base_socket, NULL,
+ &local_messages, 1);
+ priv->state = HTTP_STATE_INIT;
+ g_free (msg);
+ }
+ }
+
+ return sock;
+}
+
+
+static void
+socket_close (NiceSocket *sock)
+{
+ HttpPriv *priv = sock->priv;
+
+ if (priv->base_socket)
+ nice_socket_free (priv->base_socket);
+
+ if (priv->username)
+ g_free (priv->username);
+
+ if (priv->password)
+ g_free (priv->password);
+
+ if (priv->recv_buf)
+ g_free (priv->recv_buf);
+
+ nice_socket_free_send_queue (&priv->send_queue);
+
+ g_slice_free(HttpPriv, sock->priv);
+ sock->priv = NULL;
+}
+
+static void
+assert_ring_buffer_valid (HttpPriv *priv)
+{
+ g_assert (priv->recv_buf_fill <= priv->recv_buf_length);
+ g_assert (priv->recv_buf_pos == 0 ||
+ priv->recv_buf_pos < priv->recv_buf_length);
+ g_assert (priv->recv_buf_length == 0 || priv->recv_buf != NULL);
+}
+
+/* Pops up to @buffer_length bytes off the ring buffer and copies them into
+ * @buffer. Returns the number of bytes copied. */
+static gsize
+memcpy_ring_buffer_to_buffer (HttpPriv *priv,
+ guint8 *buffer, gsize buffer_length)
+{
+ gsize len, consumed = 0;
+ gboolean has_wrapped;
+
+ has_wrapped =
+ (priv->recv_buf_pos + priv->recv_buf_fill) > priv->recv_buf_length;
+
+ if (has_wrapped) {
+ len = MIN (priv->recv_buf_length - priv->recv_buf_pos, buffer_length);
+ memcpy (buffer, priv->recv_buf + priv->recv_buf_pos, len);
+ consumed += len;
+
+ buffer += len;
+ buffer_length -= len;
+
+ len = MIN (priv->recv_buf_fill - len, buffer_length);
+ memcpy (buffer, priv->recv_buf, len);
+ consumed += len;
+ } else {
+ len = MIN (priv->recv_buf_fill, buffer_length);
+ memcpy (buffer, priv->recv_buf + priv->recv_buf_pos, len);
+ consumed += len;
+ }
+
+ priv->recv_buf_pos =
+ (priv->recv_buf_pos + consumed) % priv->recv_buf_length;
+ priv->recv_buf_fill -= consumed;
+
+ return consumed;
+}
+
+/* Returns the number of messages touched. Silently drops any data from @buffer
+ * which doesn’t fit in @messages. Updates the ring buffer to pop the copied
+ * data off it. Treats all #GInputVectors in @messages the same; there is no
+ * differentiation between different #NiceInputMessages. */
+static gint
+memcpy_ring_buffer_to_input_messages (HttpPriv *priv,
+ NiceInputMessage *messages, guint n_messages)
+{
+ guint i, j;
+
+ for (i = 0; priv->recv_buf_fill > 0 && i < n_messages; i++) {
+ NiceInputMessage *message = &messages[i];
+
+ for (j = 0;
+ priv->recv_buf_fill > 0 &&
+ ((message->n_buffers >= 0 && j < (guint) message->n_buffers) ||
+ (message->n_buffers < 0 && message->buffers[j].buffer != NULL));
+ j++) {
+ message->buffers[j].size =
+ memcpy_ring_buffer_to_buffer (priv,
+ message->buffers[j].buffer, message->buffers[j].size);
+ }
+ }
+
+ return i;
+}
+
+/* FIXME: The current implementation of socket_recv_message() is a fast
+ * pass-through to nice_socket_recv_message() if the HTTP socket is connected,
+ * but is a slow state machine otherwise, using multiple memcpy()s. Spruce it up
+ * to better to use the recv_messages to avoid the memcpy()s. */
+static gint
+socket_recv_messages (NiceSocket *sock,
+ NiceInputMessage *recv_messages, guint n_recv_messages)
+{
+ HttpPriv *priv = sock->priv;
+ gint ret = -1;
+
+ /* Make sure socket has not been freed: */
+ g_assert (sock->priv != NULL);
+
+ if (priv->state == HTTP_STATE_CONNECTED) {
+ guint i;
+
+ /* Fast path: pass through to the base socket once we’re connected. */
+ if (priv->base_socket) {
+ ret = nice_socket_recv_messages (priv->base_socket,
+ recv_messages, n_recv_messages);
+ }
+
+ if (ret <= 0)
+ return ret;
+
+ /* After successfully receiving into at least one NiceInputMessage,
+ * update the from address in each valid NiceInputMessage. */
+ for (i = 0; i < (guint) ret; i++) {
+ if (recv_messages[i].from != NULL)
+ *recv_messages[i].from = priv->addr;
+ }
+
+ return ret;
+ } else {
+ /* Slow path: read into a local ring buffer until we’re parsed enough of the
+ * headers. Double the buffer in size every time it fills up. */
+ gboolean has_wrapped;
+ GInputVector local_recv_bufs[2];
+ NiceInputMessage local_recv_message = { local_recv_bufs, 2, NULL, 0 };
+
+ /* Has the buffer filled up? Start with an initial buffer of 1KB, which
+ * should cover the average size of HTTP response headers. Source:
+ * http://dev.chromium.org/spdy/spdy-whitepaper */
+ if (priv->recv_buf_fill == priv->recv_buf_length) {
+ priv->recv_buf_length = MAX (priv->recv_buf_length * 2, 1024);
+ priv->recv_buf = g_realloc (priv->recv_buf, priv->recv_buf_length);
+ }
+
+ assert_ring_buffer_valid (priv);
+
+ /* Read some data into the buffer. Use two GInputVectors: one for the tail
+ * of the buffer and one for the head. */
+ has_wrapped =
+ (priv->recv_buf_pos + priv->recv_buf_fill) > priv->recv_buf_length;
+
+ if (has_wrapped) {
+ local_recv_bufs[0].buffer =
+ priv->recv_buf + (priv->recv_buf_pos + priv->recv_buf_fill) %
+ priv->recv_buf_length;
+ local_recv_bufs[0].size = priv->recv_buf_length - priv->recv_buf_fill;
+ local_recv_bufs[1].buffer = NULL;
+ local_recv_bufs[1].size = 0;
+ } else {
+ local_recv_bufs[0].buffer =
+ priv->recv_buf + priv->recv_buf_pos + priv->recv_buf_fill;
+ local_recv_bufs[0].size =
+ priv->recv_buf_length - (priv->recv_buf_pos + priv->recv_buf_fill);
+ local_recv_bufs[1].buffer = priv->recv_buf;
+ local_recv_bufs[1].size = priv->recv_buf_pos;
+ }
+
+ if (priv->base_socket) {
+ ret = nice_socket_recv_messages (priv->base_socket,
+ &local_recv_message, 1);
+ }
+
+ if (ret <= 0)
+ return ret;
+
+ /* Update the buffer’s metadata. */
+ priv->recv_buf_fill += local_recv_message.length;
+ assert_ring_buffer_valid (priv);
+
+ /* Fall through and try parsing the newly received data. */
+ }
+
+#define GET_BYTE(pos) \
+ priv->recv_buf[(pos + priv->recv_buf_pos) % priv->recv_buf_length]
+#define EAT_WHITESPACE(pos) \
+ while (pos < priv->recv_buf_fill && GET_BYTE(pos) == ' ') \
+ pos++; \
+ if (pos >= priv->recv_buf_fill) \
+ goto not_enough_data;
+
+retry:
+ nice_debug ("Receiving from HTTP proxy (state %d) : %" G_GSSIZE_FORMAT " \n"
+ "'%s'", priv->state, priv->recv_buf_fill,
+ priv->recv_buf + priv->recv_buf_pos);
+
+ switch (priv->state) {
+ case HTTP_STATE_INIT:
+ {
+ /* This is a logical position in the recv_buf; add
+ * (priv->recv_buf + priv->recv_buf_pos) to get the actual byte in
+ * memory. */
+ guint pos = 0;
+
+ /* Eat leading whitespace and check we have enough data. */
+ EAT_WHITESPACE (pos);
+
+ if (pos + 7 > priv->recv_buf_fill)
+ goto not_enough_data;
+ if (GET_BYTE (pos + 0) != 'H' ||
+ GET_BYTE (pos + 1) != 'T' ||
+ GET_BYTE (pos + 2) != 'T' ||
+ GET_BYTE (pos + 3) != 'P' ||
+ GET_BYTE (pos + 4) != '/' ||
+ GET_BYTE (pos + 5) != '1' ||
+ GET_BYTE (pos + 6) != '.')
+ goto error;
+ pos += 7;
+
+ if (pos >= priv->recv_buf_fill)
+ goto not_enough_data;
+ if (GET_BYTE (pos) != '0' && GET_BYTE (pos) != '1')
+ goto error;
+ pos++;
+
+ /* Make sure we have a space after the HTTP version */
+ if (pos >= priv->recv_buf_fill)
+ goto not_enough_data;
+ if (GET_BYTE (pos) != ' ')
+ goto error;
+
+ EAT_WHITESPACE (pos);
+
+ /* Check for a successful 2xx code */
+ if (pos + 3 > priv->recv_buf_fill)
+ goto not_enough_data;
+ if (GET_BYTE (pos) != '2' ||
+ GET_BYTE (pos + 1) < '0' || GET_BYTE (pos + 1) > '9' ||
+ GET_BYTE (pos + 2) < '0' || GET_BYTE (pos + 2) > '9')
+ goto error;
+
+ /* Clear any trailing chars */
+ while (pos + 1 < priv->recv_buf_fill &&
+ GET_BYTE (pos) != '\r' && GET_BYTE (pos + 1) != '\n')
+ pos++;
+ if (pos + 1 >= priv->recv_buf_fill)
+ goto not_enough_data;
+ pos += 2;
+
+ /* Consume the data we just parsed. */
+ priv->recv_buf_pos = (priv->recv_buf_pos + pos) % priv->recv_buf_length;
+ priv->recv_buf_fill -= pos;
+
+ priv->content_length = 0;
+ priv->state = HTTP_STATE_HEADERS;
+
+ goto retry;
+ }
+ break;
+ case HTTP_STATE_HEADERS:
+ {
+ guint pos = 0;
+
+ if (pos + 15 < priv->recv_buf_fill &&
+ (GET_BYTE (pos + 0) == 'C' || GET_BYTE (pos + 0) == 'c') &&
+ (GET_BYTE (pos + 1) == 'o' || GET_BYTE (pos + 1) == 'O') &&
+ (GET_BYTE (pos + 2) == 'n' || GET_BYTE (pos + 2) == 'N') &&
+ (GET_BYTE (pos + 3) == 't' || GET_BYTE (pos + 3) == 'T') &&
+ (GET_BYTE (pos + 4) == 'e' || GET_BYTE (pos + 4) == 'E') &&
+ (GET_BYTE (pos + 5) == 'n' || GET_BYTE (pos + 5) == 'N') &&
+ (GET_BYTE (pos + 6) == 't' || GET_BYTE (pos + 6) == 'T') &&
+ GET_BYTE (pos + 7) == '-' &&
+ (GET_BYTE (pos + 8) == 'L' || GET_BYTE (pos + 8) == 'l') &&
+ (GET_BYTE (pos + 9) == 'e' || GET_BYTE (pos + 9) == 'E') &&
+ (GET_BYTE (pos + 10) == 'n' || GET_BYTE (pos + 10) == 'N') &&
+ (GET_BYTE (pos + 11) == 'g' || GET_BYTE (pos + 11) == 'G') &&
+ (GET_BYTE (pos + 12) == 't' || GET_BYTE (pos + 12) == 'T') &&
+ (GET_BYTE (pos + 13) == 'h' || GET_BYTE (pos + 13) == 'H') &&
+ GET_BYTE (pos + 14) == ':') {
+ /* Found a Content-Length header. Parse and store the value. Note that
+ * the HTTP standard allows for arbitrarily-big content lengths. We
+ * limit it to G_MAXSIZE for sanity’s sake.
+ *
+ * The code below is equivalent to strtoul(input, NULL, 10), but
+ * operates on a ring buffer. */
+ pos += 15;
+ EAT_WHITESPACE (pos);
+ priv->content_length = 0;
+
+ while (TRUE) {
+ guint8 byte = GET_BYTE (pos);
+ gint val = g_ascii_digit_value (byte);
+
+ if (byte == '\r') {
+ /* Reached the end of the value; fall out to the code below which
+ * will grab the \n. */
+ break;
+ } else if (val == -1) {
+ priv->content_length = 0;
+ goto error;
+ }
+
+ /* Check for overflow. Don’t flag it as an error; just fall through
+ * to the code below which will skip to the \r\n. */
+ if (priv->content_length > G_MAXSIZE / 10 ||
+ priv->content_length * 10 > G_MAXSIZE - val) {
+ priv->content_length = 0;
+ break;
+ }
+
+ priv->content_length = (priv->content_length * 10) + val;
+
+ if (pos + 1 > priv->recv_buf_fill)
+ goto not_enough_data;
+ pos++;
+ }
+ }
+
+ /* Skip over the header. */
+ while (pos + 1 < priv->recv_buf_fill &&
+ GET_BYTE (pos) != '\r' && GET_BYTE (pos + 1) != '\n')
+ pos++;
+
+ nice_debug ("pos = %u, fill = %" G_GSSIZE_FORMAT,
+ pos, priv->recv_buf_fill);
+
+ if (pos + 1 >= priv->recv_buf_fill)
+ goto not_enough_data;
+ pos += 2;
+
+ /* Consume the data we just parsed. */
+ priv->recv_buf_pos = (priv->recv_buf_pos + pos) % priv->recv_buf_length;
+ priv->recv_buf_fill -= pos;
+
+ if (pos == 2)
+ priv->state = HTTP_STATE_BODY;
+
+ goto retry;
+ }
+ break;
+ case HTTP_STATE_BODY:
+ {
+ gsize consumed;
+
+ if (priv->content_length == 0) {
+ priv->state = HTTP_STATE_CONNECTED;
+ goto retry;
+ }
+
+ if (priv->recv_buf_fill == 0)
+ goto not_enough_data;
+
+ consumed = MIN (priv->content_length, priv->recv_buf_fill);
+
+ priv->recv_buf_pos =
+ (priv->recv_buf_pos + consumed) % priv->recv_buf_length;
+ priv->recv_buf_fill -= consumed;
+ priv->content_length -= consumed;
+
+ goto retry;
+ }
+ break;
+ case HTTP_STATE_CONNECTED:
+ {
+ gsize len;
+
+ len = memcpy_ring_buffer_to_input_messages (priv,
+ recv_messages, n_recv_messages);
+
+ /* Send the pending data */
+ nice_socket_flush_send_queue (priv->base_socket,
+ &priv->send_queue);
+
+ return len;
+ }
+ break;
+ case HTTP_STATE_ERROR:
+ default:
+ /* Unknown status */
+ goto error;
+ }
+
+ not_enough_data:
+ return 0;
+
+ error:
+ nice_debug ("http error");
+ if (priv->base_socket)
+ nice_socket_free (priv->base_socket);
+ priv->base_socket = NULL;
+ priv->state = HTTP_STATE_ERROR;
+
+ return -1;
+}
+
+static gint
+socket_send_messages (NiceSocket *sock, const NiceAddress *to,
+ const NiceOutputMessage *messages, guint n_messages)
+{
+ HttpPriv *priv = sock->priv;
+
+ /* Make sure socket has not been freed: */
+ g_assert (sock->priv != NULL);
+
+ if (priv->state == HTTP_STATE_CONNECTED) {
+ /* Fast path. */
+ if (!priv->base_socket)
+ return -1;
+
+ return nice_socket_send_messages (priv->base_socket, to, messages,
+ n_messages);
+ } else if (priv->state == HTTP_STATE_ERROR) {
+ return -1;
+ } else {
+ return 0;
+ }
+
+ return n_messages;
+}
+
+static gint
+socket_send_messages_reliable (NiceSocket *sock, const NiceAddress *to,
+ const NiceOutputMessage *messages, guint n_messages)
+{
+ HttpPriv *priv = sock->priv;
+
+ if (priv->state == HTTP_STATE_CONNECTED) {
+ /* Fast path. */
+ if (!priv->base_socket)
+ return -1;
+
+ return nice_socket_send_messages_reliable (priv->base_socket, to, messages,
+ n_messages);
+ } else if (priv->state == HTTP_STATE_ERROR) {
+ return -1;
+ } else {
+ nice_socket_queue_send (&priv->send_queue, to, messages, n_messages);
+ }
+
+ return n_messages;
+}
+
+static gboolean
+socket_is_reliable (NiceSocket *sock)
+{
+ HttpPriv *priv = sock->priv;
+
+ return nice_socket_is_reliable (priv->base_socket);
+}
+
+static gboolean
+socket_can_send (NiceSocket *sock, NiceAddress *addr)
+{
+ HttpPriv *priv = sock->priv;
+
+ return nice_socket_can_send (priv->base_socket, addr);
+}
+
+static void
+socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data)
+{
+ HttpPriv *priv = sock->priv;
+
+ nice_socket_set_writable_callback (priv->base_socket, callback, user_data);
+}
+
+static gboolean
+socket_is_based_on (NiceSocket *sock, NiceSocket *other)
+{
+ HttpPriv *priv = sock->priv;
+
+ return (sock == other) ||
+ (priv && nice_socket_is_based_on (priv->base_socket, other));
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2008 Nokia Corporation. All rights reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef _HTTP_H
+#define _HTTP_H
+
+#include "socket.h"
+#include "agent.h"
+
+G_BEGIN_DECLS
+
+
+NiceSocket *
+nice_http_socket_new (NiceSocket *base_socket,
+ NiceAddress *addr, gchar *username, gchar *password);
+
+
+G_END_DECLS
+
+#endif /* _HTTP_H */
+
--- /dev/null
+socket_sources = [
+ 'socket.c',
+ 'udp-bsd.c',
+ 'tcp-bsd.c',
+ 'tcp-active.c',
+ 'tcp-passive.c',
+ 'pseudossl.c',
+ 'socks5.c',
+ 'http.c',
+ 'udp-turn.c',
+ 'udp-turn-over-tcp.c',
+]
+
+libsocket = static_library('socket', socket_sources,
+ c_args: ['-DG_LOG_DOMAIN="libnice-socket"'],
+ include_directories: nice_incs,
+ dependencies: nice_deps,
+ install: false)
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2008-2009 Nokia Corporation. All rights reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+/*
+ * Implementation of TCP relay socket interface using TCP Berkeley sockets. (See
+ * http://en.wikipedia.org/wiki/Berkeley_sockets.)
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "pseudossl.h"
+#include "agent-priv.h"
+#include "socket-priv.h"
+
+#include <string.h>
+
+#ifndef G_OS_WIN32
+#include <unistd.h>
+#endif
+
+typedef struct {
+ gboolean handshaken;
+ NiceSocket *base_socket;
+ GQueue send_queue;
+ NicePseudoSSLSocketCompatibility compatibility;
+} PseudoSSLPriv;
+
+
+static const gchar SSL_SERVER_GOOGLE_HANDSHAKE[] = {
+ 0x16, 0x03, 0x01, 0x00, 0x4a, 0x02, 0x00, 0x00,
+ 0x46, 0x03, 0x01, 0x42, 0x85, 0x45, 0xa7, 0x27,
+ 0xa9, 0x5d, 0xa0, 0xb3, 0xc5, 0xe7, 0x53, 0xda,
+ 0x48, 0x2b, 0x3f, 0xc6, 0x5a, 0xca, 0x89, 0xc1,
+ 0x58, 0x52, 0xa1, 0x78, 0x3c, 0x5b, 0x17, 0x46,
+ 0x00, 0x85, 0x3f, 0x20, 0x0e, 0xd3, 0x06, 0x72,
+ 0x5b, 0x5b, 0x1b, 0x5f, 0x15, 0xac, 0x13, 0xf9,
+ 0x88, 0x53, 0x9d, 0x9b, 0xe8, 0x3d, 0x7b, 0x0c,
+ 0x30, 0x32, 0x6e, 0x38, 0x4d, 0xa2, 0x75, 0x57,
+ 0x41, 0x6c, 0x34, 0x5c, 0x00, 0x04, 0x00};
+
+static const gchar SSL_CLIENT_GOOGLE_HANDSHAKE[] = {
+ 0x80, 0x46, 0x01, 0x03, 0x01, 0x00, 0x2d, 0x00,
+ 0x00, 0x00, 0x10, 0x01, 0x00, 0x80, 0x03, 0x00,
+ 0x80, 0x07, 0x00, 0xc0, 0x06, 0x00, 0x40, 0x02,
+ 0x00, 0x80, 0x04, 0x00, 0x80, 0x00, 0x00, 0x04,
+ 0x00, 0xfe, 0xff, 0x00, 0x00, 0x0a, 0x00, 0xfe,
+ 0xfe, 0x00, 0x00, 0x09, 0x00, 0x00, 0x64, 0x00,
+ 0x00, 0x62, 0x00, 0x00, 0x03, 0x00, 0x00, 0x06,
+ 0x1f, 0x17, 0x0c, 0xa6, 0x2f, 0x00, 0x78, 0xfc,
+ 0x46, 0x55, 0x2e, 0xb1, 0x83, 0x39, 0xf1, 0xea};
+
+static const gchar SSL_SERVER_MSOC_HANDSHAKE[] = {
+ 0x16, 0x03, 0x01, 0x00, 0x4e, 0x02, 0x00, 0x00,
+ 0x46, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x0e,
+ 0x00, 0x00, 0x00};
+
+static const gchar SSL_CLIENT_MSOC_HANDSHAKE[] = {
+ 0x16, 0x03, 0x01, 0x00, 0x2d, 0x01, 0x00, 0x00,
+ 0x29, 0x03, 0x01, 0xc1, 0xfc, 0xd5, 0xa3, 0x6d,
+ 0x93, 0xdd, 0x7e, 0x0b, 0x45, 0x67, 0x3f, 0xec,
+ 0x79, 0x85, 0xfb, 0xbc, 0x3f, 0xd6, 0x60, 0xc2,
+ 0xce, 0x84, 0x85, 0x08, 0x1b, 0x81, 0x21, 0xbc,
+ 0xaa, 0x10, 0xfb, 0x00, 0x00, 0x02, 0x00, 0x18,
+ 0x01, 0x00};
+
+static void socket_close (NiceSocket *sock);
+static gint socket_recv_messages (NiceSocket *sock,
+ NiceInputMessage *recv_messages, guint n_recv_messages);
+static gint socket_send_messages (NiceSocket *sock, const NiceAddress *to,
+ const NiceOutputMessage *messages, guint n_messages);
+static gint socket_send_messages_reliable (NiceSocket *sock,
+ const NiceAddress *to, const NiceOutputMessage *messages, guint n_messages);
+static gboolean socket_is_reliable (NiceSocket *sock);
+static gboolean socket_can_send (NiceSocket *sock, NiceAddress *addr);
+static void socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data);
+static gboolean socket_is_based_on (NiceSocket *sock, NiceSocket *other);
+
+NiceSocket *
+nice_pseudossl_socket_new (NiceSocket *base_socket,
+ NicePseudoSSLSocketCompatibility compatibility)
+{
+ PseudoSSLPriv *priv;
+ NiceSocket *sock;
+ const gchar *buf;
+ guint len;
+
+ if (compatibility == NICE_PSEUDOSSL_SOCKET_COMPATIBILITY_MSOC) {
+ buf = SSL_CLIENT_MSOC_HANDSHAKE;
+ len = sizeof(SSL_CLIENT_MSOC_HANDSHAKE);
+ } else if (compatibility == NICE_PSEUDOSSL_SOCKET_COMPATIBILITY_GOOGLE) {
+ buf = SSL_CLIENT_GOOGLE_HANDSHAKE;
+ len = sizeof(SSL_CLIENT_GOOGLE_HANDSHAKE);
+ } else {
+ return NULL;
+ }
+
+ sock = g_slice_new0 (NiceSocket);
+ sock->priv = priv = g_slice_new0 (PseudoSSLPriv);
+
+ priv->handshaken = FALSE;
+ priv->base_socket = base_socket;
+ priv->compatibility = compatibility;
+
+ sock->type = NICE_SOCKET_TYPE_PSEUDOSSL;
+ sock->fileno = priv->base_socket->fileno;
+ sock->addr = priv->base_socket->addr;
+ sock->send_messages = socket_send_messages;
+ sock->send_messages_reliable = socket_send_messages_reliable;
+ sock->recv_messages = socket_recv_messages;
+ sock->is_reliable = socket_is_reliable;
+ sock->can_send = socket_can_send;
+ sock->set_writable_callback = socket_set_writable_callback;
+ sock->is_based_on = socket_is_based_on;
+ sock->close = socket_close;
+
+ /* We send 'to' NULL because it will always be to an already connected
+ * TCP base socket, which ignores the destination */
+ nice_socket_send_reliable (priv->base_socket, NULL, len, buf);
+
+ return sock;
+}
+
+
+static void
+socket_close (NiceSocket *sock)
+{
+ PseudoSSLPriv *priv = sock->priv;
+
+ if (priv->base_socket)
+ nice_socket_free (priv->base_socket);
+
+ nice_socket_free_send_queue (&priv->send_queue);
+
+ g_slice_free(PseudoSSLPriv, sock->priv);
+ sock->priv = NULL;
+}
+
+static gboolean
+server_handshake_valid(NiceSocket *sock, GInputVector *data, guint length)
+{
+ PseudoSSLPriv *priv = sock->priv;
+
+ if (priv->compatibility == NICE_PSEUDOSSL_SOCKET_COMPATIBILITY_MSOC) {
+ if (length == sizeof(SSL_SERVER_MSOC_HANDSHAKE)) {
+ guint8 *buf = data->buffer;
+
+ memset(buf + 11, 0, 32);
+ memset(buf + 44, 0, 32);
+ return memcmp(SSL_SERVER_MSOC_HANDSHAKE, data->buffer,
+ sizeof(SSL_SERVER_MSOC_HANDSHAKE)) == 0;
+ }
+ return FALSE;
+ } else {
+ return length == sizeof(SSL_SERVER_GOOGLE_HANDSHAKE) &&
+ memcmp(SSL_SERVER_GOOGLE_HANDSHAKE, data->buffer,
+ sizeof(SSL_SERVER_GOOGLE_HANDSHAKE)) == 0;
+ }
+}
+
+static gint
+socket_recv_messages (NiceSocket *sock,
+ NiceInputMessage *recv_messages, guint n_recv_messages)
+{
+ PseudoSSLPriv *priv = sock->priv;
+
+ /* Make sure socket has not been freed: */
+ g_assert (sock->priv != NULL);
+
+ if (priv->handshaken) {
+ if (priv->base_socket) {
+ /* Fast path: once we’ve done the handshake, pass straight through to the
+ * base socket. */
+ return nice_socket_recv_messages (priv->base_socket,
+ recv_messages, n_recv_messages);
+ }
+ } else {
+ guint8 data[MAX(sizeof(SSL_SERVER_GOOGLE_HANDSHAKE),
+ sizeof(SSL_SERVER_MSOC_HANDSHAKE))];
+ gint ret = -1;
+ GInputVector local_recv_buf = { data, sizeof(data) };
+ NiceInputMessage local_recv_message = { &local_recv_buf, 1, NULL, 0 };
+
+
+ if (priv->compatibility == NICE_PSEUDOSSL_SOCKET_COMPATIBILITY_MSOC) {
+ local_recv_buf.size = sizeof(SSL_SERVER_MSOC_HANDSHAKE);
+ } else {
+ local_recv_buf.size = sizeof(SSL_SERVER_GOOGLE_HANDSHAKE);
+ }
+ if (priv->base_socket) {
+ ret = nice_socket_recv_messages (priv->base_socket,
+ &local_recv_message, 1);
+ }
+
+ if (ret <= 0) {
+ return ret;
+ } else if (ret == 1 && server_handshake_valid(sock, &local_recv_buf,
+ local_recv_message.length)) {
+ priv->handshaken = TRUE;
+ nice_socket_flush_send_queue (priv->base_socket, &priv->send_queue);
+ } else {
+ if (priv->base_socket)
+ nice_socket_free (priv->base_socket);
+ priv->base_socket = NULL;
+
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static gint
+socket_send_messages (NiceSocket *sock, const NiceAddress *to,
+ const NiceOutputMessage *messages, guint n_messages)
+{
+ PseudoSSLPriv *priv = sock->priv;
+
+ /* Make sure socket has not been freed: */
+ g_assert (sock->priv != NULL);
+
+ if (priv->handshaken) {
+ /* Fast path: pass directly through to the base socket once the handshake is
+ * complete. */
+ if (priv->base_socket == NULL)
+ return -1;
+
+ return nice_socket_send_messages (priv->base_socket, to, messages,
+ n_messages);
+ } else {
+ return 0;
+ }
+ return n_messages;
+}
+
+
+static gint
+socket_send_messages_reliable (NiceSocket *sock, const NiceAddress *to,
+ const NiceOutputMessage *messages, guint n_messages)
+{
+ PseudoSSLPriv *priv = sock->priv;
+
+ if (priv->handshaken) {
+ /* Fast path: pass directly through to the base socket once the handshake is
+ * complete. */
+ if (priv->base_socket == NULL)
+ return -1;
+
+ return nice_socket_send_messages_reliable (priv->base_socket, to, messages,
+ n_messages);
+ } else {
+ nice_socket_queue_send (&priv->send_queue, to, messages, n_messages);
+ }
+ return n_messages;
+}
+
+static gboolean
+socket_is_reliable (NiceSocket *sock)
+{
+ PseudoSSLPriv *priv = sock->priv;
+
+ return nice_socket_is_reliable (priv->base_socket);
+}
+
+static gboolean
+socket_can_send (NiceSocket *sock, NiceAddress *addr)
+{
+ PseudoSSLPriv *priv = sock->priv;
+
+ return nice_socket_can_send (priv->base_socket, addr);
+}
+
+static void
+socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data)
+{
+ PseudoSSLPriv *priv = sock->priv;
+
+ nice_socket_set_writable_callback (priv->base_socket, callback, user_data);
+}
+
+static gboolean
+socket_is_based_on (NiceSocket *sock, NiceSocket *other)
+{
+ PseudoSSLPriv *priv = sock->priv;
+
+ return (sock == other) ||
+ (priv && nice_socket_is_based_on (priv->base_socket, other));
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2008-2009 Nokia Corporation. All rights reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef _PSEUDOSSL_H
+#define _PSEUDOSSL_H
+
+#include "socket.h"
+
+G_BEGIN_DECLS
+
+/**
+ * PseudosslCompatibility:
+ * @NICE_PSEUDOSSL_SOCKET_COMPATIBILITY_GOOGLE: Use google compatible pseudossl
+ * @NICE_PSEUDOSSL_SOCKET_COMPATIBILITY_MSOC: Use compatibility for Microsoft
+ * Office Communicator and Lync servers
+ *
+ * An enum to specify which pseudo SSL compatibility mode the #NiceSocket should
+ * use.
+ */
+typedef enum
+{
+ NICE_PSEUDOSSL_SOCKET_COMPATIBILITY_GOOGLE = 0,
+ NICE_PSEUDOSSL_SOCKET_COMPATIBILITY_MSOC,
+} NicePseudoSSLSocketCompatibility;
+
+NiceSocket *
+nice_pseudossl_socket_new (NiceSocket *base_socket,
+ NicePseudoSSLSocketCompatibility compatibility);
+
+
+G_END_DECLS
+
+#endif /* _PSEUDOSSL_H */
+
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2008-2009 Nokia Corporation. All rights reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef _SOCKET_PRIV_H
+#define _SOCKET_PRIV_H
+
+#include "socket.h"
+
+G_BEGIN_DECLS
+
+/**
+ * nice_socket_queue_send:
+ * @send_queue: The queue to add to
+ * @to : Destination
+ * @messages: Messages to queue
+ * @n_messages: Number of messages to queue
+ *
+ * Queue messages to be sent later into the GQueue
+ */
+void nice_socket_queue_send (GQueue *send_queue, const NiceAddress *to,
+ const NiceOutputMessage *messages, guint n_messages);
+
+/**
+ * nice_socket_queue_send_with_callback:
+ * @send_queue: The queue to add to
+ * @message: The message to queue
+ * @message_offset: Number of bytes to skip in the message
+ * @message_len: Total length of the message
+ * @head: Whether to add the message to the head of the queue or the tail
+ * @gsock: The #GSocket to create the callback on
+ * @io_source: Pointer to #GSource pointer to store the created source
+ * @context: #GMainContext to attach the @io_source to
+ * @cb: Callback function to call when the @gsock is writable
+ * @user_data: User data for @cb
+ *
+ * Queue (partial) message to be sent later and create a source to call @cb
+ * when the @gsock becomes writable.
+ * The @message_offset can be used if a partial write happened and some bytes
+ * were already written, in which case @head should be set to TRUE to add the
+ * message to the head of the queue.
+ */
+void nice_socket_queue_send_with_callback (GQueue *send_queue,
+ const NiceOutputMessage *message, gsize message_offset, gsize message_len,
+ gboolean head, GSocket *gsock, GSource **io_source, GMainContext *context,
+ GSocketSourceFunc cb, gpointer user_data);
+
+/**
+ * nice_socket_flush_send_queue:
+ * @base_socket: Base socket to send on
+ * @send_queue: Queue to flush
+ *
+ * Send all the queued messages reliably to the base socket. We assume only
+ * reliable messages were queued and the underlying socket will handle the
+ * send.
+ */
+void nice_socket_flush_send_queue (NiceSocket *base_socket, GQueue *send_queue);
+
+/**
+ * nice_socket_flush_send_queue_to_socket:
+ * @gsock: GSocket to send on
+ * @send_queue: Queue to flush
+ *
+ * Send all the queued messages to the socket. If any message fails to be sent
+ * it will be readded to the queue and #FALSE will be returned, in which case
+ * the IO source must be kept to allow flushing the next time the socket
+ * is writable.
+ * If the queue gets flushed, #TRUE will be returned, in which case, the IO
+ * source should be destroyed.
+ *
+ * Returns: #TRUE if the queue was emptied, #FALSE if the socket would block.
+ */
+gboolean nice_socket_flush_send_queue_to_socket (GSocket *gsock,
+ GQueue *send_queue);
+
+/**
+ * nice_socket_free_send_queue:
+ * @send_queue: The send queue
+ *
+ * Frees every item in the send queue without sending them and empties the queue
+ */
+void nice_socket_free_send_queue (GQueue *send_queue);
+
+G_END_DECLS
+
+#endif /* _SOCKET_PRIV_H */
+
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2008-2009 Nokia Corporation. All rights reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+
+#include <glib.h>
+
+#include "socket.h"
+#include "socket-priv.h"
+#include "agent-priv.h"
+
+#include <string.h>
+
+#ifndef G_OS_WIN32
+#include <unistd.h>
+#endif
+
+typedef struct _NiceSocketQueuedSend NiceSocketQueuedSend;
+
+struct _NiceSocketQueuedSend {
+ guint8 *buf; /* owned */
+ gsize length;
+ NiceAddress to;
+};
+
+/**
+ * nice_socket_recv_messages:
+ * @sock: a #NiceSocket
+ * @recv_messages: (array length=n_recv_messages) (out caller-allocates):
+ * array of #NiceInputMessages to return received messages in
+ * @n_recv_messages: number of elements in the @recv_messages array
+ *
+ * Receive up to @n_recv_messages message on the socket, in a non-reliable,
+ * non-blocking fashion. The total size of the buffers in each #NiceInputMessage
+ * must be big enough to contain an entire message (65536 bytes), or excess
+ * bytes will be silently dropped.
+ *
+ * On success, the number of messages received into @recv_messages is returned,
+ * which may be less than @n_recv_messages if the call would have blocked
+ * part-way through. If the socket would have blocked to begin with, or if
+ * @n_recv_messages is zero, zero is returned. On failure, a negative value is
+ * returned, but no further error information is available. Calling this
+ * function on a socket which has closed is an error, and a negative value is
+ * returned.
+ *
+ * If a positive N is returned, the first N messages in @recv_messages are
+ * valid. Each valid message is guaranteed to have a non-zero
+ * #NiceInputMessage::length, and its buffers are guaranteed to be filled
+ * sequentially up to that number of bytes If #NiceInputMessage::from was
+ * non-%NULL for a valid message, it may be set to the address of the sender of
+ * that received message.
+ *
+ * If the return value is zero or negative, the from return address and length
+ * in every #NiceInputMessage in @recv_messages are guaranteed to be unmodified.
+ * The buffers may have been modified.
+ *
+ * The base addresses and sizes of the buffers in a #NiceInputMessage are never
+ * modified. Neither is the base address of #NiceInputMessage::from, nor the
+ * base address and length of the #NiceInputMessage::buffers array.
+ *
+ * Returns: number of valid messages returned in @recv_messages, or a negative
+ * value on error
+ *
+ * Since: 0.1.5
+ */
+gint
+nice_socket_recv_messages (NiceSocket *sock,
+ NiceInputMessage *recv_messages, guint n_recv_messages)
+{
+ g_return_val_if_fail (sock != NULL, -1);
+ g_return_val_if_fail (n_recv_messages == 0 || recv_messages != NULL, -1);
+
+ return sock->recv_messages (sock, recv_messages, n_recv_messages);
+}
+
+/**
+ * nice_socket_send_messages:
+ * @sock: a #NiceSocket
+ * @messages: (array length=n_messages) (in caller-allocates):
+ * array of #NiceOutputMessages containing the messages to send
+ * @n_messages: number of elements in the @messages array
+ *
+ * Send up to @n_messages on the socket, in a non-reliable, non-blocking
+ * fashion. The total size of the buffers in each #NiceOutputMessage
+ * must be at most the maximum UDP payload size (65535 bytes), or excess
+ * bytes will be silently dropped.
+ *
+ * On success, the number of messages transmitted from @messages is returned,
+ * which may be less than @n_messages if the call would have blocked
+ * part-way through. If the socket would have blocked to begin with, or if
+ * @n_messages is zero, zero is returned. On failure, a negative value is
+ * returned, but no further error information is available. Calling this
+ * function on a socket which has closed is an error, and a negative value is
+ * returned.
+ *
+ * If a positive N is returned, the first N messages in @messages have been
+ * sent in full, and the remaining messages have not been sent at all.
+ *
+ * If #NiceOutputMessage::to is specified for a message, that will be used as
+ * the destination address for the message. Otherwise, if %NULL, the default
+ * destination for @sock will be used.
+ *
+ * Every field of every #NiceOutputMessage is guaranteed to be unmodified when
+ * this function returns.
+ *
+ * Returns: number of messages successfully sent from @messages, or a negative
+ * value on error
+ *
+ * Since: 0.1.5
+ */
+gint
+nice_socket_send_messages (NiceSocket *sock, const NiceAddress *to,
+ const NiceOutputMessage *messages, guint n_messages)
+{
+ g_return_val_if_fail (sock != NULL, -1);
+ g_return_val_if_fail (n_messages == 0 || messages != NULL, -1);
+
+ return sock->send_messages (sock, to, messages, n_messages);
+}
+
+/**
+ * nice_socket_send_messages_reliable:
+ * @sock: a #NiceSocket
+ * @messages: (array length=n_messages) (in caller-allocates):
+ * array of #NiceOutputMessages containing the messages to send
+ * @n_messages: number of elements in the @messages array
+ *
+ * Send @n_messages on the socket, in a reliable, non-blocking fashion.
+ * The total size of the buffers in each #NiceOutputMessage
+ * must be at most the maximum UDP payload size (65535 bytes), or excess
+ * bytes will be silently dropped.
+ *
+ * On success, the number of messages transmitted from @messages is returned,
+ * which will be equal to @n_messages. If the call would have blocked part-way
+ * though, the remaining bytes will be queued for sending later.
+ * On failure, a negative value is returned, but no further error information
+ * is available. Calling this function on a socket which has closed is an error,
+ * and a negative value is returned. Calling this function on a socket which
+ * is not TCP or does not have a TCP base socket, will result in an error.
+ *
+ * If #NiceOutputMessage::to is specified for a message, that will be used as
+ * the destination address for the message. Otherwise, if %NULL, the default
+ * destination for @sock will be used.
+ *
+ * Every field of every #NiceOutputMessage is guaranteed to be unmodified when
+ * this function returns.
+ *
+ * Returns: number of messages successfully sent from @messages, or a negative
+ * value on error
+ *
+ * Since: 0.1.5
+ */
+gint
+nice_socket_send_messages_reliable (NiceSocket *sock, const NiceAddress *to,
+ const NiceOutputMessage *messages, guint n_messages)
+{
+ g_return_val_if_fail (sock != NULL, -1);
+ g_return_val_if_fail (n_messages == 0 || messages != NULL, -1);
+
+ return sock->send_messages_reliable (sock, to, messages, n_messages);
+}
+
+/* Convenience wrapper around nice_socket_recv_messages(). Returns the number of
+ * bytes received on success (which will be @len), zero if sending would block, or
+ * -1 on error. */
+gssize
+nice_socket_recv (NiceSocket *sock, NiceAddress *from, gsize len,
+ gchar *buf)
+{
+ GInputVector local_buf = { buf, len };
+ NiceInputMessage local_message = { &local_buf, 1, from, 0};
+ gint ret;
+
+ ret = sock->recv_messages (sock, &local_message, 1);
+ if (ret == 1)
+ return local_message.length;
+ return ret;
+}
+
+/* Convenience wrapper around nice_socket_send_messages(). Returns the number of
+ * bytes sent on success (which will be @len), zero if sending would block, or
+ * -1 on error. */
+gssize
+nice_socket_send (NiceSocket *sock, const NiceAddress *to, gsize len,
+ const gchar *buf)
+{
+ GOutputVector local_buf = { buf, len };
+ NiceOutputMessage local_message = { &local_buf, 1};
+ gint ret;
+
+ ret = sock->send_messages (sock, to, &local_message, 1);
+ if (ret == 1)
+ return len;
+ return ret;
+}
+
+gssize
+nice_socket_send_reliable (NiceSocket *sock, const NiceAddress *to, gsize len,
+ const gchar *buf)
+{
+ GOutputVector local_buf = { buf, len };
+ NiceOutputMessage local_message = { &local_buf, 1};
+ gint ret;
+
+ ret = sock->send_messages_reliable (sock, to, &local_message, 1);
+ if (ret == 1)
+ return len;
+ return ret;
+}
+
+gboolean
+nice_socket_is_reliable (NiceSocket *sock)
+{
+ return sock->is_reliable (sock);
+}
+
+gboolean
+nice_socket_can_send (NiceSocket *sock, NiceAddress *addr)
+{
+ if (sock->can_send)
+ return sock->can_send (sock, addr);
+ return TRUE;
+}
+
+void
+nice_socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data)
+{
+ if (sock->set_writable_callback)
+ sock->set_writable_callback (sock, callback, user_data);
+}
+
+gboolean
+nice_socket_is_based_on (NiceSocket *sock, NiceSocket *other)
+{
+ if (sock->is_based_on)
+ return sock->is_based_on (sock, other);
+ return (sock == other);
+}
+
+void
+nice_socket_free (NiceSocket *sock)
+{
+ if (sock) {
+ sock->close (sock);
+ g_slice_free (NiceSocket,sock);
+ }
+}
+
+static void
+nice_socket_free_queued_send (NiceSocketQueuedSend *tbs)
+{
+ g_free (tbs->buf);
+ g_slice_free (NiceSocketQueuedSend, tbs);
+}
+
+void
+nice_socket_queue_send (GQueue *send_queue, const NiceAddress *to,
+ const NiceOutputMessage *messages, guint n_messages)
+{
+ guint i;
+
+ if (n_messages == 0)
+ return;
+
+ /* Compact the message’s buffers before queueing. */
+ for (i = 0; i < n_messages; i++) {
+ NiceSocketQueuedSend *tbs;
+ const NiceOutputMessage *message = &messages[i];
+ gsize message_len_remaining = output_message_get_size (message);
+ guint j;
+ gsize offset = 0;
+
+ if (message_len_remaining == 0)
+ continue;
+
+ /* Compact the buffer. */
+ tbs = g_slice_new0 (NiceSocketQueuedSend);
+ tbs->buf = g_malloc (message_len_remaining);
+ tbs->length = message_len_remaining;
+
+ if (to)
+ tbs->to = *to;
+ else
+ memset (&tbs->to, 0, sizeof(NiceAddress));
+ g_queue_push_tail (send_queue, tbs);
+
+ for (j = 0;
+ (message->n_buffers >= 0 && j < (guint) message->n_buffers) ||
+ (message->n_buffers < 0 && message->buffers[j].buffer != NULL);
+ j++) {
+ const GOutputVector *buffer = &message->buffers[j];
+ gsize len;
+
+ len = MIN (buffer->size, message_len_remaining);
+ memcpy (tbs->buf + offset, buffer->buffer, len);
+ message_len_remaining -= len;
+ offset += len;
+ }
+
+ g_assert (offset == tbs->length);
+ }
+}
+
+void nice_socket_queue_send_with_callback (GQueue *send_queue,
+ const NiceOutputMessage *message, gsize message_offset, gsize message_len,
+ gboolean head, GSocket *gsock, GSource **io_source, GMainContext *context,
+ GSocketSourceFunc cb, gpointer user_data)
+{
+ NiceSocketQueuedSend *tbs;
+ guint j;
+ gsize offset = 0;
+
+ if (message_offset >= message_len)
+ return;
+
+ tbs = g_slice_new0 (NiceSocketQueuedSend);
+ tbs->length = message_len - message_offset;
+ tbs->buf = g_malloc (tbs->length);
+
+ if (head)
+ g_queue_push_head (send_queue, tbs);
+ else
+ g_queue_push_tail (send_queue, tbs);
+
+ if (io_source && gsock && context && cb && *io_source == NULL) {
+ *io_source = g_socket_create_source(gsock, G_IO_OUT, NULL);
+ g_source_set_callback (*io_source, (GSourceFunc) G_CALLBACK (cb), user_data, NULL);
+ g_source_attach (*io_source, context);
+ }
+
+ /* Move the data into the buffer. */
+ for (j = 0;
+ (message->n_buffers >= 0 && j < (guint) message->n_buffers) ||
+ (message->n_buffers < 0 && message->buffers[j].buffer != NULL);
+ j++) {
+ const GOutputVector *buffer = &message->buffers[j];
+ gsize len;
+
+ /* Skip this buffer if it’s within @message_offset. */
+ if (buffer->size <= message_offset) {
+ message_offset -= buffer->size;
+ continue;
+ }
+
+ len = MIN (tbs->length - offset, buffer->size - message_offset);
+ memcpy (tbs->buf + offset, (guint8 *) buffer->buffer + message_offset, len);
+ offset += len;
+ if (message_offset >= len)
+ message_offset -= len;
+ else
+ message_offset = 0;
+ }
+}
+
+void nice_socket_flush_send_queue (NiceSocket *base_socket, GQueue *send_queue)
+{
+ NiceSocketQueuedSend *tbs;
+
+ while ((tbs = g_queue_pop_head (send_queue))) {
+ NiceAddress *to = &tbs->to;
+
+ if (!nice_address_is_valid (to))
+ to = NULL;
+
+ /* We only queue reliable data */
+ nice_socket_send_reliable (base_socket, to,
+ tbs->length, (const gchar *) tbs->buf);
+ nice_socket_free_queued_send (tbs);
+ }
+}
+
+gboolean nice_socket_flush_send_queue_to_socket (GSocket *gsock,
+ GQueue *send_queue)
+{
+ NiceSocketQueuedSend *tbs;
+ GError *gerr = NULL;
+
+
+ while ((tbs = g_queue_pop_head (send_queue)) != NULL) {
+ int ret;
+
+ GOutputVector local_bufs = { tbs->buf, tbs->length };
+ ret = g_socket_send_message (gsock, NULL, &local_bufs, 1, NULL, 0,
+ G_SOCKET_MSG_NONE, NULL, &gerr);
+
+ if (ret < 0) {
+ if (g_error_matches (gerr, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
+ GOutputVector local_buf = { tbs->buf, tbs->length };
+ NiceOutputMessage local_message = {&local_buf, 1};
+
+ nice_socket_queue_send_with_callback (send_queue, &local_message,
+ 0, local_buf.size, TRUE, NULL, NULL, NULL, NULL, NULL);
+ nice_socket_free_queued_send (tbs);
+ g_error_free (gerr);
+ return FALSE;
+ }
+ g_clear_error (&gerr);
+ } else if (ret < (int) tbs->length) {
+ GOutputVector local_buf = { tbs->buf + ret, tbs->length - ret };
+ NiceOutputMessage local_message = {&local_buf, 1};
+
+ nice_socket_queue_send_with_callback (send_queue, &local_message,
+ 0, local_buf.size, TRUE, NULL, NULL, NULL, NULL, NULL);
+ nice_socket_free_queued_send (tbs);
+ return FALSE;
+ }
+
+ nice_socket_free_queued_send (tbs);
+ }
+
+ return TRUE;
+}
+
+void
+nice_socket_free_send_queue (GQueue *send_queue)
+{
+ g_list_free_full (send_queue->head, (GDestroyNotify) nice_socket_free_queued_send);
+ g_queue_init (send_queue);
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2008-2009 Nokia Corporation. All rights reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef _SOCKET_H
+#define _SOCKET_H
+
+#include "agent.h"
+#include "address.h"
+#include <gio/gio.h>
+
+#ifdef G_OS_WIN32
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+
+G_BEGIN_DECLS
+
+typedef struct _NiceSocket NiceSocket;
+
+typedef enum {
+ NICE_SOCKET_TYPE_UDP_BSD,
+ NICE_SOCKET_TYPE_TCP_BSD,
+ NICE_SOCKET_TYPE_PSEUDOSSL,
+ NICE_SOCKET_TYPE_HTTP,
+ NICE_SOCKET_TYPE_SOCKS5,
+ NICE_SOCKET_TYPE_UDP_TURN,
+ NICE_SOCKET_TYPE_UDP_TURN_OVER_TCP,
+ NICE_SOCKET_TYPE_TCP_ACTIVE,
+ NICE_SOCKET_TYPE_TCP_PASSIVE,
+ NICE_SOCKET_TYPE_TCP_SO
+} NiceSocketType;
+
+typedef void (*NiceSocketWritableCb) (NiceSocket *sock, gpointer user_data);
+
+struct _NiceSocket
+{
+ NiceAddress addr;
+ NiceSocketType type;
+ GSocket *fileno;
+ /* Implementations must handle any value of n_recv_messages, including 0. Iff
+ * n_recv_messages is 0, recv_messages may be NULL. */
+ gint (*recv_messages) (NiceSocket *sock,
+ NiceInputMessage *recv_messages, guint n_recv_messages);
+ /* As above, @n_messages may be zero. Iff so, @messages may be %NULL. */
+ gint (*send_messages) (NiceSocket *sock, const NiceAddress *to,
+ const NiceOutputMessage *messages, guint n_messages);
+ gint (*send_messages_reliable) (NiceSocket *sock, const NiceAddress *to,
+ const NiceOutputMessage *messages, guint n_messages);
+ gboolean (*is_reliable) (NiceSocket *sock);
+ gboolean (*can_send) (NiceSocket *sock, NiceAddress *addr);
+ void (*set_writable_callback) (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data);
+ gboolean (*is_based_on) (NiceSocket *sock, NiceSocket *other);
+ void (*close) (NiceSocket *sock);
+ void *priv;
+};
+
+
+G_GNUC_WARN_UNUSED_RESULT
+gint
+nice_socket_recv_messages (NiceSocket *sock,
+ NiceInputMessage *recv_messages, guint n_recv_messages);
+
+gint
+nice_socket_send_messages (NiceSocket *sock, const NiceAddress *addr,
+ const NiceOutputMessage *messages, guint n_messages);
+gint
+nice_socket_send_messages_reliable (NiceSocket *sock, const NiceAddress *addr,
+ const NiceOutputMessage *messages, guint n_messages);
+gssize
+nice_socket_recv (NiceSocket *sock, NiceAddress *from, gsize len,
+ gchar *buf);
+gssize
+nice_socket_send (NiceSocket *sock, const NiceAddress *to, gsize len,
+ const gchar *buf);
+gssize
+nice_socket_send_reliable (NiceSocket *sock, const NiceAddress *addr, gsize len,
+ const gchar *buf);
+
+gboolean
+nice_socket_is_reliable (NiceSocket *sock);
+
+gboolean
+nice_socket_can_send (NiceSocket *sock, NiceAddress *addr);
+
+void
+nice_socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data);
+
+/**
+ * nice_socket_is_based_on:
+ * @sock: a #NiceSocket
+ * @other: another #NiceSocket
+ *
+ * Checks whether @sock wraps @other as a source and destination of its read and
+ * write operations. The function traverses the whole chain of @sock's base
+ * sockets until @other is found or the end is reached.
+ *
+ * Returns: %TRUE if @sock is based on @other or if @sock and @other are
+ * the same socket, %FALSE otherwise.
+ *
+ * Since: 0.1.14
+ */
+gboolean
+nice_socket_is_based_on (NiceSocket *sock, NiceSocket *other);
+
+void
+nice_socket_free (NiceSocket *sock);
+
+#include "udp-bsd.h"
+#include "tcp-bsd.h"
+#include "tcp-active.h"
+#include "tcp-passive.h"
+#include "pseudossl.h"
+#include "socks5.h"
+#include "http.h"
+#include "udp-turn.h"
+#include "udp-turn-over-tcp.h"
+
+G_END_DECLS
+
+#endif /* _SOCKET_H */
+
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2008 Nokia Corporation. All rights reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+/*
+ * Implementation of TCP relay socket interface using TCP Berkeley sockets. (See
+ * http://en.wikipedia.org/wiki/Berkeley_sockets.)
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "socks5.h"
+#include "agent-priv.h"
+#include "socket-priv.h"
+
+#include <string.h>
+
+#ifndef G_OS_WIN32
+#include <unistd.h>
+#endif
+
+typedef enum {
+ SOCKS_STATE_INIT,
+ SOCKS_STATE_AUTH,
+ SOCKS_STATE_CONNECT,
+ SOCKS_STATE_CONNECTED,
+ SOCKS_STATE_ERROR
+} SocksState;
+
+typedef struct {
+ SocksState state;
+ NiceSocket *base_socket;
+ NiceAddress addr;
+ gchar *username;
+ gchar *password;
+ GQueue send_queue;
+} Socks5Priv;
+
+
+static void socket_close (NiceSocket *sock);
+static gint socket_recv_messages (NiceSocket *sock,
+ NiceInputMessage *recv_messages, guint n_recv_messages);
+static gint socket_send_messages (NiceSocket *sock, const NiceAddress *to,
+ const NiceOutputMessage *messages, guint n_messages);
+static gint socket_send_messages_reliable (NiceSocket *sock,
+ const NiceAddress *to, const NiceOutputMessage *messages, guint n_messages);
+static gboolean socket_is_reliable (NiceSocket *sock);
+static gboolean socket_can_send (NiceSocket *sock, NiceAddress *addr);
+static void socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data);
+static gboolean socket_is_based_on (NiceSocket *sock, NiceSocket *other);
+
+
+NiceSocket *
+nice_socks5_socket_new (NiceSocket *base_socket,
+ NiceAddress *addr, gchar *username, gchar *password)
+{
+ Socks5Priv *priv;
+ NiceSocket *sock = NULL;
+
+ if (addr) {
+ sock = g_slice_new0 (NiceSocket);
+ sock->priv = priv = g_slice_new0 (Socks5Priv);
+
+ priv->base_socket = base_socket;
+ priv->addr = *addr;
+ priv->username = g_strdup (username);
+ priv->password = g_strdup (password);
+
+ sock->type = NICE_SOCKET_TYPE_SOCKS5;
+ sock->fileno = priv->base_socket->fileno;
+ sock->addr = priv->base_socket->addr;
+ sock->send_messages = socket_send_messages;
+ sock->send_messages_reliable = socket_send_messages_reliable;
+ sock->recv_messages = socket_recv_messages;
+ sock->is_reliable = socket_is_reliable;
+ sock->can_send = socket_can_send;
+ sock->set_writable_callback = socket_set_writable_callback;
+ sock->is_based_on = socket_is_based_on;
+ sock->close = socket_close;
+
+ /* Send SOCKS5 handshake */
+ {
+ gchar msg[4];
+ gint len = 3;
+
+ msg[0] = 0x05; /* SOCKS version */
+ msg[1] = 0x01; /* number of methods supported */
+ msg[2] = 0x00; /* no authentication method*/
+
+ g_debug ("user/pass : %s - %s", username, password);
+ /* add support for authentication method */
+ if (username || password) {
+ msg[1] = 0x02; /* number of methods supported */
+ msg[3] = 0x02; /* authentication method */
+ len++;
+ }
+
+ /* We send 'to' NULL because it will always be to an already connected
+ * TCP base socket, which ignores the destination */
+ nice_socket_send_reliable (priv->base_socket, NULL, len, msg);
+ priv->state = SOCKS_STATE_INIT;
+ }
+ }
+
+ return sock;
+}
+
+
+static void
+socket_close (NiceSocket *sock)
+{
+ Socks5Priv *priv = sock->priv;
+
+ if (priv->base_socket)
+ nice_socket_free (priv->base_socket);
+
+ if (priv->username)
+ g_free (priv->username);
+
+ if (priv->password)
+ g_free (priv->password);
+
+ nice_socket_free_send_queue (&priv->send_queue);
+
+ g_slice_free(Socks5Priv, sock->priv);
+ sock->priv = NULL;
+}
+
+
+static gint
+socket_recv_messages (NiceSocket *sock,
+ NiceInputMessage *recv_messages, guint n_recv_messages)
+{
+ Socks5Priv *priv = sock->priv;
+ guint i;
+ gint ret = -1;
+
+ /* Make sure socket has not been freed: */
+ g_assert (sock->priv != NULL);
+
+ switch (priv->state) {
+ case SOCKS_STATE_CONNECTED:
+ /* Common case: fast pass-through to the base socket once we’re
+ * connected. */
+ if (priv->base_socket) {
+ ret = nice_socket_recv_messages (priv->base_socket,
+ recv_messages, n_recv_messages);
+ }
+
+ if (ret <= 0)
+ return ret;
+
+ /* After successfully receiving into at least one NiceInputMessage,
+ * update the from address in each valid NiceInputMessage. */
+ for (i = 0; i < (guint) ret; i++) {
+ if (recv_messages[i].from != NULL)
+ *recv_messages[i].from = priv->addr;
+ }
+
+ return ret;
+
+ case SOCKS_STATE_INIT:
+ {
+ guint8 data[2];
+ GInputVector local_recv_buf = { data, sizeof (data) };
+ NiceInputMessage local_recv_message = { &local_recv_buf, 1, NULL, 0 };
+
+ nice_debug ("Socks5 state Init");
+
+ if (priv->base_socket) {
+ ret = nice_socket_recv_messages (priv->base_socket,
+ &local_recv_message, 1);
+ }
+
+ if (ret <= 0) {
+ return ret;
+ } else if (ret == 1 && local_recv_buf.size == sizeof(data)) {
+ if (data[0] == 0x05) {
+ if (data[1] == 0x02) {
+ gchar msg[515];
+ gint len = 0;
+
+ if (priv->username || priv->password) {
+ gint ulen = 0;
+ gint plen = 0;
+
+ if (priv->username)
+ ulen = strlen (priv->username);
+ if (ulen > 255) {
+ nice_debug ("Socks5 username length > 255");
+ goto error;
+ }
+
+ if (priv->password)
+ plen = strlen (priv->password);
+ if (plen > 255) {
+ nice_debug ("Socks5 password length > 255");
+ goto error;
+ }
+
+ msg[len++] = 0x01; /* auth version */
+ msg[len++] = ulen; /* username length */
+ if (ulen > 0)
+ memcpy (msg + len, priv->username, ulen); /* Username */
+ len += ulen;
+ msg[len++] = plen; /* Password length */
+ if (plen > 0)
+ memcpy (msg + len, priv->password, plen); /* Password */
+ len += plen;
+
+ nice_socket_send_reliable (priv->base_socket, NULL, len, msg);
+ priv->state = SOCKS_STATE_AUTH;
+ } else {
+ /* Authentication required but no auth info available */
+ goto error;
+ }
+ } else if (data[1] == 0x00) {
+ goto send_connect;
+ } else {
+ /* method not supported by socks server */
+ goto error;
+ }
+ } else {
+ /* invalid SOCKS server version */
+ goto error;
+ }
+ } else {
+ /* read error */
+ goto error;
+ }
+ }
+ break;
+ case SOCKS_STATE_AUTH:
+ {
+ guint8 data[2];
+ GInputVector local_recv_buf = { data, sizeof (data) };
+ NiceInputMessage local_recv_message = { &local_recv_buf, 1, NULL, 0 };
+
+ nice_debug ("Socks5 state auth");
+ if (priv->base_socket) {
+ ret = nice_socket_recv_messages (priv->base_socket,
+ &local_recv_message, 1);
+ }
+
+ if (ret <= 0) {
+ return ret;
+ } else if (ret == 1 && local_recv_buf.size == sizeof(data)) {
+ if (data[0] == 0x01 && data[1] == 0x00) {
+ /* Authenticated */
+ goto send_connect;
+ } else {
+ /* Authentication failed */
+ goto error;
+ }
+ }
+ }
+ break;
+ case SOCKS_STATE_CONNECT:
+ {
+ guint8 data[22];
+ GInputVector local_recv_buf = { data, sizeof (data) };
+ NiceInputMessage local_recv_message = { &local_recv_buf, 1, NULL, 0 };
+
+ nice_debug ("Socks5 state connect");
+ if (priv->base_socket) {
+ local_recv_buf.size = 4;
+ ret = nice_socket_recv_messages (priv->base_socket,
+ &local_recv_message, 1);
+ }
+
+ if (ret <= 0) {
+ return ret;
+ } else if (ret == 1 && local_recv_buf.size == 4) {
+ if (data[0] == 0x05) {
+ switch (data[1]) {
+ case 0x00:
+ if (data[2] == 0x00) {
+ switch (data[3]) {
+ case 0x01: /* IPV4 bound address */
+ local_recv_buf.size = 6;
+ ret = nice_socket_recv_messages (priv->base_socket,
+ &local_recv_message, 1);
+ if (ret != 1 || local_recv_buf.size != 6) {
+ /* Could not read server bound address */
+ goto error;
+ }
+ break;
+ case 0x04: /* IPV6 bound address */
+ local_recv_buf.size = 18;
+ ret = nice_socket_recv_messages (priv->base_socket,
+ &local_recv_message, 1);
+ if (ret != 1 || local_recv_buf.size != 18) {
+ /* Could not read server bound address */
+ goto error;
+ }
+ break;
+ default:
+ /* Unsupported address type */
+ goto error;
+ }
+ nice_socket_flush_send_queue (priv->base_socket,
+ &priv->send_queue);
+ priv->state = SOCKS_STATE_CONNECTED;
+ } else {
+ /* Wrong reserved value */
+ goto error;
+ }
+ break;
+ case 0x01: /* general SOCKS server failure */
+ case 0x02: /* connection not allowed by ruleset */
+ case 0x03: /* Network unreachable */
+ case 0x04: /* Host unreachable */
+ case 0x05: /* Connection refused */
+ case 0x06: /* TTL expired */
+ case 0x07: /* Command not supported */
+ case 0x08: /* Address type not supported */
+ default: /* Unknown error */
+ goto error;
+ break;
+ }
+ } else {
+ /* Wrong server version */
+ goto error;
+ }
+ } else {
+ /* Invalid data received */
+ goto error;
+ }
+ }
+ break;
+ case SOCKS_STATE_ERROR:
+ default:
+ /* Unknown status */
+ goto error;
+ }
+
+ return 0;
+
+ send_connect:
+ {
+ gchar msg[22];
+ gint len = 0;
+ union {
+ struct sockaddr_storage storage;
+ struct sockaddr addr;
+ struct sockaddr_in in;
+ struct sockaddr_in6 in6;
+ } name;
+ nice_address_copy_to_sockaddr(&priv->addr, &name.addr);
+
+ msg[len++] = 0x05; /* SOCKS version */
+ msg[len++] = 0x01; /* connect command */
+ msg[len++] = 0x00; /* reserved */
+ if (name.storage.ss_family == AF_INET) {
+ msg[len++] = 0x01; /* IPV4 address type */
+ /* Address */
+ memcpy (msg + len, &(&name.in)->sin_addr, 4);
+ len += 4;
+ /* Port */
+ memcpy (msg + len, &(&name.in)->sin_port, 2);
+ len += 2;
+ } else if (name.storage.ss_family == AF_INET6) {
+ msg[len++] = 0x04; /* IPV6 address type */
+ /* Address */
+ memcpy (msg + len, &(&name.in6)->sin6_addr, 16);
+ len += 16;
+ /* Port */
+ memcpy (msg + len, &(&name.in6)->sin6_port, 2);
+ len += 2;
+ }
+
+ nice_socket_send_reliable (priv->base_socket, NULL, len, msg);
+ priv->state = SOCKS_STATE_CONNECT;
+
+ return 0;
+ }
+ error:
+ nice_debug ("Socks5 error");
+ if (priv->base_socket)
+ nice_socket_free (priv->base_socket);
+ priv->base_socket = NULL;
+ priv->state = SOCKS_STATE_ERROR;
+
+ return -1;
+}
+
+static gint
+socket_send_messages (NiceSocket *sock, const NiceAddress *to,
+ const NiceOutputMessage *messages, guint n_messages)
+{
+ Socks5Priv *priv = sock->priv;
+
+ /* Make sure socket has not been freed: */
+ g_assert (sock->priv != NULL);
+
+ if (priv->state == SOCKS_STATE_CONNECTED) {
+ /* Fast path: pass through to the base socket once connected. */
+ if (priv->base_socket == NULL)
+ return -1;
+
+ return nice_socket_send_messages (priv->base_socket, to, messages,
+ n_messages);
+ } else if (priv->state == SOCKS_STATE_ERROR) {
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+
+static gint
+socket_send_messages_reliable (NiceSocket *sock, const NiceAddress *to,
+ const NiceOutputMessage *messages, guint n_messages)
+{
+ Socks5Priv *priv = sock->priv;
+
+ if (priv->state == SOCKS_STATE_CONNECTED) {
+ /* Fast path: pass through to the base socket once connected. */
+ if (priv->base_socket == NULL)
+ return -1;
+
+ return nice_socket_send_messages_reliable (priv->base_socket, to, messages,
+ n_messages);
+ } else if (priv->state == SOCKS_STATE_ERROR) {
+ return -1;
+ } else {
+ nice_socket_queue_send (&priv->send_queue, to, messages, n_messages);
+ }
+ return n_messages;
+}
+
+
+static gboolean
+socket_is_reliable (NiceSocket *sock)
+{
+ Socks5Priv *priv = sock->priv;
+
+ return nice_socket_is_reliable (priv->base_socket);
+}
+
+static gboolean
+socket_can_send (NiceSocket *sock, NiceAddress *addr)
+{
+ Socks5Priv *priv = sock->priv;
+
+ return nice_socket_can_send (priv->base_socket, addr);
+}
+
+static void
+socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data)
+{
+ Socks5Priv *priv = sock->priv;
+
+ nice_socket_set_writable_callback (priv->base_socket, callback, user_data);
+}
+
+static gboolean
+socket_is_based_on (NiceSocket *sock, NiceSocket *other)
+{
+ Socks5Priv *priv = sock->priv;
+
+ return (sock == other) ||
+ (priv && nice_socket_is_based_on (priv->base_socket, other));
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2008 Nokia Corporation. All rights reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef _SOCKS5_H
+#define _SOCKS5_H
+
+#include "socket.h"
+#include "agent.h"
+
+G_BEGIN_DECLS
+
+
+NiceSocket *
+nice_socks5_socket_new (NiceSocket *base_socket,
+ NiceAddress *addr, gchar *username, gchar *password);
+
+
+G_END_DECLS
+
+#endif /* _SOCKS5_H */
+
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2012 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2008-2009 Nokia Corporation. All rights reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ * George Kiagiadakis, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "socket.h"
+#include "tcp-active.h"
+
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#ifndef G_OS_WIN32
+#include <unistd.h>
+#endif
+
+/* FIXME: This should be defined in gio/gnetworking.h, which we should include;
+ * but we cannot do that without refactoring.
+ * (See: https://phabricator.freedesktop.org/D230). */
+#undef TCP_NODELAY
+#define TCP_NODELAY 1
+
+typedef struct {
+ GSocketAddress *local_addr;
+ GMainContext *context;
+} TcpActivePriv;
+
+
+static void socket_close (NiceSocket *sock);
+static gint socket_recv_messages (NiceSocket *sock,
+ NiceInputMessage *recv_messages, guint n_recv_messages);
+static gint socket_send_messages (NiceSocket *sock, const NiceAddress *to,
+ const NiceOutputMessage *messages, guint n_messages);
+static gint socket_send_messages_reliable (NiceSocket *sock,
+ const NiceAddress *to, const NiceOutputMessage *messages, guint n_messages);
+static gboolean socket_is_reliable (NiceSocket *sock);
+static gboolean socket_can_send (NiceSocket *sock, NiceAddress *addr);
+static void socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data);
+
+
+NiceSocket *
+nice_tcp_active_socket_new (GMainContext *ctx, NiceAddress *addr)
+{
+ union {
+ struct sockaddr_storage storage;
+ struct sockaddr addr;
+ } name;
+ NiceSocket *sock;
+ TcpActivePriv *priv;
+ GSocketAddress *gaddr;
+ NiceAddress local_addr;
+
+ if (addr != NULL) {
+
+ local_addr = *addr;
+ /* Make sure we don't bind to any local port */
+ nice_address_set_port (&local_addr, 0);
+ nice_address_copy_to_sockaddr(&local_addr, &name.addr);
+ } else {
+ memset (&local_addr, 0, sizeof (local_addr));
+ memset (&name, 0, sizeof (name));
+ name.storage.ss_family = AF_UNSPEC;
+ }
+
+ gaddr = g_socket_address_new_from_native (&name, sizeof (name));
+
+ if (gaddr == NULL) {
+ return NULL;
+ }
+
+ if (ctx == NULL) {
+ ctx = g_main_context_default ();
+ }
+
+ sock = g_slice_new0 (NiceSocket);
+
+ sock->priv = priv = g_slice_new0 (TcpActivePriv);
+
+ priv->context = g_main_context_ref (ctx);
+ priv->local_addr = gaddr;
+
+ sock->type = NICE_SOCKET_TYPE_TCP_ACTIVE;
+ sock->fileno = NULL;
+ sock->addr = local_addr;
+ sock->send_messages = socket_send_messages;
+ sock->send_messages_reliable = socket_send_messages_reliable;
+ sock->recv_messages = socket_recv_messages;
+ sock->is_reliable = socket_is_reliable;
+ sock->can_send = socket_can_send;
+ sock->set_writable_callback = socket_set_writable_callback;
+ sock->close = socket_close;
+
+ return sock;
+}
+
+static void
+socket_close (NiceSocket *sock)
+{
+ TcpActivePriv *priv = sock->priv;
+
+ if (priv->context)
+ g_main_context_unref (priv->context);
+ if (priv->local_addr)
+ g_object_unref (priv->local_addr);
+
+ g_slice_free(TcpActivePriv, sock->priv);
+}
+
+static gint socket_recv_messages (NiceSocket *sock,
+ NiceInputMessage *recv_messages, guint n_recv_messages)
+{
+ return -1;
+}
+
+static gint socket_send_messages (NiceSocket *sock, const NiceAddress *to,
+ const NiceOutputMessage *messages, guint n_messages)
+{
+ return -1;
+}
+
+static gint socket_send_messages_reliable (NiceSocket *sock,
+ const NiceAddress *to, const NiceOutputMessage *messages, guint n_messages)
+{
+ return -1;
+}
+
+static gboolean
+socket_is_reliable (NiceSocket *sock)
+{
+ return TRUE;
+}
+
+static gboolean
+socket_can_send (NiceSocket *sock, NiceAddress *addr)
+{
+ return FALSE;
+}
+
+static void
+socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data)
+{
+}
+
+NiceSocket *
+nice_tcp_active_socket_connect (NiceSocket *sock, NiceAddress *addr)
+{
+ union {
+ struct sockaddr_storage storage;
+ struct sockaddr addr;
+ } name;
+ TcpActivePriv *priv = sock->priv;
+ GSocket *gsock = NULL;
+ GError *gerr = NULL;
+ gboolean gret = FALSE;
+ GSocketAddress *gaddr;
+ NiceAddress local_addr;
+ NiceSocket *new_socket = NULL;
+
+ if (addr == NULL) {
+ /* We can't connect a tcp socket with no destination address */
+ return NULL;
+ }
+
+ nice_address_copy_to_sockaddr (addr, &name.addr);
+
+ if (name.storage.ss_family == AF_UNSPEC || name.storage.ss_family == AF_INET) {
+ gsock = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_STREAM,
+ G_SOCKET_PROTOCOL_TCP, NULL);
+
+ name.storage.ss_family = AF_INET;
+#ifdef HAVE_SA_LEN
+ name.storage.ss_len = sizeof (struct sockaddr_in);
+#endif
+ } else if (name.storage.ss_family == AF_INET6) {
+ gsock = g_socket_new (G_SOCKET_FAMILY_IPV6, G_SOCKET_TYPE_STREAM,
+ G_SOCKET_PROTOCOL_TCP, NULL);
+ name.storage.ss_family = AF_INET6;
+#ifdef HAVE_SA_LEN
+ name.storage.ss_len = sizeof (struct sockaddr_in6);
+#endif
+ }
+
+ if (gsock == NULL) {
+ return NULL;
+ }
+
+ gaddr = g_socket_address_new_from_native (&name.addr, sizeof (name));
+ if (gaddr == NULL) {
+ g_object_unref (gsock);
+ return NULL;
+ }
+
+ /* GSocket: All socket file descriptors are set to be close-on-exec. */
+ g_socket_set_blocking (gsock, false);
+
+ /* setting TCP_NODELAY to TRUE in order to avoid packet batching */
+ g_socket_set_option (gsock, IPPROTO_TCP, TCP_NODELAY, TRUE, NULL);
+
+ /* Allow g_socket_bind to fail */
+ g_socket_bind (gsock, priv->local_addr, FALSE, NULL);
+
+ gret = g_socket_connect (gsock, gaddr, NULL, &gerr);
+ g_object_unref (gaddr);
+
+ if (gret == FALSE) {
+ if (g_error_matches (gerr, G_IO_ERROR, G_IO_ERROR_PENDING) == FALSE) {
+ g_error_free (gerr);
+ g_socket_close (gsock, NULL);
+ g_object_unref (gsock);
+ return NULL;
+ }
+ g_error_free (gerr);
+ }
+
+ gaddr = g_socket_get_local_address (gsock, NULL);
+ if (gaddr == NULL ||
+ !g_socket_address_to_native (gaddr, &name.addr, sizeof (name), NULL)) {
+ g_socket_close (gsock, NULL);
+ g_object_unref (gsock);
+ return NULL;
+ }
+ g_object_unref (gaddr);
+
+ nice_address_set_from_sockaddr (&local_addr, &name.addr);
+
+ new_socket = nice_tcp_bsd_socket_new_from_gsock (priv->context, gsock,
+ &local_addr, addr, TRUE);
+ g_object_unref (gsock);
+
+ return new_socket;
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef _TCP_ACTIVE_H
+#define _TCP_ACTIVE_H
+
+#include "socket.h"
+
+G_BEGIN_DECLS
+
+
+NiceSocket * nice_tcp_active_socket_new (GMainContext *ctx, NiceAddress *addr);
+NiceSocket * nice_tcp_active_socket_connect (NiceSocket *socket, NiceAddress *addr);
+
+
+G_END_DECLS
+
+#endif /* _TCP_ACTIVE_H */
+
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2008-2009 Nokia Corporation. All rights reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+/*
+ * Implementation of TCP relay socket interface using TCP Berkeley sockets. (See
+ * http://en.wikipedia.org/wiki/Berkeley_sockets.)
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "tcp-bsd.h"
+#include "agent-priv.h"
+#include "socket-priv.h"
+
+#include "tcp-passive.h"
+
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#ifndef G_OS_WIN32
+#include <unistd.h>
+#endif
+
+/* FIXME: This should be defined in gio/gnetworking.h, which we should include;
+ * but we cannot do that without refactoring.
+ * (See: https://phabricator.freedesktop.org/D230). */
+#undef TCP_NODELAY
+#define TCP_NODELAY 1
+
+static GMutex mutex;
+
+typedef struct {
+ NiceAddress remote_addr;
+ GQueue send_queue;
+ GMainContext *context;
+ GSource *io_source;
+ gboolean error;
+ gboolean reliable;
+ NiceSocketWritableCb writable_cb;
+ gpointer writable_data;
+ NiceSocket *passive_parent;
+} TcpPriv;
+
+#define MAX_QUEUE_LENGTH 20
+
+static void socket_close (NiceSocket *sock);
+static gint socket_recv_messages (NiceSocket *sock,
+ NiceInputMessage *recv_messages, guint n_recv_messages);
+static gint socket_send_messages (NiceSocket *sock, const NiceAddress *to,
+ const NiceOutputMessage *messages, guint n_messages);
+static gint socket_send_messages_reliable (NiceSocket *sock,
+ const NiceAddress *to, const NiceOutputMessage *messages, guint n_messages);
+static gboolean socket_is_reliable (NiceSocket *sock);
+static gboolean socket_can_send (NiceSocket *sock, NiceAddress *addr);
+static void socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data);
+
+static gboolean socket_send_more (GSocket *gsocket, GIOCondition condition,
+ gpointer data);
+
+NiceSocket *
+nice_tcp_bsd_socket_new_from_gsock (GMainContext *ctx, GSocket *gsock,
+ NiceAddress *local_addr, NiceAddress *remote_addr, gboolean reliable)
+{
+ NiceSocket *sock;
+ TcpPriv *priv;
+
+ g_return_val_if_fail (G_IS_SOCKET (gsock), NULL);
+
+ sock = g_slice_new0 (NiceSocket);
+ sock->priv = priv = g_slice_new0 (TcpPriv);
+
+ if (ctx == NULL)
+ ctx = g_main_context_default ();
+ priv->context = g_main_context_ref (ctx);
+ priv->remote_addr = *remote_addr;
+ priv->error = FALSE;
+ priv->reliable = reliable;
+ priv->writable_cb = NULL;
+ priv->writable_data = NULL;
+
+ sock->type = NICE_SOCKET_TYPE_TCP_BSD;
+ sock->fileno = g_object_ref (gsock);
+ sock->addr = *local_addr;
+ sock->send_messages = socket_send_messages;
+ sock->send_messages_reliable = socket_send_messages_reliable;
+ sock->recv_messages = socket_recv_messages;
+ sock->is_reliable = socket_is_reliable;
+ sock->can_send = socket_can_send;
+ sock->set_writable_callback = socket_set_writable_callback;
+ sock->close = socket_close;
+
+ return sock;
+}
+
+NiceSocket *
+nice_tcp_bsd_socket_new (GMainContext *ctx, NiceAddress *local_addr,
+ NiceAddress *remote_addr, gboolean reliable)
+{
+ union {
+ struct sockaddr_storage storage;
+ struct sockaddr addr;
+ } name;
+ NiceSocket *sock;
+ GSocket *gsock = NULL;
+ GError *gerr = NULL;
+ gboolean gret = FALSE;
+ GSocketAddress *gaddr;
+
+ if (remote_addr == NULL) {
+ /* We can't connect a tcp socket with no destination address */
+ return NULL;
+ }
+
+ nice_address_copy_to_sockaddr (remote_addr, &name.addr);
+
+ if (name.storage.ss_family == AF_UNSPEC || name.storage.ss_family == AF_INET) {
+ gsock = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_STREAM,
+ G_SOCKET_PROTOCOL_TCP, NULL);
+
+ name.storage.ss_family = AF_INET;
+#ifdef HAVE_SA_LEN
+ name.storage.ss_len = sizeof (struct sockaddr_in);
+#endif
+ } else if (name.storage.ss_family == AF_INET6) {
+ gsock = g_socket_new (G_SOCKET_FAMILY_IPV6, G_SOCKET_TYPE_STREAM,
+ G_SOCKET_PROTOCOL_TCP, NULL);
+ name.storage.ss_family = AF_INET6;
+#ifdef HAVE_SA_LEN
+ name.storage.ss_len = sizeof (struct sockaddr_in6);
+#endif
+ }
+
+ if (gsock == NULL) {
+ return NULL;
+ }
+
+ gaddr = g_socket_address_new_from_native (&name.addr, sizeof (name));
+ if (gaddr == NULL) {
+ g_object_unref (gsock);
+ return NULL;
+ }
+
+ /* GSocket: All socket file descriptors are set to be close-on-exec. */
+ g_socket_set_blocking (gsock, false);
+
+ /* setting TCP_NODELAY to TRUE in order to avoid packet batching */
+ g_socket_set_option (gsock, IPPROTO_TCP, TCP_NODELAY, TRUE, NULL);
+
+ gret = g_socket_connect (gsock, gaddr, NULL, &gerr);
+ g_object_unref (gaddr);
+
+ if (gret == FALSE) {
+ if (g_error_matches (gerr, G_IO_ERROR, G_IO_ERROR_PENDING) == FALSE) {
+ g_error_free (gerr);
+ g_socket_close (gsock, NULL);
+ g_object_unref (gsock);
+ return NULL;
+ }
+ g_error_free (gerr);
+ }
+
+ nice_address_copy_to_sockaddr (local_addr, &name.addr);
+ gaddr = g_socket_address_new_from_native (&name.addr, sizeof (name));
+ if (gaddr == NULL) {
+ g_socket_close (gsock, NULL);
+ g_object_unref (gsock);
+ return NULL;
+ }
+ g_socket_bind (gsock, gaddr, FALSE, NULL);
+ g_object_unref (gaddr);
+
+ sock = nice_tcp_bsd_socket_new_from_gsock (ctx, gsock, local_addr, remote_addr,
+ reliable);
+ g_object_unref (gsock);
+
+ return sock;
+}
+
+
+static void
+socket_close (NiceSocket *sock)
+{
+ TcpPriv *priv = sock->priv;
+
+ g_mutex_lock (&mutex);
+
+ if (sock->fileno) {
+ g_socket_close (sock->fileno, NULL);
+ g_object_unref (sock->fileno);
+ sock->fileno = NULL;
+ }
+ if (priv->io_source) {
+ g_source_destroy (priv->io_source);
+ g_source_unref (priv->io_source);
+ }
+
+ if (priv->passive_parent) {
+ nice_tcp_passive_socket_remove_connection (priv->passive_parent, &priv->remote_addr);
+ }
+
+ nice_socket_free_send_queue (&priv->send_queue);
+
+ if (priv->context)
+ g_main_context_unref (priv->context);
+
+ g_mutex_unlock (&mutex);
+
+ g_slice_free(TcpPriv, sock->priv);
+}
+
+static gint
+socket_recv_messages (NiceSocket *sock,
+ NiceInputMessage *recv_messages, guint n_recv_messages)
+{
+ TcpPriv *priv = sock->priv;
+ guint i;
+
+ /* Make sure socket has not been freed: */
+ g_assert (sock->priv != NULL);
+
+ /* Don't try to access the socket if it had an error */
+ if (priv->error)
+ return -1;
+
+ for (i = 0; i < n_recv_messages; i++) {
+ gint flags = G_SOCKET_MSG_NONE;
+ GError *gerr = NULL;
+ gssize len;
+
+ len = g_socket_receive_message (sock->fileno, NULL,
+ recv_messages[i].buffers, recv_messages[i].n_buffers,
+ NULL, NULL, &flags, NULL, &gerr);
+
+ recv_messages[i].length = MAX (len, 0);
+
+ /* recv returns 0 when the peer performed a shutdown.. we must return -1
+ * here so that the agent destroys the g_source */
+ if (len == 0) {
+ priv->error = TRUE;
+ break;
+ }
+
+ if (len < 0) {
+ if (g_error_matches (gerr, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
+ len = 0;
+
+ g_error_free (gerr);
+ return len;
+ }
+
+ if (recv_messages[i].from)
+ *recv_messages[i].from = priv->remote_addr;
+ }
+
+ /* Was there an error processing the first message? */
+ if (priv->error && i == 0)
+ return -1;
+
+ return i;
+}
+
+static gssize
+socket_send_message (NiceSocket *sock,
+ const NiceOutputMessage *message, gboolean reliable)
+{
+ TcpPriv *priv = sock->priv;
+ gssize ret;
+ GError *gerr = NULL;
+ gsize message_len;
+
+ /* Make sure socket has not been freed: */
+ g_assert (sock->priv != NULL);
+
+ /* Don't try to access the socket if it had an error, otherwise we risk a
+ * crash with SIGPIPE (Broken pipe) */
+ if (priv->error)
+ return -1;
+
+ message_len = output_message_get_size (message);
+
+ /* First try to send the data, don't send it later if it can be sent now
+ * this way we avoid allocating memory on every send */
+ if (g_queue_is_empty (&priv->send_queue)) {
+ ret = g_socket_send_message (sock->fileno, NULL, message->buffers,
+ message->n_buffers, NULL, 0, G_SOCKET_MSG_NONE, NULL, &gerr);
+
+ if (ret < 0) {
+ if (g_error_matches (gerr, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK) ||
+ g_error_matches (gerr, G_IO_ERROR, G_IO_ERROR_FAILED)) {
+ /* Queue the message and send it later. */
+ nice_socket_queue_send_with_callback (&priv->send_queue,
+ message, 0, message_len, FALSE, sock->fileno, &priv->io_source,
+ priv->context, socket_send_more, sock);
+ ret = message_len;
+ }
+
+ g_error_free (gerr);
+ } else if ((gsize) ret < message_len) {
+ /* Partial send. */
+ nice_socket_queue_send_with_callback (&priv->send_queue,
+ message, ret, message_len, TRUE, sock->fileno, &priv->io_source,
+ priv->context, socket_send_more, sock);
+ ret = message_len;
+ }
+ } else {
+ /* Only queue if we're sending reliably */
+ if (reliable) {
+ /* Queue the message and send it later. */
+ nice_socket_queue_send_with_callback (&priv->send_queue,
+ message, 0, message_len, FALSE, sock->fileno, &priv->io_source,
+ priv->context, socket_send_more, sock);
+ ret = message_len;
+ } else {
+ /* non reliable send, so we shouldn't queue the message */
+ ret = 0;
+ }
+ }
+
+ return ret;
+}
+
+/* Data sent to this function must be a single entity because buffers can be
+ * dropped if the bandwidth isn't fast enough. So do not send a message in
+ * multiple chunks. */
+static gint
+socket_send_messages (NiceSocket *sock, const NiceAddress *to,
+ const NiceOutputMessage *messages, guint n_messages)
+{
+ guint i;
+
+ /* Make sure socket has not been freed: */
+ g_assert (sock->priv != NULL);
+
+ for (i = 0; i < n_messages; i++) {
+ const NiceOutputMessage *message = &messages[i];
+ gssize len;
+
+ len = socket_send_message (sock, message, FALSE);
+
+ if (len < 0) {
+ /* Error. */
+ if (i > 0)
+ break;
+ return len;
+ } else if (len == 0) {
+ /* EWOULDBLOCK. */
+ break;
+ }
+ }
+
+ return i;
+}
+
+static gint
+socket_send_messages_reliable (NiceSocket *sock, const NiceAddress *to,
+ const NiceOutputMessage *messages, guint n_messages)
+{
+ guint i;
+
+ for (i = 0; i < n_messages; i++) {
+ if (socket_send_message (sock, &messages[i], TRUE) < 0) {
+ /* Error. */
+ return -1;
+ }
+ }
+
+ return i;
+}
+
+static gboolean
+socket_is_reliable (NiceSocket *sock)
+{
+ TcpPriv *priv = sock->priv;
+
+ return priv->reliable;
+}
+
+static gboolean
+socket_can_send (NiceSocket *sock, NiceAddress *addr)
+{
+ TcpPriv *priv = sock->priv;
+
+ return g_queue_is_empty (&priv->send_queue);
+}
+
+static void
+socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data)
+{
+ TcpPriv *priv = sock->priv;
+
+ priv->writable_cb = callback;
+ priv->writable_data = user_data;
+}
+
+static gboolean
+socket_send_more (
+ GSocket *gsocket,
+ GIOCondition condition,
+ gpointer data)
+{
+ NiceSocket *sock = (NiceSocket *) data;
+ TcpPriv *priv = sock->priv;
+
+ g_mutex_lock (&mutex);
+
+ if (g_source_is_destroyed (g_main_current_source ())) {
+ nice_debug ("Source was destroyed. "
+ "Avoided race condition in tcp-bsd.c:socket_send_more");
+ g_mutex_unlock (&mutex);
+ return FALSE;
+ }
+
+ /* connection hangs up or queue was emptied */
+ if (condition & G_IO_HUP ||
+ nice_socket_flush_send_queue_to_socket (sock->fileno,
+ &priv->send_queue)) {
+ g_source_destroy (priv->io_source);
+ g_source_unref (priv->io_source);
+ priv->io_source = NULL;
+
+ g_mutex_unlock (&mutex);
+
+ if (priv->writable_cb)
+ priv->writable_cb (sock, priv->writable_data);
+
+ return FALSE;
+ }
+
+ g_mutex_unlock (&mutex);
+ return TRUE;
+}
+
+void
+nice_tcp_bsd_socket_set_passive_parent (NiceSocket *sock, NiceSocket *passive_parent)
+{
+ TcpPriv *priv = sock->priv;
+
+ g_assert (priv->passive_parent == NULL);
+
+ priv->passive_parent = passive_parent;
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2008-2009 Nokia Corporation. All rights reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef _TCP_BSD_H
+#define _TCP_BSD_H
+
+#include "socket.h"
+
+G_BEGIN_DECLS
+
+NiceSocket *
+nice_tcp_bsd_socket_new (GMainContext *ctx, NiceAddress *remote_addr,
+ NiceAddress *local_addr, gboolean reliable);
+
+NiceSocket *
+nice_tcp_bsd_socket_new_from_gsock (GMainContext *ctx, GSocket *gsock,
+ NiceAddress *remote_addr, NiceAddress *local_addr, gboolean reliable);
+
+void
+nice_tcp_bsd_socket_set_passive_parent (NiceSocket *socket, NiceSocket *passive_parent);
+
+G_END_DECLS
+
+#endif /* _TCP_BSD_H */
+
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2012 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2008-2009 Nokia Corporation. All rights reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ * George Kiagiadakis, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "tcp-passive.h"
+#include "agent-priv.h"
+
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#ifndef G_OS_WIN32
+#include <unistd.h>
+#endif
+
+/* FIXME: This should be defined in gio/gnetworking.h, which we should include;
+ * but we cannot do that without refactoring.
+ * (See: https://phabricator.freedesktop.org/D230). */
+#undef TCP_NODELAY
+#define TCP_NODELAY 1
+
+typedef struct {
+ GMainContext *context;
+ GHashTable *connections;
+ NiceSocketWritableCb writable_cb;
+ gpointer writable_data;
+} TcpPassivePriv;
+
+
+static void socket_close (NiceSocket *sock);
+static gint socket_recv_messages (NiceSocket *sock,
+ NiceInputMessage *recv_messages, guint n_recv_messages);
+static gint socket_send_messages (NiceSocket *sock, const NiceAddress *to,
+ const NiceOutputMessage *messages, guint n_messages);
+static gint socket_send_messages_reliable (NiceSocket *sock,
+ const NiceAddress *to, const NiceOutputMessage *messages, guint n_messages);
+static gboolean socket_is_reliable (NiceSocket *sock);
+static gboolean socket_can_send (NiceSocket *sock, NiceAddress *addr);
+static void socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data);
+
+static guint nice_address_hash (const NiceAddress * key);
+
+NiceSocket *
+nice_tcp_passive_socket_new (GMainContext *ctx, NiceAddress *addr)
+{
+ union {
+ struct sockaddr_storage storage;
+ struct sockaddr addr;
+ } name;
+ NiceSocket *sock;
+ TcpPassivePriv *priv;
+ GSocket *gsock = NULL;
+ gboolean gret = FALSE;
+ GSocketAddress *gaddr;
+
+ if (addr != NULL) {
+ nice_address_copy_to_sockaddr(addr, &name.addr);
+ } else {
+ memset (&name, 0, sizeof (name));
+ name.storage.ss_family = AF_UNSPEC;
+ }
+
+ if (name.storage.ss_family == AF_UNSPEC || name.storage.ss_family == AF_INET) {
+ gsock = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_STREAM,
+ G_SOCKET_PROTOCOL_TCP, NULL);
+
+ name.storage.ss_family = AF_INET;
+#ifdef HAVE_SA_LEN
+ name.storage.ss_len = sizeof (struct sockaddr_in);
+#endif
+ } else if (name.storage.ss_family == AF_INET6) {
+ gsock = g_socket_new (G_SOCKET_FAMILY_IPV6, G_SOCKET_TYPE_STREAM,
+ G_SOCKET_PROTOCOL_TCP, NULL);
+ name.storage.ss_family = AF_INET6;
+#ifdef HAVE_SA_LEN
+ name.storage.ss_len = sizeof (struct sockaddr_in6);
+#endif
+ }
+
+ if (gsock == NULL) {
+ return NULL;
+ }
+
+ gaddr = g_socket_address_new_from_native (&name.addr, sizeof (name));
+
+ if (gaddr == NULL) {
+ g_object_unref (gsock);
+ return NULL;
+ }
+
+ /* GSocket: All socket file descriptors are set to be close-on-exec. */
+ g_socket_set_blocking (gsock, false);
+
+ gret = g_socket_bind (gsock, gaddr, FALSE, NULL) &&
+ g_socket_listen (gsock, NULL);
+ g_object_unref (gaddr);
+
+ if (gret == FALSE) {
+ g_socket_close (gsock, NULL);
+ g_object_unref (gsock);
+ return NULL;
+ }
+
+ gaddr = g_socket_get_local_address (gsock, NULL);
+ if (gaddr == NULL ||
+ !g_socket_address_to_native (gaddr, &name.addr, sizeof (name), NULL)) {
+ g_socket_close (gsock, NULL);
+ g_object_unref (gsock);
+ return NULL;
+ }
+ g_object_unref (gaddr);
+
+ if (ctx == NULL) {
+ ctx = g_main_context_default ();
+ }
+
+ sock = g_slice_new0 (NiceSocket);
+
+ nice_address_set_from_sockaddr (&sock->addr, &name.addr);
+
+ sock->priv = priv = g_slice_new0 (TcpPassivePriv);
+ priv->context = g_main_context_ref (ctx);
+ priv->connections = g_hash_table_new_full ((GHashFunc) nice_address_hash,
+ (GEqualFunc) nice_address_equal, (
+ GDestroyNotify) nice_address_free, NULL);
+ priv->writable_cb = NULL;
+ priv->writable_data = NULL;
+
+ sock->type = NICE_SOCKET_TYPE_TCP_PASSIVE;
+ sock->fileno = gsock;
+ sock->send_messages = socket_send_messages;
+ sock->send_messages_reliable = socket_send_messages_reliable;
+ sock->recv_messages = socket_recv_messages;
+ sock->is_reliable = socket_is_reliable;
+ sock->can_send = socket_can_send;
+ sock->set_writable_callback = socket_set_writable_callback;
+ sock->close = socket_close;
+
+ return sock;
+}
+
+static void
+socket_close (NiceSocket *sock)
+{
+ TcpPassivePriv *priv = sock->priv;
+
+ if (sock->fileno != NULL) {
+ g_socket_close (sock->fileno, NULL);
+ g_object_unref (sock->fileno);
+ sock->fileno = NULL;
+ }
+
+ if (priv->context)
+ g_main_context_unref (priv->context);
+ g_hash_table_unref (priv->connections);
+
+ g_slice_free (TcpPassivePriv, sock->priv);
+}
+
+static gint socket_recv_messages (NiceSocket *sock,
+ NiceInputMessage *recv_messages, guint n_recv_messages)
+{
+ return -1;
+}
+
+static gint socket_send_messages (NiceSocket *sock, const NiceAddress *to,
+ const NiceOutputMessage *messages, guint n_messages)
+{
+ TcpPassivePriv *priv = sock->priv;
+
+ if (to) {
+ NiceSocket *peer_socket = g_hash_table_lookup (priv->connections, to);
+ if (peer_socket)
+ return nice_socket_send_messages (peer_socket, to, messages, n_messages);
+ }
+ return -1;
+}
+
+static gint socket_send_messages_reliable (NiceSocket *sock,
+ const NiceAddress *to, const NiceOutputMessage *messages, guint n_messages)
+{
+ TcpPassivePriv *priv = sock->priv;
+
+ if (to) {
+ NiceSocket *peer_socket = g_hash_table_lookup (priv->connections, to);
+ if (peer_socket)
+ return nice_socket_send_messages_reliable (peer_socket, to, messages,
+ n_messages);
+ }
+ return -1;
+}
+
+static gboolean
+socket_is_reliable (NiceSocket *sock)
+{
+ return TRUE;
+}
+
+static gboolean
+socket_can_send (NiceSocket *sock, NiceAddress *addr)
+{
+ TcpPassivePriv *priv = sock->priv;
+ NiceSocket *peer_socket = NULL;
+
+ /* FIXME: Danger if child socket was closed */
+ if (addr)
+ peer_socket = g_hash_table_lookup (priv->connections, addr);
+ if (peer_socket)
+ return nice_socket_can_send (peer_socket, addr);
+ return FALSE;
+}
+
+static void
+_child_writable_cb (NiceSocket *child, gpointer data)
+{
+ NiceSocket *sock = data;
+ TcpPassivePriv *priv = sock->priv;
+
+ if (priv->writable_cb)
+ priv->writable_cb (sock, priv->writable_data);
+}
+
+static void
+socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data)
+{
+ TcpPassivePriv *priv = sock->priv;
+
+ priv->writable_cb = callback;
+ priv->writable_data = user_data;
+}
+
+NiceSocket *
+nice_tcp_passive_socket_accept (NiceSocket *sock)
+{
+ union {
+ struct sockaddr_storage storage;
+ struct sockaddr addr;
+ } name;
+ TcpPassivePriv *priv = sock->priv;
+ GSocket *gsock = NULL;
+ GSocketAddress *gaddr;
+ NiceAddress remote_addr;
+ NiceSocket *new_socket = NULL;
+
+ gsock = g_socket_accept (sock->fileno, NULL, NULL);
+
+ if (gsock == NULL) {
+ return NULL;
+ }
+
+ /* GSocket: All socket file descriptors are set to be close-on-exec. */
+ g_socket_set_blocking (gsock, false);
+
+ /* setting TCP_NODELAY to TRUE in order to avoid packet batching */
+ g_socket_set_option (gsock, IPPROTO_TCP, TCP_NODELAY, TRUE, NULL);
+
+ gaddr = g_socket_get_remote_address (gsock, NULL);
+ if (gaddr == NULL ||
+ !g_socket_address_to_native (gaddr, &name.addr, sizeof (name), NULL)) {
+ g_socket_close (gsock, NULL);
+ g_object_unref (gsock);
+ return NULL;
+ }
+ g_object_unref (gaddr);
+
+ nice_address_set_from_sockaddr (&remote_addr, &name.addr);
+
+ new_socket = nice_tcp_bsd_socket_new_from_gsock (priv->context, gsock,
+ &sock->addr, &remote_addr, TRUE);
+ g_object_unref (gsock);
+
+ if (new_socket) {
+ NiceAddress *key = nice_address_dup (&remote_addr);
+
+ nice_tcp_bsd_socket_set_passive_parent (new_socket, sock);
+
+ nice_socket_set_writable_callback (new_socket, _child_writable_cb, sock);
+ g_hash_table_insert (priv->connections, key, new_socket);
+ }
+ return new_socket;
+}
+
+static guint nice_address_hash (const NiceAddress * key)
+{
+ gchar ip[INET6_ADDRSTRLEN];
+ gchar *str;
+ guint hash;
+
+ nice_address_to_string (key, ip);
+ str = g_strdup_printf ("%s:%u", ip, nice_address_get_port (key));
+ hash = g_str_hash (str);
+ g_free (str);
+
+ return hash;
+}
+
+void nice_tcp_passive_socket_remove_connection (NiceSocket *sock, const NiceAddress *to)
+{
+ TcpPassivePriv *priv = sock->priv;
+
+ g_hash_table_remove (priv->connections, to);
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2012 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2008-2009 Nokia Corporation. All rights reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ * George Kiagiadakis, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef _TCP_PASSIVE_H
+#define _TCP_PASSIVE_H
+
+#include "socket.h"
+
+G_BEGIN_DECLS
+
+
+NiceSocket * nice_tcp_passive_socket_new (GMainContext *ctx, NiceAddress *addr);
+NiceSocket * nice_tcp_passive_socket_accept (NiceSocket *socket);
+
+void nice_tcp_passive_socket_remove_connection (NiceSocket *socket,
+ const NiceAddress *to);
+
+
+G_END_DECLS
+
+#endif /* _TCP_PASSIVE_H */
+
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2006-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2006-2009 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Dafydd Harries, Collabora Ltd.
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+/*
+ * Implementation of UDP socket interface using Berkeley sockets. (See
+ * http://en.wikipedia.org/wiki/Berkeley_sockets.)
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include "udp-bsd.h"
+#include "agent-priv.h"
+
+#ifndef G_OS_WIN32
+#include <unistd.h>
+#endif
+
+
+static void socket_close (NiceSocket *sock);
+static gint socket_recv_messages (NiceSocket *sock,
+ NiceInputMessage *recv_messages, guint n_recv_messages);
+static gint socket_send_messages (NiceSocket *sock, const NiceAddress *to,
+ const NiceOutputMessage *messages, guint n_messages);
+static gint socket_send_messages_reliable (NiceSocket *sock,
+ const NiceAddress *to, const NiceOutputMessage *messages, guint n_messages);
+static gboolean socket_is_reliable (NiceSocket *sock);
+static gboolean socket_can_send (NiceSocket *sock, NiceAddress *addr);
+static void socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data);
+
+struct UdpBsdSocketPrivate
+{
+ GMutex mutex;
+
+ /* protected by mutex */
+ NiceAddress niceaddr;
+ GSocketAddress *gaddr;
+};
+
+NiceSocket *
+nice_udp_bsd_socket_new (NiceAddress *addr)
+{
+ union {
+ struct sockaddr_storage storage;
+ struct sockaddr addr;
+ } name;
+ NiceSocket *sock = g_slice_new0 (NiceSocket);
+ GSocket *gsock = NULL;
+ gboolean gret = FALSE;
+ GSocketAddress *gaddr;
+ struct UdpBsdSocketPrivate *priv;
+
+ if (addr != NULL) {
+ nice_address_copy_to_sockaddr(addr, &name.addr);
+ } else {
+ memset (&name, 0, sizeof (name));
+ name.storage.ss_family = AF_UNSPEC;
+ }
+
+ if (name.storage.ss_family == AF_UNSPEC || name.storage.ss_family == AF_INET) {
+ gsock = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM,
+ G_SOCKET_PROTOCOL_UDP, NULL);
+ name.storage.ss_family = AF_INET;
+#ifdef HAVE_SA_LEN
+ name.storage.ss_len = sizeof (struct sockaddr_in);
+#endif
+ } else if (name.storage.ss_family == AF_INET6) {
+ gsock = g_socket_new (G_SOCKET_FAMILY_IPV6, G_SOCKET_TYPE_DATAGRAM,
+ G_SOCKET_PROTOCOL_UDP, NULL);
+ name.storage.ss_family = AF_INET6;
+#ifdef HAVE_SA_LEN
+ name.storage.ss_len = sizeof (struct sockaddr_in6);
+#endif
+ }
+
+ if (gsock == NULL) {
+ g_slice_free (NiceSocket, sock);
+ return NULL;
+ }
+
+ /* GSocket: All socket file descriptors are set to be close-on-exec. */
+ g_socket_set_blocking (gsock, false);
+ gaddr = g_socket_address_new_from_native (&name.addr, sizeof (name));
+ if (gaddr != NULL) {
+ gret = g_socket_bind (gsock, gaddr, FALSE, NULL);
+ g_object_unref (gaddr);
+ }
+
+ if (gret == FALSE) {
+ g_slice_free (NiceSocket, sock);
+ g_socket_close (gsock, NULL);
+ g_object_unref (gsock);
+ return NULL;
+ }
+
+ gaddr = g_socket_get_local_address (gsock, NULL);
+ if (gaddr == NULL ||
+ !g_socket_address_to_native (gaddr, &name.addr, sizeof(name), NULL)) {
+ g_slice_free (NiceSocket, sock);
+ g_socket_close (gsock, NULL);
+ g_object_unref (gsock);
+ return NULL;
+ }
+
+ g_object_unref (gaddr);
+
+ nice_address_set_from_sockaddr (&sock->addr, &name.addr);
+
+ priv = sock->priv = g_slice_new0 (struct UdpBsdSocketPrivate);
+ nice_address_init (&priv->niceaddr);
+
+ sock->type = NICE_SOCKET_TYPE_UDP_BSD;
+ sock->fileno = gsock;
+ sock->send_messages = socket_send_messages;
+ sock->send_messages_reliable = socket_send_messages_reliable;
+ sock->recv_messages = socket_recv_messages;
+ sock->is_reliable = socket_is_reliable;
+ sock->can_send = socket_can_send;
+ sock->set_writable_callback = socket_set_writable_callback;
+ sock->close = socket_close;
+
+ g_mutex_init (&priv->mutex);
+
+ return sock;
+}
+
+static void
+socket_close (NiceSocket *sock)
+{
+ struct UdpBsdSocketPrivate *priv = sock->priv;
+
+ g_clear_object (&priv->gaddr);
+ g_mutex_clear (&priv->mutex);
+ g_slice_free (struct UdpBsdSocketPrivate, sock->priv);
+ sock->priv = NULL;
+
+ if (sock->fileno) {
+ g_socket_close (sock->fileno, NULL);
+ g_object_unref (sock->fileno);
+ sock->fileno = NULL;
+ }
+}
+
+static gint
+socket_recv_messages (NiceSocket *sock,
+ NiceInputMessage *recv_messages, guint n_recv_messages)
+{
+ guint i;
+ gboolean error = FALSE;
+
+ /* Make sure socket has not been freed: */
+ g_assert (sock->priv != NULL);
+
+ /* Read messages into recv_messages until one fails or would block, or we
+ * reach the end. */
+ for (i = 0; i < n_recv_messages; i++) {
+ NiceInputMessage *recv_message = &recv_messages[i];
+ GSocketAddress *gaddr = NULL;
+ GError *gerr = NULL;
+ gssize recvd;
+ gint flags = G_SOCKET_MSG_NONE;
+
+ recvd = g_socket_receive_message (sock->fileno,
+ (recv_message->from != NULL) ? &gaddr : NULL,
+ recv_message->buffers, recv_message->n_buffers, NULL, NULL,
+ &flags, NULL, &gerr);
+
+ if (recvd < 0) {
+ /* Handle ECONNRESET here as if it were EWOULDBLOCK; see
+ * https://phabricator.freedesktop.org/T121 */
+ if (g_error_matches (gerr, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK) ||
+ g_error_matches (gerr, G_IO_ERROR, G_IO_ERROR_CONNECTION_CLOSED))
+ recvd = 0;
+ else if (g_error_matches (gerr, G_IO_ERROR, G_IO_ERROR_MESSAGE_TOO_LARGE))
+ recvd = input_message_get_size (recv_message);
+ else
+ error = TRUE;
+
+ g_error_free (gerr);
+ }
+
+ recv_message->length = MAX (recvd, 0);
+
+ if (recvd > 0 && recv_message->from != NULL && gaddr != NULL) {
+ union {
+ struct sockaddr_storage storage;
+ struct sockaddr addr;
+ } sa;
+
+ g_socket_address_to_native (gaddr, &sa.addr, sizeof (sa), NULL);
+ nice_address_set_from_sockaddr (recv_message->from, &sa.addr);
+ }
+
+ if (gaddr != NULL)
+ g_object_unref (gaddr);
+
+ /* Return early on error or EWOULDBLOCK. */
+ if (recvd <= 0)
+ break;
+ }
+
+ /* Was there an error processing the first message? */
+ if (error && i == 0)
+ return -1;
+
+ return i;
+}
+
+static gssize
+socket_send_message (NiceSocket *sock, const NiceAddress *to,
+ const NiceOutputMessage *message)
+{
+ struct UdpBsdSocketPrivate *priv = sock->priv;
+ GError *child_error = NULL;
+ gssize len;
+ GSocketAddress *gaddr = NULL;
+
+ /* Make sure socket has not been freed: */
+ g_assert (sock->priv != NULL);
+
+ g_mutex_lock (&priv->mutex);
+ if (!nice_address_is_valid (&priv->niceaddr) ||
+ !nice_address_equal (&priv->niceaddr, to)) {
+ union {
+ struct sockaddr_storage storage;
+ struct sockaddr addr;
+ } sa;
+
+ g_clear_object (&priv->gaddr);
+
+ nice_address_copy_to_sockaddr (to, &sa.addr);
+ gaddr = g_socket_address_new_from_native (&sa.addr, sizeof(sa));
+ if (gaddr)
+ priv->gaddr = g_object_ref (gaddr);
+
+ if (gaddr == NULL) {
+ g_mutex_unlock (&priv->mutex);
+ return -1;
+ }
+
+ priv->niceaddr = *to;
+ } else {
+ if (priv->gaddr)
+ gaddr = g_object_ref (priv->gaddr);
+ }
+ g_mutex_unlock (&priv->mutex);
+
+ len = g_socket_send_message (sock->fileno, gaddr, message->buffers,
+ message->n_buffers, NULL, 0, G_SOCKET_MSG_NONE, NULL, &child_error);
+
+ g_clear_object (&gaddr);
+
+ if (len < 0) {
+ if (g_error_matches (child_error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
+ len = 0;
+ } else {
+ nice_debug_verbose ("%s: udp-bsd socket %p: error: %s", G_STRFUNC, sock,
+ child_error->message);
+ }
+
+ g_error_free (child_error);
+ }
+
+ return len;
+}
+
+static gint
+socket_send_messages (NiceSocket *sock, const NiceAddress *to,
+ const NiceOutputMessage *messages, guint n_messages)
+{
+ guint i;
+
+ /* Make sure socket has not been freed: */
+ g_assert (sock->priv != NULL);
+
+ for (i = 0; i < n_messages; i++) {
+ const NiceOutputMessage *message = &messages[i];
+ gssize len;
+
+ len = socket_send_message (sock, to, message);
+
+ if (len < 0) {
+ /* Error. */
+ if (i > 0)
+ break;
+ return len;
+ } else if (len == 0) {
+ /* EWOULDBLOCK. */
+ break;
+ }
+ }
+
+ return i;
+}
+
+static gint
+socket_send_messages_reliable (NiceSocket *sock, const NiceAddress *to,
+ const NiceOutputMessage *messages, guint n_messages)
+{
+ return -1;
+}
+
+static gboolean
+socket_is_reliable (NiceSocket *sock)
+{
+ return FALSE;
+}
+
+static gboolean
+socket_can_send (NiceSocket *sock, NiceAddress *addr)
+{
+ return TRUE;
+}
+
+static void
+socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data)
+{
+}
+
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2006-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2006-2009 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Dafydd Harries, Collabora Ltd.
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef _UDP_BSD_H
+#define _UDP_BSD_H
+
+#include "socket.h"
+
+G_BEGIN_DECLS
+
+NiceSocket *
+nice_udp_bsd_socket_new (NiceAddress *addr);
+
+G_END_DECLS
+
+#endif /* _UDP_BSD_H */
+
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2008-2009 Nokia Corporation. All rights reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+/*
+ * Implementation of TCP relay socket interface using TCP Berkeley sockets. (See
+ * http://en.wikipedia.org/wiki/Berkeley_sockets.)
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "udp-turn-over-tcp.h"
+#include "agent-priv.h"
+
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#ifndef G_OS_WIN32
+#include <unistd.h>
+#endif
+
+typedef struct {
+ NiceTurnSocketCompatibility compatibility;
+ union {
+ guint8 u8[65536];
+ guint16 u16[32768];
+ } recv_buf;
+ gsize recv_buf_len; /* in bytes */
+ guint expecting_len;
+ NiceSocket *base_socket;
+} TurnTcpPriv;
+
+typedef enum {
+ MS_TURN_CONTROL_MESSAGE = 2,
+ MS_TURN_END_TO_END_DATA = 3
+} MsTurnPayloadType;
+
+#define MAX_UDP_MESSAGE_SIZE 65535
+
+#define MAGIC_COOKIE_OFFSET \
+ STUN_MESSAGE_HEADER_LENGTH + STUN_MESSAGE_TYPE_LEN + \
+ STUN_MESSAGE_LENGTH_LEN + sizeof(guint16)
+
+static void socket_close (NiceSocket *sock);
+static gint socket_recv_messages (NiceSocket *sock,
+ NiceInputMessage *recv_messages, guint n_recv_messages);
+static gint socket_send_messages (NiceSocket *sock, const NiceAddress *to,
+ const NiceOutputMessage *messages, guint n_messages);
+static gint socket_send_messages_reliable (NiceSocket *sock,
+ const NiceAddress *to, const NiceOutputMessage *messages, guint n_messages);
+static gboolean socket_is_reliable (NiceSocket *sock);
+static gboolean socket_can_send (NiceSocket *sock, NiceAddress *addr);
+static void socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data);
+static gboolean socket_is_based_on (NiceSocket *sock, NiceSocket *other);
+
+NiceSocket *
+nice_udp_turn_over_tcp_socket_new (NiceSocket *base_socket,
+ NiceTurnSocketCompatibility compatibility)
+{
+ TurnTcpPriv *priv;
+ NiceSocket *sock = g_slice_new0 (NiceSocket);
+ sock->priv = priv = g_slice_new0 (TurnTcpPriv);
+
+ priv->compatibility = compatibility;
+ priv->base_socket = base_socket;
+
+ sock->type = NICE_SOCKET_TYPE_UDP_TURN_OVER_TCP;
+ sock->fileno = priv->base_socket->fileno;
+ sock->addr = priv->base_socket->addr;
+ sock->send_messages = socket_send_messages;
+ sock->send_messages_reliable = socket_send_messages_reliable;
+ sock->recv_messages = socket_recv_messages;
+ sock->is_reliable = socket_is_reliable;
+ sock->can_send = socket_can_send;
+ sock->set_writable_callback = socket_set_writable_callback;
+ sock->is_based_on = socket_is_based_on;
+ sock->close = socket_close;
+
+ return sock;
+}
+
+
+static void
+socket_close (NiceSocket *sock)
+{
+ TurnTcpPriv *priv = sock->priv;
+
+ if (priv->base_socket)
+ nice_socket_free (priv->base_socket);
+
+ g_slice_free(TurnTcpPriv, sock->priv);
+ sock->priv = NULL;
+}
+
+static gssize
+socket_recv_message (NiceSocket *sock, NiceInputMessage *recv_message)
+{
+ TurnTcpPriv *priv = sock->priv;
+ gssize ret;
+ guint padlen;
+ GInputVector local_recv_buf;
+ NiceInputMessage local_recv_message;
+
+ /* Make sure socket has not been freed: */
+ g_assert (sock->priv != NULL);
+
+ if (priv->expecting_len == 0) {
+ guint headerlen = 0;
+
+ if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 ||
+ priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766 ||
+ priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_OC2007)
+ headerlen = 4;
+ else if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE)
+ headerlen = 2;
+ else
+ return -1;
+
+ local_recv_buf.buffer = priv->recv_buf.u8 + priv->recv_buf_len;
+ local_recv_buf.size = headerlen - priv->recv_buf_len;
+ local_recv_message.buffers = &local_recv_buf;
+ local_recv_message.n_buffers = 1;
+ local_recv_message.from = recv_message->from;
+ local_recv_message.length = 0;
+
+ ret = nice_socket_recv_messages (priv->base_socket, &local_recv_message, 1);
+ if (ret < 0)
+ return ret;
+
+ priv->recv_buf_len += local_recv_message.length;
+
+ if (priv->recv_buf_len < headerlen)
+ return 0;
+
+ if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 ||
+ priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766) {
+ guint16 magic = ntohs (*priv->recv_buf.u16);
+ guint16 packetlen = ntohs (*(priv->recv_buf.u16 + 1));
+
+ if (magic < 0x4000) {
+ /* Its STUN */
+ priv->expecting_len = 20 + packetlen;
+ } else {
+ /* Channel data */
+ priv->expecting_len = 4 + packetlen;
+ }
+ }
+ else if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE) {
+ guint compat_len = ntohs (*priv->recv_buf.u16);
+ priv->expecting_len = compat_len;
+ priv->recv_buf_len = 0;
+ }
+ else if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_OC2007) {
+ guint8 pt = *priv->recv_buf.u8;
+ guint16 packetlen = ntohs (priv->recv_buf.u16[1]);
+
+ if (pt != MS_TURN_CONTROL_MESSAGE &&
+ pt != MS_TURN_END_TO_END_DATA) {
+ /* Unexpected data, error in stream */
+ return -1;
+ }
+
+ /* Keep the RFC4571 framing for the NiceAgent to unframe */
+ priv->expecting_len = packetlen + sizeof(guint16);
+ priv->recv_buf_len = sizeof(guint16);
+ priv->recv_buf.u16[0] = priv->recv_buf.u16[1];
+ }
+ }
+
+ if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 ||
+ priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766)
+ padlen = (priv->expecting_len % 4) ? 4 - (priv->expecting_len % 4) : 0;
+ else
+ padlen = 0;
+
+ local_recv_buf.buffer = priv->recv_buf.u8 + priv->recv_buf_len;
+ local_recv_buf.size = priv->expecting_len + padlen - priv->recv_buf_len;
+ local_recv_message.buffers = &local_recv_buf;
+ local_recv_message.n_buffers = 1;
+ local_recv_message.from = recv_message->from;
+ local_recv_message.length = 0;
+
+ ret = nice_socket_recv_messages (priv->base_socket, &local_recv_message, 1);
+ if (ret < 0)
+ return ret;
+
+ priv->recv_buf_len += local_recv_message.length;
+
+ if (priv->recv_buf_len == priv->expecting_len + padlen) {
+ /* FIXME: Eliminate this memcpy(). */
+ ret = memcpy_buffer_to_input_message (recv_message,
+ priv->recv_buf.u8, priv->recv_buf_len);
+
+ priv->expecting_len = 0;
+ priv->recv_buf_len = 0;
+
+ return ret;
+ }
+
+ return 0;
+}
+
+static gint
+socket_recv_messages (NiceSocket *nicesock,
+ NiceInputMessage *recv_messages, guint n_recv_messages)
+{
+ guint i;
+ gboolean error = FALSE;
+
+ /* Make sure socket has not been freed: */
+ g_assert (nicesock->priv != NULL);
+
+ for (i = 0; i < n_recv_messages; i++) {
+ gssize len;
+
+ len = socket_recv_message (nicesock, &recv_messages[i]);
+ recv_messages[i].length = MAX (len, 0);
+
+ if (len < 0)
+ error = TRUE;
+
+ if (len <= 0)
+ break;
+ }
+
+ /* Was there an error processing the first message? */
+ if (error && i == 0)
+ return -1;
+
+ return i;
+}
+
+static gssize
+socket_send_message (NiceSocket *sock, const NiceAddress *to,
+ const NiceOutputMessage *message, gboolean reliable)
+{
+ TurnTcpPriv *priv = sock->priv;
+ guint8 padbuf[3] = {0, 0, 0};
+ GOutputVector *local_bufs;
+ NiceOutputMessage local_message;
+ guint j;
+ gint ret;
+ guint n_bufs;
+ union {
+ guint16 google_len;
+ struct {
+ guint8 pt;
+ guint8 zero;
+ } msoc;
+ } header_buf;
+ guint offset = 0;
+
+ /* Make sure socket has not been freed: */
+ g_assert (sock->priv != NULL);
+
+ /* Count the number of buffers. */
+ if (message->n_buffers == -1) {
+ n_bufs = 0;
+
+ for (j = 0; message->buffers[j].buffer != NULL; j++)
+ n_bufs++;
+ } else {
+ n_bufs = message->n_buffers;
+ }
+
+ /* Allocate a new array of buffers, covering all the buffers in the input
+ * @message, but with an additional one for a header and one for a footer. */
+ local_bufs = g_alloca ((n_bufs + 1) * sizeof (GOutputVector));
+ local_message.buffers = local_bufs;
+ local_message.n_buffers = n_bufs + 1;
+
+ if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE) {
+ header_buf.google_len = htons (output_message_get_size (message));
+ local_bufs[0].buffer = &header_buf;
+ local_bufs[0].size = sizeof (guint16);
+ offset = 1;
+ } else if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 ||
+ priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766) {
+ gsize message_len = output_message_get_size (message);
+ gsize padlen = (message_len % 4) ? 4 - (message_len % 4) : 0;
+
+ local_bufs[n_bufs].buffer = &padbuf;
+ local_bufs[n_bufs].size = padlen;
+ } else if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_OC2007) {
+ union {
+ guint32 u32;
+ guint8 u8[4];
+ } cookie;
+ guint16 len = output_message_get_size (message);
+
+ /* Copy the cookie from possibly split messages */
+ cookie.u32 = 0;
+ if (len > sizeof (TURN_MAGIC_COOKIE) + MAGIC_COOKIE_OFFSET) {
+ guint16 buf_offset = 0;
+ guint i;
+
+ for (i = 0; i < n_bufs; i++) {
+ if (message->buffers[i].size >
+ (gsize) (MAGIC_COOKIE_OFFSET - buf_offset)) {
+ /* If the cookie is split, we assume it's data */
+ if (message->buffers[i].size > sizeof (TURN_MAGIC_COOKIE) +
+ MAGIC_COOKIE_OFFSET - buf_offset) {
+ const guint8 *buf = message->buffers[i].buffer;
+ memcpy (&cookie.u8, buf + MAGIC_COOKIE_OFFSET - buf_offset,
+ sizeof (TURN_MAGIC_COOKIE));
+ }
+ break;
+ } else {
+ buf_offset += message->buffers[i].size;
+ }
+ }
+ }
+
+ cookie.u32 = ntohl(cookie.u32);
+ header_buf.msoc.zero = 0;
+ if (cookie.u32 == TURN_MAGIC_COOKIE)
+ header_buf.msoc.pt = MS_TURN_CONTROL_MESSAGE;
+ else
+ header_buf.msoc.pt = MS_TURN_END_TO_END_DATA;
+
+ local_bufs[0].buffer = &header_buf;
+ local_bufs[0].size = sizeof(header_buf.msoc);
+ offset = 1;
+ } else {
+ local_message.n_buffers = n_bufs;
+ }
+
+ /* Copy the existing buffers across. */
+ for (j = 0; j < n_bufs; j++) {
+ local_bufs[j + offset].buffer = message->buffers[j].buffer;
+ local_bufs[j + offset].size = message->buffers[j].size;
+ }
+
+
+ if (reliable)
+ ret = nice_socket_send_messages_reliable (priv->base_socket, to,
+ &local_message, 1);
+ else
+ ret = nice_socket_send_messages (priv->base_socket, to, &local_message, 1);
+
+ if (ret == 1)
+ ret = output_message_get_size (&local_message);
+
+ return ret;
+}
+
+static gint
+socket_send_messages (NiceSocket *sock, const NiceAddress *to,
+ const NiceOutputMessage *messages, guint n_messages)
+{
+ guint i;
+
+ /* Make sure socket has not been freed: */
+ g_assert (sock->priv != NULL);
+
+ for (i = 0; i < n_messages; i++) {
+ const NiceOutputMessage *message = &messages[i];
+ gssize len;
+
+ len = socket_send_message (sock, to, message, FALSE);
+
+ if (len < 0) {
+ /* Error. */
+ if (i > 0)
+ break;
+ return len;
+ } else if (len == 0) {
+ /* EWOULDBLOCK. */
+ break;
+ }
+ }
+
+ return i;
+}
+
+static gint
+socket_send_messages_reliable (NiceSocket *sock, const NiceAddress *to,
+ const NiceOutputMessage *messages, guint n_messages)
+{
+ guint i;
+
+ for (i = 0; i < n_messages; i++) {
+ const NiceOutputMessage *message = &messages[i];
+ gssize len;
+
+ len = socket_send_message (sock, to, message, TRUE);
+
+ if (len < 0) {
+ /* Error. */
+ return len;
+ }
+ }
+
+ return i;
+}
+
+
+static gboolean
+socket_is_reliable (NiceSocket *sock)
+{
+ TurnTcpPriv *priv = sock->priv;
+
+ return nice_socket_is_reliable (priv->base_socket);
+}
+
+static gboolean
+socket_can_send (NiceSocket *sock, NiceAddress *addr)
+{
+ TurnTcpPriv *priv = sock->priv;
+
+ return nice_socket_can_send (priv->base_socket, addr);
+}
+
+static void
+socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data)
+{
+ TurnTcpPriv *priv = sock->priv;
+
+ nice_socket_set_writable_callback (priv->base_socket, callback, user_data);
+}
+
+static gboolean
+socket_is_based_on (NiceSocket *sock, NiceSocket *other)
+{
+ TurnTcpPriv *priv = sock->priv;
+
+ return (sock == other) ||
+ (priv && nice_socket_is_based_on (priv->base_socket, other));
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2008-2009 Nokia Corporation. All rights reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef _UDP_TURN_OVER_TCP_H
+#define _UDP_TURN_OVER_TCP_H
+
+#include "socket.h"
+#include "agent.h"
+
+G_BEGIN_DECLS
+
+
+NiceSocket *
+nice_udp_turn_over_tcp_socket_new (NiceSocket *base_socket,
+ NiceTurnSocketCompatibility compatibility);
+
+
+G_END_DECLS
+
+#endif /* _UDP_TURN_OVER_TCP_H */
+
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2008 Nokia Corporation
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+/*
+ * Implementation of TURN
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+
+#include "udp-turn.h"
+#include "stun/stunagent.h"
+#include "stun/usages/timer.h"
+#include "agent-priv.h"
+
+#define STUN_END_TIMEOUT 8000
+#define STUN_MAX_MS_REALM_LEN 128 // as defined in [MS-TURN]
+#define STUN_EXPIRE_TIMEOUT 60 /* Time we refresh before expiration */
+#define STUN_PERMISSION_TIMEOUT (300 - STUN_EXPIRE_TIMEOUT) /* 240 s */
+#define STUN_BINDING_TIMEOUT (600 - STUN_EXPIRE_TIMEOUT) /* 540 s */
+
+static GMutex mutex;
+
+typedef struct {
+ StunMessage message;
+ uint8_t buffer[STUN_MAX_MESSAGE_SIZE];
+ StunTimer timer;
+} TURNMessage;
+
+typedef struct {
+ NiceAddress peer;
+ uint16_t channel;
+ gboolean renew;
+ GSource *timeout_source;
+} ChannelBinding;
+
+typedef struct {
+ GMainContext *ctx;
+ StunAgent agent;
+ GList *channels;
+ GList *pending_bindings;
+ ChannelBinding *current_binding;
+ TURNMessage *current_binding_msg;
+ GList *pending_permissions;
+ GSource *tick_source_channel_bind;
+ GSource *tick_source_create_permission;
+ NiceSocket *base_socket;
+ NiceAddress server_addr;
+ uint8_t *username;
+ gsize username_len;
+ uint8_t *password;
+ gsize password_len;
+ NiceTurnSocketCompatibility compatibility;
+ GQueue *send_requests;
+ uint8_t ms_realm[STUN_MAX_MS_REALM_LEN + 1];
+ uint8_t ms_connection_id[20];
+ uint32_t ms_sequence_num;
+ bool ms_connection_id_valid;
+ GList *permissions; /* the peers (NiceAddress) for which
+ there is an installed permission */
+ GList *sent_permissions; /* ongoing permission installed */
+ GHashTable *send_data_queues; /* stores a send data queue for per peer */
+ GSource *permission_timeout_source; /* timer used to invalidate
+ permissions */
+
+ guint8 *cached_realm;
+ uint16_t cached_realm_len;
+ guint8 *cached_nonce;
+ uint16_t cached_nonce_len;
+
+ GByteArray *fragment_buffer;
+ NiceAddress from;
+} UdpTurnPriv;
+
+
+typedef struct {
+ StunTransactionId id;
+ GSource *source;
+ UdpTurnPriv *priv;
+} SendRequest;
+
+/* used to store data sent while obtaining a permission */
+typedef struct {
+ gchar *data;
+ guint data_len;
+ gboolean reliable;
+} SendData;
+
+static void socket_close (NiceSocket *sock);
+static gint socket_recv_messages (NiceSocket *sock,
+ NiceInputMessage *recv_messages, guint n_recv_messages);
+static gint socket_send_messages (NiceSocket *sock, const NiceAddress *to,
+ const NiceOutputMessage *messages, guint n_messages);
+static gint socket_send_messages_reliable (NiceSocket *sock,
+ const NiceAddress *to, const NiceOutputMessage *messages, guint n_messages);
+static gboolean socket_is_reliable (NiceSocket *sock);
+static gboolean socket_can_send (NiceSocket *sock, NiceAddress *addr);
+static void socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data);
+static gboolean socket_is_based_on (NiceSocket *sock, NiceSocket *other);
+
+static void priv_process_pending_bindings (UdpTurnPriv *priv);
+static gboolean priv_retransmissions_tick_unlocked (UdpTurnPriv *priv);
+static gboolean priv_retransmissions_tick (gpointer pointer);
+static void priv_schedule_tick (UdpTurnPriv *priv);
+static void priv_send_turn_message (UdpTurnPriv *priv, TURNMessage *msg);
+static gboolean priv_send_create_permission (UdpTurnPriv *priv,
+ const NiceAddress *peer);
+static gboolean priv_send_channel_bind (UdpTurnPriv *priv,
+ uint16_t channel,
+ const NiceAddress *peer);
+static gboolean priv_add_channel_binding (UdpTurnPriv *priv,
+ const NiceAddress *peer);
+static gboolean priv_forget_send_request_timeout (gpointer pointer);
+static void priv_clear_permissions (UdpTurnPriv *priv);
+
+static void
+send_request_free (SendRequest *r)
+{
+ g_source_destroy (r->source);
+ g_source_unref (r->source);
+
+ stun_agent_forget_transaction (&r->priv->agent, r->id);
+
+ g_slice_free (SendRequest, r);
+}
+
+static guint
+priv_nice_address_hash (gconstpointer data)
+{
+ gchar address[NICE_ADDRESS_STRING_LEN];
+
+ nice_address_to_string ((NiceAddress *) data, address);
+
+ return g_str_hash(address);
+}
+
+static void
+priv_send_data_queue_destroy (gpointer user_data)
+{
+ GQueue *send_queue = (GQueue *) user_data;
+ GList *i;
+
+ for (i = g_queue_peek_head_link (send_queue); i; i = i->next) {
+ SendData *data = (SendData *) i->data;
+
+ g_free (data->data);
+ g_slice_free (SendData, data);
+ }
+ g_queue_free (send_queue);
+}
+
+NiceSocket *
+nice_udp_turn_socket_new (GMainContext *ctx, NiceAddress *addr,
+ NiceSocket *base_socket, const NiceAddress *server_addr,
+ const gchar *username, const gchar *password,
+ NiceTurnSocketCompatibility compatibility)
+{
+ UdpTurnPriv *priv;
+ NiceSocket *sock = g_slice_new0 (NiceSocket);
+
+ if (!sock) {
+ return NULL;
+ }
+
+ priv = g_new0 (UdpTurnPriv, 1);
+
+ if (compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 ||
+ compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766) {
+ stun_agent_init (&priv->agent, STUN_ALL_KNOWN_ATTRIBUTES,
+ STUN_COMPATIBILITY_RFC5389,
+ STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS);
+ } else if (compatibility == NICE_TURN_SOCKET_COMPATIBILITY_MSN) {
+ stun_agent_init (&priv->agent, STUN_ALL_KNOWN_ATTRIBUTES,
+ STUN_COMPATIBILITY_RFC3489,
+ STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS |
+ STUN_AGENT_USAGE_NO_INDICATION_AUTH);
+ } else if (compatibility == NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE) {
+ stun_agent_init (&priv->agent, STUN_ALL_KNOWN_ATTRIBUTES,
+ STUN_COMPATIBILITY_RFC3489,
+ STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS |
+ STUN_AGENT_USAGE_IGNORE_CREDENTIALS);
+ } else if (compatibility == NICE_TURN_SOCKET_COMPATIBILITY_OC2007) {
+ stun_agent_init (&priv->agent, STUN_ALL_KNOWN_ATTRIBUTES,
+ STUN_COMPATIBILITY_OC2007,
+ STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS |
+ STUN_AGENT_USAGE_NO_ALIGNED_ATTRIBUTES);
+ }
+
+ priv->channels = NULL;
+ priv->current_binding = NULL;
+ priv->base_socket = base_socket;
+ if (ctx)
+ priv->ctx = g_main_context_ref (ctx);
+
+ if (compatibility == NICE_TURN_SOCKET_COMPATIBILITY_MSN ||
+ compatibility == NICE_TURN_SOCKET_COMPATIBILITY_OC2007) {
+ priv->username = g_base64_decode (username, &priv->username_len);
+ priv->password = g_base64_decode (password, &priv->password_len);
+ } else {
+ priv->username = (uint8_t *)g_strdup (username);
+ priv->username_len = (gsize) strlen (username);
+ if (compatibility == NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE) {
+ priv->password = NULL;
+ priv->password_len = 0;
+ } else {
+ priv->password = (uint8_t *)g_strdup (password);
+ priv->password_len = (gsize) strlen (password);
+ }
+ }
+ priv->server_addr = *server_addr;
+ priv->compatibility = compatibility;
+ priv->send_requests = g_queue_new ();
+
+ priv->send_data_queues =
+ g_hash_table_new_full (priv_nice_address_hash,
+ (GEqualFunc) nice_address_equal,
+ (GDestroyNotify) nice_address_free,
+ priv_send_data_queue_destroy);
+
+ sock->type = NICE_SOCKET_TYPE_UDP_TURN;
+ sock->fileno = NULL;
+ sock->addr = *addr;
+ sock->send_messages = socket_send_messages;
+ sock->send_messages_reliable = socket_send_messages_reliable;
+ sock->recv_messages = socket_recv_messages;
+ sock->is_reliable = socket_is_reliable;
+ sock->can_send = socket_can_send;
+ sock->set_writable_callback = socket_set_writable_callback;
+ sock->is_based_on = socket_is_based_on;
+ sock->close = socket_close;
+ sock->priv = (void *) priv;
+
+ return sock;
+}
+
+
+
+static void
+socket_close (NiceSocket *sock)
+{
+ UdpTurnPriv *priv = (UdpTurnPriv *) sock->priv;
+ GList *i = NULL;
+
+ g_mutex_lock (&mutex);
+
+ for (i = priv->channels; i; i = i->next) {
+ ChannelBinding *b = i->data;
+ if (b->timeout_source) {
+ g_source_destroy (b->timeout_source);
+ g_source_unref (b->timeout_source);
+ }
+ g_free (b);
+ }
+ g_list_free (priv->channels);
+
+ g_list_free_full (priv->pending_bindings, (GDestroyNotify) nice_address_free);
+
+ if (priv->tick_source_channel_bind != NULL) {
+ g_source_destroy (priv->tick_source_channel_bind);
+ g_source_unref (priv->tick_source_channel_bind);
+ priv->tick_source_channel_bind = NULL;
+ }
+
+ if (priv->tick_source_create_permission != NULL) {
+ g_source_destroy (priv->tick_source_create_permission);
+ g_source_unref (priv->tick_source_create_permission);
+ priv->tick_source_create_permission = NULL;
+ }
+
+ g_queue_free_full (priv->send_requests, (GDestroyNotify) send_request_free);
+
+ priv_clear_permissions (priv);
+ g_list_free_full (priv->sent_permissions, (GDestroyNotify) nice_address_free);
+ g_hash_table_destroy (priv->send_data_queues);
+
+ if (priv->permission_timeout_source) {
+ g_source_destroy (priv->permission_timeout_source);
+ g_source_unref (priv->permission_timeout_source);
+ priv->permission_timeout_source = NULL;
+ }
+
+ if (priv->ctx)
+ g_main_context_unref (priv->ctx);
+
+ g_free (priv->current_binding);
+ g_free (priv->current_binding_msg);
+ g_list_free_full (priv->pending_permissions, g_free);
+ g_free (priv->username);
+ g_free (priv->password);
+ g_free (priv->cached_realm);
+ g_free (priv->cached_nonce);
+
+ if (priv->fragment_buffer) {
+ g_byte_array_free(priv->fragment_buffer, TRUE);
+ }
+
+ g_free (priv);
+
+ sock->priv = NULL;
+
+ g_mutex_unlock (&mutex);
+}
+
+static gint
+socket_recv_messages (NiceSocket *sock,
+ NiceInputMessage *recv_messages, guint n_recv_messages)
+{
+ UdpTurnPriv *priv = (UdpTurnPriv *) sock->priv;
+ gint n_messages;
+ gint n_output_messages = 0;
+ guint i;
+ gboolean error = FALSE;
+
+ /* Make sure socket has not been freed: */
+ g_assert (sock->priv != NULL);
+
+ nice_debug_verbose ("received message on TURN socket");
+
+ if (priv->fragment_buffer) {
+ /* Fill as many recv_messages as possible with RFC4571-framed data we
+ * already hold in our buffer before reading more from the base socket. */
+ guint8 *f_buffer = priv->fragment_buffer->data;
+ guint f_buffer_len = priv->fragment_buffer->len;
+
+ for (i = 0; i < n_recv_messages && f_buffer_len >= sizeof (guint16); ++i) {
+ guint32 msg_len = ((f_buffer[0] << 8) | f_buffer[1]) + sizeof (guint16);
+
+ if (msg_len > f_buffer_len) {
+ /* The next message in the buffer isn't complete yet. Wait for more
+ * data from the base socket. */
+ break;
+ }
+
+ /* We have a full message in the buffer. Copy it into the user-provided
+ * NiceInputMessage. */
+ memcpy_buffer_to_input_message (&recv_messages[i], f_buffer, msg_len);
+ *recv_messages[i].from = priv->from;
+
+ f_buffer += msg_len;
+ f_buffer_len -= msg_len;
+ ++n_output_messages;
+ }
+
+ /* Adjust recv_messages with the number of messages we've just filled. */
+ recv_messages += n_output_messages;
+ n_recv_messages -= n_output_messages;
+
+ /* Shrink the fragment buffer, deallocate it if empty. */
+ g_byte_array_remove_range (priv->fragment_buffer, 0,
+ priv->fragment_buffer->len - f_buffer_len);
+ if (priv->fragment_buffer->len == 0) {
+ g_byte_array_free (priv->fragment_buffer, TRUE);
+ priv->fragment_buffer = NULL;
+ }
+ }
+
+ n_messages = nice_socket_recv_messages (priv->base_socket,
+ recv_messages, n_recv_messages);
+
+ if (n_messages < 0)
+ return n_messages;
+
+ /* Process all the messages. Those which fail parsing are re-used for the next
+ * message.
+ *
+ * FIXME: This needs a fast path which avoids allocations or memcpy()s.
+ * Implementing such a path means rewriting the TURN parser (and hence the
+ * STUN message code) to operate on vectors of buffers, rather than a
+ * monolithic buffer. */
+ for (i = 0; i < (guint) n_messages; ++i) {
+ NiceInputMessage *message = &recv_messages[i];
+ NiceSocket *dummy;
+ NiceAddress from;
+ guint8 *buffer;
+ gsize buffer_length;
+ gint parsed_buffer_length;
+ gboolean allocated_buffer = FALSE;
+
+ if (message->length == 0)
+ continue;
+
+ /* Compact the message’s buffers into a single one for parsing. Avoid this
+ * in the (hopefully) common case of a single-element buffer vector. */
+ if (message->n_buffers == 1 ||
+ (message->n_buffers == -1 &&
+ message->buffers[0].buffer != NULL &&
+ message->buffers[1].buffer == NULL)) {
+ buffer = message->buffers[0].buffer;
+ buffer_length = message->length;
+ } else {
+ nice_debug_verbose ("%s: **WARNING: SLOW PATH**", G_STRFUNC);
+
+ buffer = compact_input_message (message, &buffer_length);
+ allocated_buffer = TRUE;
+ }
+
+ /* Parse in-place. */
+ parsed_buffer_length = nice_udp_turn_socket_parse_recv (sock, &dummy,
+ &from, buffer_length, buffer,
+ message->from, buffer, buffer_length);
+ message->length = MAX (parsed_buffer_length, 0);
+
+ if (parsed_buffer_length < 0) {
+ error = TRUE;
+ } else if (parsed_buffer_length > 0) {
+ *message->from = from;
+ }
+ /* parsed_buffer_length == 0 means this is a TURN control message which
+ * needs ignoring. */
+
+ if (nice_socket_is_reliable (sock) && parsed_buffer_length > 0) {
+ /* Determine the portion of the current NiceInputMessage we can already
+ * return. */
+ gint32 msg_len = 0;
+ if (!priv->fragment_buffer) {
+ msg_len = ((buffer[0] << 8) | buffer[1]) + sizeof (guint16);
+ if (msg_len > parsed_buffer_length) {
+ /* The RFC4571 frame is larger than the current TURN message, need to
+ * buffer it and wait for more data. */
+ msg_len = 0;
+ }
+ }
+
+ if (msg_len != parsed_buffer_length && !priv->fragment_buffer) {
+ /* Start of message fragmenting detected. Allocate fragment buffer
+ * large enough for the recv_message's we haven't parsed yet. */
+ gint j;
+ guint buffer_len = 0;
+
+ for (j = i; j < n_messages; ++j) {
+ buffer_len += recv_messages[j].length;
+ }
+ priv->fragment_buffer = g_byte_array_sized_new (buffer_len);
+ }
+
+ if (priv->fragment_buffer) {
+ /* The messages are fragmented. Store the excess data (after msg_len
+ * bytes) into fragment buffer for reassembly. */
+ g_byte_array_append (priv->fragment_buffer, buffer + msg_len,
+ parsed_buffer_length - msg_len);
+
+ parsed_buffer_length = msg_len;
+ message->length = msg_len;
+ priv->from = from;
+ }
+ }
+
+ /* Split up the monolithic buffer again into the caller-provided buffers. */
+ if (parsed_buffer_length > 0 && allocated_buffer) {
+ memcpy_buffer_to_input_message (message, buffer,
+ parsed_buffer_length);
+ }
+
+ if (allocated_buffer)
+ g_free (buffer);
+
+ if (error)
+ break;
+
+ ++n_output_messages;
+ }
+
+ /* Was there an error processing the first message? */
+ if (error && i == 0)
+ return -1;
+
+ return n_output_messages;
+}
+
+/* interval is given in milliseconds */
+static GSource *
+priv_timeout_add_with_context (UdpTurnPriv *priv, guint interval,
+ GSourceFunc function, gpointer data)
+{
+ GSource *source = NULL;
+
+ g_return_val_if_fail (function != NULL, NULL);
+
+ source = g_timeout_source_new (interval);
+
+ g_source_set_callback (source, function, data, NULL);
+ g_source_attach (source, priv->ctx);
+
+ return source;
+}
+
+/* interval is given in seconds */
+static GSource *
+priv_timeout_add_seconds_with_context (UdpTurnPriv *priv, guint interval,
+ GSourceFunc function, gpointer data)
+{
+ GSource *source = NULL;
+
+ g_return_val_if_fail (function != NULL, NULL);
+
+ source = g_timeout_source_new_seconds (interval);
+
+ g_source_set_callback (source, function, data, NULL);
+ g_source_attach (source, priv->ctx);
+
+ return source;
+}
+
+static StunMessageReturn
+stun_message_append_ms_connection_id(StunMessage *msg,
+ uint8_t *ms_connection_id, uint32_t ms_sequence_num)
+{
+ union {
+ uint8_t buf8[24];
+ uint32_t buf32[24/4];
+ } buf;
+
+ memcpy(buf.buf8, ms_connection_id, 20);
+ buf.buf32[5] = htonl(ms_sequence_num);
+ return stun_message_append_bytes (msg, STUN_ATTRIBUTE_MS_SEQUENCE_NUMBER,
+ buf.buf8, 24);
+}
+
+static void
+stun_message_ensure_ms_realm(StunMessage *msg, uint8_t *realm)
+{
+ /* With MS-TURN, original clients do not send REALM attribute in Send and Set
+ * Active Destination requests, but use it to compute MESSAGE-INTEGRITY. We
+ * simply append cached realm value to the message and use it in subsequent
+ * stun_agent_finish_message() call. Messages with this additional attribute
+ * are handled correctly on OCS Access Edge working as TURN server. */
+ if (stun_message_get_method(msg) == STUN_SEND ||
+ stun_message_get_method(msg) == STUN_OLD_SET_ACTIVE_DST) {
+ stun_message_append_bytes (msg, STUN_ATTRIBUTE_REALM, realm,
+ strlen((char *)realm));
+ }
+}
+
+static gboolean
+priv_is_peer_in_list (const GList *list, const NiceAddress *peer)
+{
+ const GList *iter;
+
+ for (iter = list ; iter ; iter = g_list_next (iter)) {
+ NiceAddress *address = (NiceAddress *) iter->data;
+
+ if (nice_address_equal (address, peer))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+priv_has_permission_for_peer (UdpTurnPriv *priv, const NiceAddress *peer)
+{
+ return priv_is_peer_in_list (priv->permissions, peer);
+}
+
+static gboolean
+priv_has_sent_permission_for_peer (UdpTurnPriv *priv, const NiceAddress *peer)
+{
+ return priv_is_peer_in_list (priv->sent_permissions, peer);
+}
+
+static void
+priv_add_permission_for_peer (UdpTurnPriv *priv, const NiceAddress *peer)
+{
+ priv->permissions =
+ g_list_append (priv->permissions, nice_address_dup (peer));
+}
+
+static void
+priv_add_sent_permission_for_peer (UdpTurnPriv *priv, const NiceAddress *peer)
+{
+ priv->sent_permissions =
+ g_list_append (priv->sent_permissions, nice_address_dup (peer));
+}
+
+static GList *
+priv_remove_peer_from_list (GList *list, const NiceAddress *peer)
+{
+ GList *iter;
+
+ for (iter = list ; iter ; iter = g_list_next (iter)) {
+ NiceAddress *address = (NiceAddress *) iter->data;
+
+ if (nice_address_equal (address, peer)) {
+ GList *prev = iter->prev;
+
+ nice_address_free (address);
+ list = g_list_delete_link (list, iter);
+ iter = prev;
+ if (iter)
+ iter = list;
+ }
+ }
+
+ return list;
+}
+
+static void
+priv_remove_sent_permission_for_peer (UdpTurnPriv *priv, const NiceAddress *peer)
+{
+ priv->sent_permissions =
+ priv_remove_peer_from_list (priv->sent_permissions, peer);
+}
+
+static void
+priv_clear_permissions (UdpTurnPriv *priv)
+{
+ g_list_free_full (priv->permissions, (GDestroyNotify) nice_address_free);
+ priv->permissions = NULL;
+}
+
+static gint
+_socket_send_messages_wrapped (NiceSocket *sock, const NiceAddress *to,
+ const NiceOutputMessage *messages, guint n_messages, gboolean reliable)
+{
+ if (!nice_socket_is_reliable (sock)) {
+ if (reliable)
+ return nice_socket_send_messages_reliable (sock, to, messages, n_messages);
+ else
+ return nice_socket_send_messages (sock, to, messages, n_messages);
+ } else {
+ GOutputVector *local_bufs;
+ NiceOutputMessage local_message;
+ const NiceOutputMessage *message;
+ gsize message_len;
+ guint n_bufs = 0;
+ guint16 rfc4571_frame;
+ guint i;
+ gint ret;
+
+ g_assert (n_messages == 1);
+ message = &messages[0];
+ message_len = output_message_get_size (message);
+ g_assert (message_len <= G_MAXUINT16);
+
+ /* ICE-TCP requires that all packets be framed with RFC4571 */
+
+ /* Count the number of buffers. */
+ if (message->n_buffers == -1) {
+ for (i = 0; message->buffers[i].buffer != NULL; i++)
+ n_bufs++;
+ } else {
+ n_bufs = message->n_buffers;
+ }
+
+ local_bufs = g_alloca ((n_bufs + 1) * sizeof (GOutputVector));
+ local_message.buffers = local_bufs;
+ local_message.n_buffers = n_bufs + 1;
+
+ rfc4571_frame = htons (message_len);
+ local_bufs[0].buffer = &rfc4571_frame;
+ local_bufs[0].size = sizeof (guint16);
+
+ for (i = 0; i < n_bufs; i++) {
+ local_bufs[i + 1].buffer = message->buffers[i].buffer;
+ local_bufs[i + 1].size = message->buffers[i].size;
+ }
+
+
+ if (reliable)
+ ret = nice_socket_send_messages_reliable (sock, to,
+ &local_message, 1);
+ else
+ ret = nice_socket_send_messages (sock, to, &local_message, 1);
+
+ if (ret == 1)
+ ret = message_len;
+
+ return ret;
+ }
+}
+
+static gssize
+_socket_send_wrapped (NiceSocket *sock, const NiceAddress *to,
+ guint len, const gchar *buf, gboolean reliable)
+{
+ gint ret;
+
+ if (!nice_socket_is_reliable (sock)) {
+ GOutputVector local_buf = { buf, len };
+ NiceOutputMessage local_message = { &local_buf, 1};
+
+ ret = _socket_send_messages_wrapped (sock, to, &local_message, 1, reliable);
+ if (ret == 1)
+ return len;
+ return ret;
+ } else {
+ guint16 rfc4571_frame = htons (len);
+ GOutputVector local_buf[2] = {{&rfc4571_frame, 2}, { buf, len }};
+ NiceOutputMessage local_message = { local_buf, 2};
+
+ if (reliable)
+ ret = nice_socket_send_messages_reliable (sock, to, &local_message, 1);
+ else
+ ret = nice_socket_send_messages (sock, to, &local_message, 1);
+
+ if (ret == 1)
+ return len;
+ return ret;
+ }
+}
+
+static void
+socket_enqueue_data(UdpTurnPriv *priv, const NiceAddress *to,
+ guint len, const gchar *buf, gboolean reliable)
+{
+ SendData *data = g_slice_new0 (SendData);
+ GQueue *queue = g_hash_table_lookup (priv->send_data_queues, to);
+
+ if (queue == NULL) {
+ queue = g_queue_new ();
+ g_hash_table_insert (priv->send_data_queues, nice_address_dup (to),
+ queue);
+ }
+
+ data->data = g_memdup(buf, len);
+ data->data_len = len;
+ data->reliable = reliable;
+ g_queue_push_tail (queue, data);
+}
+
+static void
+socket_dequeue_all_data (UdpTurnPriv *priv, const NiceAddress *to)
+{
+ GQueue *send_queue = g_hash_table_lookup (priv->send_data_queues, to);
+
+ if (send_queue) {
+ while (!g_queue_is_empty (send_queue)) {
+ SendData *data =
+ (SendData *) g_queue_pop_head(send_queue);
+
+ nice_debug_verbose ("dequeuing data");
+ _socket_send_wrapped (priv->base_socket, &priv->server_addr,
+ data->data_len, data->data, data->reliable);
+
+ g_free (data->data);
+ g_slice_free (SendData, data);
+ }
+
+ /* remove queue from table */
+ g_hash_table_remove (priv->send_data_queues, to);
+ }
+}
+
+
+static gssize
+socket_send_message (NiceSocket *sock, const NiceAddress *to,
+ const NiceOutputMessage *message, gboolean reliable)
+{
+ UdpTurnPriv *priv = (UdpTurnPriv *) sock->priv;
+ StunMessage msg;
+ uint8_t buffer[STUN_MAX_MESSAGE_SIZE];
+ size_t msg_len;
+ union {
+ struct sockaddr_storage storage;
+ struct sockaddr addr;
+ } sa;
+ GList *i;
+ ChannelBinding *binding = NULL;
+ gint ret;
+
+ /* Make sure socket has not been freed: */
+ g_assert (sock->priv != NULL);
+
+ for (i = priv->channels; i; i = i->next) {
+ ChannelBinding *b = i->data;
+ if (nice_address_equal (&b->peer, to)) {
+ binding = b;
+ break;
+ }
+ }
+
+ nice_address_copy_to_sockaddr (to, &sa.addr);
+
+ if (binding) {
+ if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 ||
+ priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766) {
+ gsize message_len = output_message_get_size (message);
+
+ if (message_len + sizeof(uint32_t) <= sizeof(buffer)) {
+ guint j;
+ uint16_t len16, channel16;
+ gsize message_offset = 0;
+
+ len16 = htons ((uint16_t) message_len);
+ channel16 = htons (binding->channel);
+
+ memcpy (buffer, &channel16, sizeof(uint16_t));
+ memcpy (buffer + sizeof(uint16_t), &len16, sizeof(uint16_t));
+
+ /* FIXME: Slow path! This should be replaced by code which manipulates
+ * the GOutputVector array, rather than the buffer contents
+ * themselves. */
+ for (j = 0;
+ (message->n_buffers >= 0 && j < (guint) message->n_buffers) ||
+ (message->n_buffers < 0 && message->buffers[j].buffer != NULL);
+ j++) {
+ const GOutputVector *out_buf = &message->buffers[j];
+ gsize out_len;
+
+ out_len = MIN (message_len - message_offset, out_buf->size);
+ memcpy (buffer + sizeof (uint32_t) + message_offset,
+ out_buf->buffer, out_len);
+ message_offset += out_len;
+ }
+
+ msg_len = message_len + sizeof(uint32_t);
+ } else {
+ goto error;
+ }
+ } else {
+ ret = _socket_send_messages_wrapped (priv->base_socket,
+ &priv->server_addr, message, 1, reliable);
+
+ if (ret == 1)
+ return output_message_get_size (message);
+ return ret;
+ }
+ } else {
+ guint8 *compacted_buf;
+ gsize compacted_buf_len;
+
+ if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 ||
+ priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766) {
+ if (!stun_agent_init_indication (&priv->agent, &msg,
+ buffer, sizeof(buffer), STUN_IND_SEND))
+ goto error;
+ if (stun_message_append_xor_addr (&msg, STUN_ATTRIBUTE_PEER_ADDRESS,
+ &sa.storage, sizeof(sa)) !=
+ STUN_MESSAGE_RETURN_SUCCESS)
+ goto error;
+ } else {
+ if (!stun_agent_init_request (&priv->agent, &msg,
+ buffer, sizeof(buffer), STUN_SEND))
+ goto error;
+
+ if (stun_message_append32 (&msg, STUN_ATTRIBUTE_MAGIC_COOKIE,
+ TURN_MAGIC_COOKIE) != STUN_MESSAGE_RETURN_SUCCESS)
+ goto error;
+ if (priv->username != NULL && priv->username_len > 0) {
+ if (stun_message_append_bytes (&msg, STUN_ATTRIBUTE_USERNAME,
+ priv->username, priv->username_len) !=
+ STUN_MESSAGE_RETURN_SUCCESS)
+ goto error;
+ }
+ if (stun_message_append_addr (&msg, STUN_ATTRIBUTE_DESTINATION_ADDRESS,
+ &sa.addr, sizeof(sa)) !=
+ STUN_MESSAGE_RETURN_SUCCESS)
+ goto error;
+
+ if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE &&
+ priv->current_binding &&
+ nice_address_equal (&priv->current_binding->peer, to)) {
+ stun_message_append32 (&msg, STUN_ATTRIBUTE_OPTIONS, 1);
+ }
+ }
+
+ if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_OC2007) {
+ stun_message_append32(&msg, STUN_ATTRIBUTE_MS_VERSION, 1);
+
+ if (priv->ms_connection_id_valid)
+ stun_message_append_ms_connection_id(&msg, priv->ms_connection_id,
+ ++priv->ms_sequence_num);
+
+ stun_message_ensure_ms_realm(&msg, priv->ms_realm);
+ }
+
+ /* Slow path! We have to compact the buffers to append them to the message.
+ * FIXME: This could be improved by adding vectored I/O support to
+ * stun_message_append_bytes(). */
+ compacted_buf = compact_output_message (message, &compacted_buf_len);
+
+ if (stun_message_append_bytes (&msg, STUN_ATTRIBUTE_DATA,
+ compacted_buf, compacted_buf_len) != STUN_MESSAGE_RETURN_SUCCESS) {
+ g_free (compacted_buf);
+ goto error;
+ }
+
+ g_free (compacted_buf);
+
+ /* Finish the message. */
+ msg_len = stun_agent_finish_message (&priv->agent, &msg,
+ priv->password, priv->password_len);
+ if (msg_len > 0 && stun_message_get_class (&msg) == STUN_REQUEST &&
+ priv->compatibility != NICE_TURN_SOCKET_COMPATIBILITY_OC2007) {
+ SendRequest *req = g_slice_new0 (SendRequest);
+
+ req->priv = priv;
+ stun_message_id (&msg, req->id);
+ req->source = priv_timeout_add_with_context (priv,
+ STUN_END_TIMEOUT, priv_forget_send_request_timeout, req);
+ g_queue_push_tail (priv->send_requests, req);
+ }
+ }
+
+ if (msg_len > 0) {
+ if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766 &&
+ !priv_has_permission_for_peer (priv, to)) {
+ if (!priv_has_sent_permission_for_peer (priv, to)) {
+ priv_send_create_permission (priv, to);
+ }
+
+ /* enque data */
+ nice_debug_verbose ("enqueuing data");
+ socket_enqueue_data(priv, to, msg_len, (gchar *)buffer, reliable);
+
+ return msg_len;
+ } else {
+ GOutputVector local_buf = { buffer, msg_len };
+ NiceOutputMessage local_message = {&local_buf, 1};
+
+ ret = _socket_send_messages_wrapped (priv->base_socket,
+ &priv->server_addr, &local_message, 1, reliable);
+
+ if (ret == 1)
+ return msg_len;
+ return ret;
+ }
+ }
+
+ /* Error condition pass through to the base socket. */
+ ret = _socket_send_messages_wrapped (priv->base_socket, to, message, 1,
+ reliable);
+ if (ret == 1)
+ return output_message_get_size (message);
+ return ret;
+error:
+ return -1;
+}
+
+static gint
+socket_send_messages (NiceSocket *sock, const NiceAddress *to,
+ const NiceOutputMessage *messages, guint n_messages)
+{
+ guint i;
+
+ g_mutex_lock (&mutex);
+
+ /* Make sure socket has not been freed: */
+ g_assert (sock->priv != NULL);
+
+ for (i = 0; i < n_messages; i++) {
+ const NiceOutputMessage *message = &messages[i];
+ gssize len;
+
+ len = socket_send_message (sock, to, message, FALSE);
+
+ if (len < 0) {
+ /* Error. */
+ if (i > 0)
+ break;
+ g_mutex_unlock (&mutex);
+ return len;
+ } else if (len == 0) {
+ /* EWOULDBLOCK. */
+ break;
+ }
+ }
+
+ g_mutex_unlock (&mutex);
+
+ return i;
+}
+
+static gint
+socket_send_messages_reliable (NiceSocket *sock, const NiceAddress *to,
+ const NiceOutputMessage *messages, guint n_messages)
+{
+ UdpTurnPriv *priv = (UdpTurnPriv *) sock->priv;
+ guint i;
+
+ g_mutex_lock (&mutex);
+
+ /* TURN can depend either on tcp-turn or udp-bsd as a base socket
+ * if we allow reliable send and need to create permissions and we queue the
+ * data, then we must be sure that the reliable send will succeed later, so
+ * we check for udp-bsd here as the base socket and don't allow it.
+ */
+ if (priv->base_socket->type == NICE_SOCKET_TYPE_UDP_BSD) {
+ g_mutex_unlock (&mutex);
+ return -1;
+ }
+
+ for (i = 0; i < n_messages; i++) {
+ const NiceOutputMessage *message = &messages[i];
+ gssize len;
+
+ len = socket_send_message (sock, to, message, TRUE);
+
+ if (len < 0) {
+ /* Error. */
+ g_mutex_unlock (&mutex);
+ return len;
+ } else if (len == 0) {
+ /* EWOULDBLOCK. */
+ break;
+ }
+ }
+
+ g_mutex_unlock (&mutex);
+ return i;
+}
+
+static gboolean
+socket_is_reliable (NiceSocket *sock)
+{
+ UdpTurnPriv *priv = (UdpTurnPriv *) sock->priv;
+
+ return nice_socket_is_reliable (priv->base_socket);
+}
+
+static gboolean
+socket_can_send (NiceSocket *sock, NiceAddress *addr)
+{
+ UdpTurnPriv *priv = sock->priv;
+
+ return nice_socket_can_send (priv->base_socket, addr);
+}
+
+static void
+socket_set_writable_callback (NiceSocket *sock,
+ NiceSocketWritableCb callback, gpointer user_data)
+{
+ UdpTurnPriv *priv = sock->priv;
+
+ nice_socket_set_writable_callback (priv->base_socket, callback, user_data);
+}
+
+static gboolean
+socket_is_based_on (NiceSocket *sock, NiceSocket *other)
+{
+ UdpTurnPriv *priv = sock->priv;
+
+ return (sock == other) ||
+ (priv && nice_socket_is_based_on (priv->base_socket, other));
+}
+
+static gboolean
+priv_forget_send_request_timeout (gpointer pointer)
+{
+ SendRequest *req = pointer;
+
+ g_mutex_lock (&mutex);
+ if (g_source_is_destroyed (g_main_current_source ())) {
+ nice_debug ("Source was destroyed. "
+ "Avoided race condition in turn.c:priv_forget_send_request");
+ g_mutex_unlock (&mutex);
+ return G_SOURCE_REMOVE;
+ }
+
+ send_request_free (req);
+ g_queue_remove (req->priv->send_requests, req);
+
+ g_mutex_unlock (&mutex);
+
+ return G_SOURCE_REMOVE;
+}
+
+static gboolean
+priv_permission_timeout (gpointer data)
+{
+ UdpTurnPriv *priv = (UdpTurnPriv *) data;
+
+ nice_debug ("Permission is about to timeout, schedule renewal");
+
+ g_mutex_lock (&mutex);
+
+ if (g_source_is_destroyed (g_main_current_source ())) {
+ nice_debug ("Source was destroyed. Avoided race condition in "
+ "udp-turn.c:priv_permission_timeout");
+
+ g_mutex_unlock (&mutex);
+ return G_SOURCE_REMOVE;
+ }
+
+
+ /* remove all permissions for this agent (the permission for the peer
+ we are sending to will be renewed) */
+ priv_clear_permissions (priv);
+ g_mutex_unlock (&mutex);
+
+ return TRUE;
+}
+
+static gboolean
+priv_binding_expired_timeout (gpointer data)
+{
+ UdpTurnPriv *priv = (UdpTurnPriv *) data;
+ GList *i;
+ GSource *source = NULL;
+
+ g_mutex_lock (&mutex);
+ if (g_source_is_destroyed (g_main_current_source ())) {
+ nice_debug ("Source was destroyed. Avoided race condition in "
+ "udp-turn.c:priv_permission_timeout");
+
+ g_mutex_unlock (&mutex);
+ return G_SOURCE_REMOVE;
+ }
+
+ nice_debug ("Permission expired, refresh failed");
+
+ /* find current binding and destroy it */
+ for (i = priv->channels ; i; i = i->next) {
+ ChannelBinding *b = i->data;
+ if (b->timeout_source == source) {
+ priv->channels = g_list_remove (priv->channels, b);
+ /* Make sure we don't free a currently being-refreshed binding */
+ if (priv->current_binding_msg && !priv->current_binding) {
+ union {
+ struct sockaddr_storage storage;
+ struct sockaddr addr;
+ } sa;
+ socklen_t sa_len = sizeof(sa);
+ NiceAddress to;
+
+ /* look up binding associated with peer */
+ stun_message_find_xor_addr (
+ &priv->current_binding_msg->message,
+ STUN_ATTRIBUTE_XOR_PEER_ADDRESS, &sa.storage, &sa_len);
+ nice_address_set_from_sockaddr (&to, &sa.addr);
+
+ /* If the binding is being refreshed, then move it to
+ priv->current_binding so it counts as a 'new' binding and
+ will get readded to the list if it succeeds */
+ if (nice_address_equal (&b->peer, &to)) {
+ priv->current_binding = b;
+ break;
+ }
+ }
+ /* In case the binding timed out before it could be processed, add it to
+ the pending list */
+ priv_add_channel_binding (priv, &b->peer);
+ g_free (b);
+ break;
+ }
+ }
+
+ g_mutex_unlock (&mutex);
+ return G_SOURCE_REMOVE;
+}
+
+static gboolean
+priv_binding_timeout (gpointer data)
+{
+ UdpTurnPriv *priv = (UdpTurnPriv *) data;
+ GList *i;
+ GSource *source = NULL;
+
+ g_mutex_lock (&mutex);
+ if (g_source_is_destroyed (g_main_current_source ())) {
+ nice_debug ("Source was destroyed. Avoided race condition in "
+ "udp-turn.c:priv_permission_timeout");
+
+ g_mutex_unlock (&mutex);
+ return G_SOURCE_REMOVE;
+ }
+
+ nice_debug ("Permission is about to timeout, sending binding renewal");
+
+ /* find current binding and mark it for renewal */
+ for (i = priv->channels ; i; i = i->next) {
+ ChannelBinding *b = i->data;
+ if (b->timeout_source == source) {
+ b->renew = TRUE;
+
+ /* Remove any existing timer */
+ if (b->timeout_source) {
+ g_source_destroy (b->timeout_source);
+ g_source_unref (b->timeout_source);
+ }
+
+ /* Install timer to expire the permission */
+ b->timeout_source = priv_timeout_add_seconds_with_context (priv,
+ STUN_EXPIRE_TIMEOUT, priv_binding_expired_timeout, priv);
+
+ /* Send renewal */
+ if (!priv->current_binding_msg)
+ priv_send_channel_bind (priv, b->channel, &b->peer);
+ break;
+ }
+ }
+
+ g_mutex_unlock (&mutex);
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+nice_udp_turn_socket_cache_realm_nonce_locked (NiceSocket *sock,
+ StunMessage *msg)
+{
+ UdpTurnPriv *priv = sock->priv;
+ gconstpointer tmp;
+
+ g_assert (sock->type == NICE_SOCKET_TYPE_UDP_TURN);
+
+ g_free (priv->cached_realm);
+ priv->cached_realm = NULL;
+ priv->cached_realm_len = 0;
+
+ g_free (priv->cached_nonce);
+ priv->cached_nonce = NULL;
+ priv->cached_nonce_len = 0;
+
+ tmp = stun_message_find (msg, STUN_ATTRIBUTE_REALM, &priv->cached_realm_len);
+ if (tmp && priv->cached_realm_len < 764)
+ priv->cached_realm = g_memdup (tmp, priv->cached_realm_len);
+
+ tmp = stun_message_find (msg, STUN_ATTRIBUTE_NONCE, &priv->cached_nonce_len);
+ if (tmp && priv->cached_nonce_len < 764)
+ priv->cached_nonce = g_memdup (tmp, priv->cached_nonce_len);
+
+}
+
+void
+nice_udp_turn_socket_cache_realm_nonce (NiceSocket *sock,
+ StunMessage *msg)
+{
+ g_mutex_lock (&mutex);
+ nice_udp_turn_socket_cache_realm_nonce_locked (sock, msg);
+ g_mutex_unlock (&mutex);
+}
+
+guint
+nice_udp_turn_socket_parse_recv_message (NiceSocket *sock, NiceSocket **from_sock,
+ NiceInputMessage *message)
+{
+ /* TODO: Speed this up in the common reliable case of having a 24-byte header
+ * buffer to begin with, followed by one or more massive buffers. */
+ guint8 *buf;
+ gsize buf_len, len;
+
+ if (message->n_buffers == 1 ||
+ (message->n_buffers == -1 &&
+ message->buffers[0].buffer != NULL &&
+ message->buffers[1].buffer == NULL)) {
+ /* Fast path. Single massive buffer. */
+ len = nice_udp_turn_socket_parse_recv (sock, from_sock,
+ message->from, message->length, message->buffers[0].buffer,
+ message->from, message->buffers[0].buffer, message->length);
+
+ g_assert_cmpuint (len, <=, message->length);
+
+ message->length = len;
+
+ return (len > 0) ? 1 : 0;
+ }
+
+ /* Slow path. */
+ nice_debug_verbose ("%s: **WARNING: SLOW PATH**", G_STRFUNC);
+
+ buf = compact_input_message (message, &buf_len);
+ len = nice_udp_turn_socket_parse_recv (sock, from_sock,
+ message->from, buf_len, buf,
+ message->from, buf, buf_len);
+ len = memcpy_buffer_to_input_message (message, buf, len);
+ g_free (buf);
+
+ return (len > 0) ? 1 : 0;
+}
+
+gsize
+nice_udp_turn_socket_parse_recv (NiceSocket *sock, NiceSocket **from_sock,
+ NiceAddress *from, gsize len, guint8 *buf,
+ const NiceAddress *recv_from, const guint8 *_recv_buf, gsize recv_len)
+{
+
+ UdpTurnPriv *priv = (UdpTurnPriv *) sock->priv;
+ StunValidationStatus valid;
+ StunMessage msg;
+ GList *l;
+ ChannelBinding *binding = NULL;
+
+ union {
+ const guint8 *u8;
+ const guint16 *u16;
+ } recv_buf;
+
+ g_mutex_lock (&mutex);
+
+ /* In the case of a reliable UDP-TURN-OVER-TCP (which means MS-TURN)
+ * we must use RFC4571 framing */
+ if (nice_socket_is_reliable (sock)) {
+ recv_buf.u8 = _recv_buf + sizeof(guint16);
+ recv_len -= sizeof(guint16);
+ } else {
+ recv_buf.u8 = _recv_buf;
+ }
+
+ if (nice_address_equal (&priv->server_addr, recv_from)) {
+ valid = stun_agent_validate (&priv->agent, &msg,
+ recv_buf.u8, recv_len, NULL, NULL);
+
+ if (valid == STUN_VALIDATION_SUCCESS) {
+ if (priv->compatibility != NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 &&
+ priv->compatibility != NICE_TURN_SOCKET_COMPATIBILITY_RFC5766) {
+ uint32_t cookie;
+ if (stun_message_find32 (&msg, STUN_ATTRIBUTE_MAGIC_COOKIE,
+ &cookie) != STUN_MESSAGE_RETURN_SUCCESS)
+ goto recv;
+ if (cookie != TURN_MAGIC_COOKIE)
+ goto recv;
+ }
+
+ if (stun_message_get_method (&msg) == STUN_SEND) {
+ if (stun_message_get_class (&msg) == STUN_RESPONSE) {
+ SendRequest *req = NULL;
+ GList *i = g_queue_peek_head_link (priv->send_requests);
+ StunTransactionId msg_id;
+
+ stun_message_id (&msg, msg_id);
+
+ for (; i; i = i->next) {
+ SendRequest *r = i->data;
+ if (memcmp (&r->id, msg_id, sizeof(StunTransactionId)) == 0) {
+ req = r;
+ break;
+ }
+ }
+
+ if (req) {
+ g_queue_remove (priv->send_requests, req);
+ send_request_free (req);
+ }
+
+ if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE) {
+ uint32_t opts = 0;
+ if (stun_message_find32 (&msg, STUN_ATTRIBUTE_OPTIONS, &opts) ==
+ STUN_MESSAGE_RETURN_SUCCESS && opts & 0x1)
+ goto msn_google_lock;
+ }
+ }
+
+ goto done;
+ } else if (stun_message_get_method (&msg) == STUN_OLD_SET_ACTIVE_DST) {
+ StunTransactionId request_id;
+ StunTransactionId response_id;
+
+ if (priv->current_binding && priv->current_binding_msg) {
+ stun_message_id (&msg, response_id);
+ stun_message_id (&priv->current_binding_msg->message, request_id);
+ if (memcmp (request_id, response_id,
+ sizeof(StunTransactionId)) == 0) {
+ g_free (priv->current_binding_msg);
+ priv->current_binding_msg = NULL;
+
+ if (stun_message_get_class (&msg) == STUN_RESPONSE &&
+ (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_OC2007 ||
+ priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_MSN)) {
+ goto msn_google_lock;
+ } else {
+ g_free (priv->current_binding);
+ priv->current_binding = NULL;
+ }
+ }
+ }
+
+ goto done;
+ } else if (stun_message_get_method (&msg) == STUN_CHANNELBIND) {
+ StunTransactionId request_id;
+ StunTransactionId response_id;
+
+ if (priv->current_binding_msg) {
+ stun_message_id (&msg, response_id);
+ stun_message_id (&priv->current_binding_msg->message, request_id);
+ if (memcmp (request_id, response_id,
+ sizeof(StunTransactionId)) == 0) {
+
+ if (priv->current_binding) {
+ /* New channel binding */
+ binding = priv->current_binding;
+ } else {
+ /* Existing binding refresh */
+ GList *i;
+ union {
+ struct sockaddr_storage storage;
+ struct sockaddr addr;
+ } sa;
+ socklen_t sa_len = sizeof(sa);
+ NiceAddress to;
+
+ /* look up binding associated with peer */
+ stun_message_find_xor_addr (
+ &priv->current_binding_msg->message,
+ STUN_ATTRIBUTE_XOR_PEER_ADDRESS, &sa.storage, &sa_len);
+ nice_address_set_from_sockaddr (&to, &sa.addr);
+
+ for (i = priv->channels; i; i = i->next) {
+ ChannelBinding *b = i->data;
+ if (nice_address_equal (&b->peer, &to)) {
+ binding = b;
+ break;
+ }
+ }
+ }
+
+ if (stun_message_get_class (&msg) == STUN_ERROR) {
+ int code = -1;
+ uint8_t *sent_realm = NULL;
+ uint8_t *recv_realm = NULL;
+ uint16_t sent_realm_len = 0;
+ uint16_t recv_realm_len = 0;
+
+ sent_realm =
+ (uint8_t *) stun_message_find (
+ &priv->current_binding_msg->message,
+ STUN_ATTRIBUTE_REALM, &sent_realm_len);
+ recv_realm =
+ (uint8_t *) stun_message_find (&msg,
+ STUN_ATTRIBUTE_REALM, &recv_realm_len);
+
+ /* check for unauthorized error response */
+ if (stun_message_find_error (&msg, &code) ==
+ STUN_MESSAGE_RETURN_SUCCESS &&
+ (code == STUN_ERROR_STALE_NONCE ||
+ (code == STUN_ERROR_UNAUTHORIZED &&
+ !(recv_realm != NULL &&
+ recv_realm_len > 0 &&
+ recv_realm_len == sent_realm_len &&
+ sent_realm != NULL &&
+ memcmp (sent_realm, recv_realm,
+ sent_realm_len) == 0)))) {
+
+ g_free (priv->current_binding_msg);
+ priv->current_binding_msg = NULL;
+ nice_udp_turn_socket_cache_realm_nonce_locked (sock, &msg);
+ if (binding)
+ priv_send_channel_bind (priv, binding->channel,
+ &binding->peer);
+ } else {
+ g_free (priv->current_binding);
+ priv->current_binding = NULL;
+ g_free (priv->current_binding_msg);
+ priv->current_binding_msg = NULL;
+ priv_process_pending_bindings (priv);
+ }
+ } else if (stun_message_get_class (&msg) == STUN_RESPONSE) {
+ g_free (priv->current_binding_msg);
+ priv->current_binding_msg = NULL;
+
+ /* If it's a new channel binding, then add it to the list */
+ if (priv->current_binding)
+ priv->channels = g_list_append (priv->channels,
+ priv->current_binding);
+ priv->current_binding = NULL;
+
+ if (binding) {
+ binding->renew = FALSE;
+
+ /* Remove any existing timer */
+ if (binding->timeout_source) {
+ g_source_destroy (binding->timeout_source);
+ g_source_unref (binding->timeout_source);
+ }
+ /* Install timer to schedule refresh of the permission */
+ binding->timeout_source =
+ priv_timeout_add_seconds_with_context (priv,
+ STUN_BINDING_TIMEOUT, priv_binding_timeout, priv);
+ }
+ priv_process_pending_bindings (priv);
+ }
+ }
+ }
+ goto done;
+ } else if (stun_message_get_method (&msg) == STUN_CREATEPERMISSION) {
+ StunTransactionId request_id;
+ StunTransactionId response_id;
+ GList *i, *next;
+ TURNMessage *current_create_permission_msg;
+
+ for (i = priv->pending_permissions; i; i = next) {
+ current_create_permission_msg = (TURNMessage *) i->data;
+ next = i->next;
+
+ stun_message_id (&msg, response_id);
+ stun_message_id (¤t_create_permission_msg->message, request_id);
+
+ if (memcmp (request_id, response_id,
+ sizeof(StunTransactionId)) == 0) {
+ union {
+ struct sockaddr_storage storage;
+ struct sockaddr addr;
+ } peer;
+ socklen_t peer_len = sizeof(peer);
+ NiceAddress to;
+ gchar tmpbuf[INET6_ADDRSTRLEN];
+
+ stun_message_find_xor_addr (
+ ¤t_create_permission_msg->message,
+ STUN_ATTRIBUTE_XOR_PEER_ADDRESS, &peer.storage, &peer_len);
+ nice_address_set_from_sockaddr (&to, &peer.addr);
+ nice_address_to_string (&to, tmpbuf);
+ nice_debug ("TURN: got response for CreatePermission "
+ "with XOR_PEER_ADDRESS=[%s]:%u : %s",
+ tmpbuf, nice_address_get_port (&to),
+ stun_message_get_class (&msg) == STUN_ERROR ? "unauthorized" : "ok");
+
+ /* unathorized => resend with realm and nonce */
+ if (stun_message_get_class (&msg) == STUN_ERROR) {
+ int code = -1;
+ uint8_t *sent_realm = NULL;
+ uint8_t *recv_realm = NULL;
+ uint16_t sent_realm_len = 0;
+ uint16_t recv_realm_len = 0;
+
+ sent_realm =
+ (uint8_t *) stun_message_find (
+ ¤t_create_permission_msg->message,
+ STUN_ATTRIBUTE_REALM, &sent_realm_len);
+ recv_realm =
+ (uint8_t *) stun_message_find (&msg,
+ STUN_ATTRIBUTE_REALM, &recv_realm_len);
+
+ /* check for unauthorized error response */
+ if (stun_message_find_error (&msg, &code) ==
+ STUN_MESSAGE_RETURN_SUCCESS &&
+ (code == STUN_ERROR_STALE_NONCE ||
+ (code == STUN_ERROR_UNAUTHORIZED &&
+ !(recv_realm != NULL &&
+ recv_realm_len > 0 &&
+ recv_realm_len == sent_realm_len &&
+ sent_realm != NULL &&
+ memcmp (sent_realm, recv_realm,
+ sent_realm_len) == 0)))) {
+
+ priv->pending_permissions = g_list_delete_link (
+ priv->pending_permissions, i);
+ g_free (current_create_permission_msg);
+ current_create_permission_msg = NULL;
+
+ nice_udp_turn_socket_cache_realm_nonce_locked (sock, &msg);
+ /* resend CreatePermission */
+ priv_send_create_permission (priv, &to);
+ goto done;
+ }
+ }
+ /* If we get an error, we just assume the server somehow
+ doesn't support permissions and we ignore the error and
+ fake a successful completion. If the server needs a permission
+ but it failed to create it, then the connchecks will fail. */
+ priv_remove_sent_permission_for_peer (priv, &to);
+ priv_add_permission_for_peer (priv, &to);
+
+ /* install timer to schedule refresh of the permission */
+ /* (will not schedule refresh if we got an error) */
+ if (stun_message_get_class (&msg) == STUN_RESPONSE &&
+ !priv->permission_timeout_source) {
+ priv->permission_timeout_source =
+ priv_timeout_add_seconds_with_context (priv,
+ STUN_PERMISSION_TIMEOUT, priv_permission_timeout,
+ priv);
+ }
+
+ /* send enqued data */
+ socket_dequeue_all_data (priv, &to);
+
+ priv->pending_permissions = g_list_delete_link (
+ priv->pending_permissions, i);
+ g_free (current_create_permission_msg);
+ current_create_permission_msg = NULL;
+
+ break;
+ }
+ }
+
+ goto done;
+ } else if (stun_message_get_class (&msg) == STUN_INDICATION &&
+ stun_message_get_method (&msg) == STUN_IND_DATA) {
+ uint16_t data_len;
+ uint8_t *data;
+ union {
+ struct sockaddr_storage storage;
+ struct sockaddr addr;
+ } sa;
+ socklen_t from_len = sizeof (sa);
+
+ if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 ||
+ priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766) {
+ if (stun_message_find_xor_addr (&msg, STUN_ATTRIBUTE_REMOTE_ADDRESS,
+ &sa.storage, &from_len) !=
+ STUN_MESSAGE_RETURN_SUCCESS)
+ goto recv;
+ } else {
+ if (stun_message_find_addr (&msg, STUN_ATTRIBUTE_REMOTE_ADDRESS,
+ &sa.storage, &from_len) !=
+ STUN_MESSAGE_RETURN_SUCCESS)
+ goto recv;
+ }
+
+ data = (uint8_t *) stun_message_find (&msg, STUN_ATTRIBUTE_DATA,
+ &data_len);
+
+ if (data == NULL)
+ goto recv;
+
+ nice_address_set_from_sockaddr (from, &sa.addr);
+
+ if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766 &&
+ !priv_has_permission_for_peer (priv, from)) {
+ if (!priv_has_sent_permission_for_peer (priv, from)) {
+ priv_send_create_permission (priv, from);
+ }
+ }
+
+ *from_sock = sock;
+ memmove (buf, data, len > data_len ? data_len : len);
+ g_mutex_unlock (&mutex);
+ return len > data_len ? data_len : len;
+ } else {
+ goto recv;
+ }
+ }
+ }
+
+ recv:
+ for (l = priv->channels; l; l = l->next) {
+ ChannelBinding *b = l->data;
+ if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 ||
+ priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766) {
+ if (b->channel == ntohs(recv_buf.u16[0])) {
+ recv_len = ntohs (recv_buf.u16[1]);
+ recv_buf.u8 += sizeof(uint32_t);
+ binding = b;
+ break;
+ }
+ } else {
+ binding = b;
+ break;
+ }
+ }
+
+ if (binding) {
+ *from = binding->peer;
+ *from_sock = sock;
+ } else {
+ *from = *recv_from;
+ }
+
+ memmove (buf, recv_buf.u8, len > recv_len ? recv_len : len);
+ g_mutex_unlock (&mutex);
+ return len > recv_len ? recv_len : len;
+
+ msn_google_lock:
+
+ if (priv->current_binding) {
+ GList *i = priv->channels;
+ for (; i; i = i->next) {
+ ChannelBinding *b = i->data;
+ g_free (b);
+ }
+ g_list_free (priv->channels);
+ priv->channels = g_list_append (NULL, priv->current_binding);
+ priv->current_binding = NULL;
+ priv_process_pending_bindings (priv);
+ }
+
+ done:
+ g_mutex_unlock (&mutex);
+ return 0;
+}
+
+gboolean
+nice_udp_turn_socket_set_peer (NiceSocket *sock, NiceAddress *peer)
+{
+ UdpTurnPriv *priv;
+ gboolean ret;
+
+ g_mutex_lock (&mutex);
+
+ priv = (UdpTurnPriv *) sock->priv;
+
+ ret = priv_add_channel_binding (priv, peer);
+
+ g_mutex_unlock (&mutex);
+
+ return ret;
+}
+
+static void
+priv_process_pending_bindings (UdpTurnPriv *priv)
+{
+ gboolean ret = FALSE;
+
+ while (priv->pending_bindings != NULL && ret == FALSE) {
+ NiceAddress *peer = priv->pending_bindings->data;
+ ret = priv_add_channel_binding (priv, peer);
+ priv->pending_bindings = g_list_remove (priv->pending_bindings, peer);
+ nice_address_free (peer);
+ }
+
+ /* If no new channel bindings are in progress and there are no
+ pending bindings, then renew the soon to be expired bindings */
+ if (priv->pending_bindings == NULL && priv->current_binding_msg == NULL) {
+ GList *i = NULL;
+
+ /* find binding to renew */
+ for (i = priv->channels ; i; i = i->next) {
+ ChannelBinding *b = i->data;
+ if (b->renew) {
+ priv_send_channel_bind (priv, b->channel, &b->peer);
+ break;
+ }
+ }
+ }
+}
+
+
+static gboolean
+priv_retransmissions_tick_unlocked (UdpTurnPriv *priv)
+{
+ gboolean ret = FALSE;
+
+ if (priv->current_binding_msg) {
+ switch (stun_timer_refresh (&priv->current_binding_msg->timer)) {
+ case STUN_USAGE_TIMER_RETURN_TIMEOUT:
+ {
+ /* Time out */
+ StunTransactionId id;
+
+ stun_message_id (&priv->current_binding_msg->message, id);
+ stun_agent_forget_transaction (&priv->agent, id);
+
+ g_free (priv->current_binding);
+ priv->current_binding = NULL;
+ g_free (priv->current_binding_msg);
+ priv->current_binding_msg = NULL;
+
+
+ priv_process_pending_bindings (priv);
+ break;
+ }
+ case STUN_USAGE_TIMER_RETURN_RETRANSMIT:
+ /* Retransmit */
+ _socket_send_wrapped (priv->base_socket, &priv->server_addr,
+ stun_message_length (&priv->current_binding_msg->message),
+ (gchar *)priv->current_binding_msg->buffer, FALSE);
+ ret = TRUE;
+ break;
+ case STUN_USAGE_TIMER_RETURN_SUCCESS:
+ ret = TRUE;
+ break;
+ default:
+ /* Nothing to do. */
+ break;
+ }
+ }
+
+ if (ret)
+ priv_schedule_tick (priv);
+ return ret;
+}
+
+static gboolean
+priv_retransmissions_create_permission_tick_unlocked (UdpTurnPriv *priv, GList *list_element)
+{
+ gboolean ret = FALSE;
+ TURNMessage *current_create_permission_msg;
+
+ current_create_permission_msg = (TURNMessage *)list_element->data;
+
+ if (current_create_permission_msg) {
+ switch (stun_timer_refresh (¤t_create_permission_msg->timer)) {
+ case STUN_USAGE_TIMER_RETURN_TIMEOUT:
+ {
+ /* Time out */
+ StunTransactionId id;
+ NiceAddress to;
+ union {
+ struct sockaddr_storage storage;
+ struct sockaddr addr;
+ } addr;
+ socklen_t addr_len = sizeof(addr);
+
+ stun_message_id (¤t_create_permission_msg->message, id);
+ stun_agent_forget_transaction (&priv->agent, id);
+ stun_message_find_xor_addr (
+ ¤t_create_permission_msg->message,
+ STUN_ATTRIBUTE_XOR_PEER_ADDRESS, &addr.storage, &addr_len);
+ nice_address_set_from_sockaddr (&to, &addr.addr);
+
+ priv_remove_sent_permission_for_peer (priv, &to);
+ priv->pending_permissions = g_list_delete_link (
+ priv->pending_permissions, list_element);
+ g_free (current_create_permission_msg);
+ current_create_permission_msg = NULL;
+
+ /* we got a timeout when retransmitting a CreatePermission
+ message, assume we can just send the data, the server
+ might not support RFC TURN, or connectivity check will
+ fail eventually anyway */
+ priv_add_permission_for_peer (priv, &to);
+
+ socket_dequeue_all_data (priv, &to);
+
+ break;
+ }
+ case STUN_USAGE_TIMER_RETURN_RETRANSMIT:
+ /* Retransmit */
+ _socket_send_wrapped (priv->base_socket, &priv->server_addr,
+ stun_message_length (¤t_create_permission_msg->message),
+ (gchar *)current_create_permission_msg->buffer, FALSE);
+ ret = TRUE;
+ break;
+ case STUN_USAGE_TIMER_RETURN_SUCCESS:
+ ret = TRUE;
+ break;
+ default:
+ /* Nothing to do. */
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static gboolean
+priv_retransmissions_tick (gpointer pointer)
+{
+ UdpTurnPriv *priv = pointer;
+
+ g_mutex_lock (&mutex);
+ if (g_source_is_destroyed (g_main_current_source ())) {
+ nice_debug ("Source was destroyed. Avoided race condition in "
+ "udp-turn.c:priv_permission_timeout");
+
+ g_mutex_unlock (&mutex);
+ return G_SOURCE_REMOVE;
+ }
+
+ if (priv_retransmissions_tick_unlocked (priv) == FALSE) {
+ if (priv->tick_source_channel_bind != NULL) {
+ g_source_destroy (priv->tick_source_channel_bind);
+ g_source_unref (priv->tick_source_channel_bind);
+ priv->tick_source_channel_bind = NULL;
+ }
+ }
+
+ g_mutex_unlock (&mutex);
+
+ return G_SOURCE_REMOVE;
+}
+
+static gboolean
+priv_retransmissions_create_permission_tick (gpointer pointer)
+{
+ UdpTurnPriv *priv = pointer;
+
+ g_mutex_lock (&mutex);
+ if (g_source_is_destroyed (g_main_current_source ())) {
+ nice_debug ("Source was destroyed. Avoided race condition in "
+ "udp-turn.c:priv_permission_timeout");
+
+ g_mutex_unlock (&mutex);
+ return G_SOURCE_REMOVE;
+ }
+
+ /* This will call priv_retransmissions_create_permission_tick_unlocked() for
+ * every pending permission with an expired timer and will create a new timer
+ * if there are pending permissions that require it */
+ priv_schedule_tick (priv);
+
+ g_mutex_unlock (&mutex);
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+priv_schedule_tick (UdpTurnPriv *priv)
+{
+ GList *i, *next, *prev;
+ TURNMessage *current_create_permission_msg;
+ guint min_timeout = G_MAXUINT;
+
+ if (priv->tick_source_channel_bind != NULL) {
+ g_source_destroy (priv->tick_source_channel_bind);
+ g_source_unref (priv->tick_source_channel_bind);
+ priv->tick_source_channel_bind = NULL;
+ }
+
+ if (priv->current_binding_msg) {
+ guint timeout = stun_timer_remainder (&priv->current_binding_msg->timer);
+ if (timeout > 0) {
+ priv->tick_source_channel_bind =
+ priv_timeout_add_with_context (priv, timeout,
+ priv_retransmissions_tick, priv);
+ } else {
+ priv_retransmissions_tick_unlocked (priv);
+ }
+ }
+
+ if (priv->tick_source_create_permission != NULL) {
+ g_source_destroy (priv->tick_source_create_permission);
+ g_source_unref (priv->tick_source_create_permission);
+ priv->tick_source_create_permission = NULL;
+ }
+
+ for (i = priv->pending_permissions, prev = NULL; i; i = next) {
+ guint timeout;
+
+ current_create_permission_msg = (TURNMessage *)i->data;
+ next = i->next;
+
+ timeout = stun_timer_remainder (¤t_create_permission_msg->timer);
+
+ if (timeout > 0) {
+ min_timeout = MIN (min_timeout, timeout);
+ prev = i;
+ } else {
+ /* This could either delete the permission from the list, or it could
+ * refresh it, changing its timeout value */
+ priv_retransmissions_create_permission_tick_unlocked (priv, i);
+ if (prev == NULL)
+ next = priv->pending_permissions;
+ else
+ next = prev->next;
+ }
+ }
+
+ /* We create one timer for the minimal timeout we need */
+ if (min_timeout != G_MAXUINT) {
+ priv->tick_source_create_permission =
+ priv_timeout_add_with_context (priv, min_timeout,
+ priv_retransmissions_create_permission_tick,
+ priv);
+ }
+}
+
+static void
+priv_send_turn_message (UdpTurnPriv *priv, TURNMessage *msg)
+{
+ size_t stun_len = stun_message_length (&msg->message);
+
+ if (priv->current_binding_msg) {
+ g_free (priv->current_binding_msg);
+ priv->current_binding_msg = NULL;
+ }
+
+ if (nice_socket_is_reliable (priv->base_socket)) {
+ _socket_send_wrapped (priv->base_socket, &priv->server_addr,
+ stun_len, (gchar *)msg->buffer, TRUE);
+ stun_timer_start_reliable (&msg->timer,
+ STUN_TIMER_DEFAULT_RELIABLE_TIMEOUT);
+ } else {
+ if (_socket_send_wrapped (priv->base_socket, &priv->server_addr,
+ stun_len, (gchar *)msg->buffer, TRUE) < 0)
+ _socket_send_wrapped (priv->base_socket, &priv->server_addr,
+ stun_len, (gchar *)msg->buffer, FALSE);
+ stun_timer_start (&msg->timer, STUN_TIMER_DEFAULT_TIMEOUT,
+ STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS);
+ }
+
+ priv->current_binding_msg = msg;
+ priv_schedule_tick (priv);
+}
+
+static gboolean
+priv_send_create_permission(UdpTurnPriv *priv,
+ const NiceAddress *peer)
+{
+ guint msg_buf_len;
+ gboolean res = FALSE;
+ TURNMessage *msg = g_new0 (TURNMessage, 1);
+ union {
+ struct sockaddr_storage storage;
+ struct sockaddr addr;
+ } addr;
+
+ /* register this peer as being pening a permission (if not already pending) */
+ if (!priv_has_sent_permission_for_peer (priv, peer)) {
+ priv_add_sent_permission_for_peer (priv, peer);
+ }
+
+ nice_address_copy_to_sockaddr (peer, &addr.addr);
+
+ /* send CreatePermission */
+ msg_buf_len = stun_usage_turn_create_permission(&priv->agent, &msg->message,
+ msg->buffer,
+ sizeof(msg->buffer),
+ priv->username,
+ priv->username_len,
+ priv->password,
+ priv->password_len,
+ priv->cached_realm, priv->cached_realm_len,
+ priv->cached_nonce, priv->cached_nonce_len,
+ &addr.storage,
+ STUN_USAGE_TURN_COMPATIBILITY_RFC5766);
+
+ if (msg_buf_len > 0) {
+ if (nice_socket_is_reliable (priv->base_socket)) {
+ res = _socket_send_wrapped (priv->base_socket, &priv->server_addr,
+ msg_buf_len, (gchar *) msg->buffer, TRUE);
+ } else {
+ res = _socket_send_wrapped (priv->base_socket, &priv->server_addr,
+ msg_buf_len, (gchar *) msg->buffer, TRUE);
+ if (res < 0)
+ res = _socket_send_wrapped (priv->base_socket, &priv->server_addr,
+ msg_buf_len, (gchar *) msg->buffer, FALSE);
+ }
+
+ if (nice_socket_is_reliable (priv->base_socket)) {
+ stun_timer_start_reliable (&msg->timer,
+ STUN_TIMER_DEFAULT_RELIABLE_TIMEOUT);
+ } else {
+ stun_timer_start (&msg->timer, STUN_TIMER_DEFAULT_TIMEOUT,
+ STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS);
+ }
+
+ priv->pending_permissions = g_list_append (priv->pending_permissions, msg);
+ priv_schedule_tick (priv);
+ } else {
+ g_free(msg);
+ }
+
+ return res;
+}
+
+static gboolean
+priv_send_channel_bind (UdpTurnPriv *priv, uint16_t channel,
+ const NiceAddress *peer)
+{
+ uint32_t channel_attr = channel << 16;
+ size_t stun_len;
+ union {
+ struct sockaddr_storage storage;
+ struct sockaddr addr;
+ } sa;
+ TURNMessage *msg = g_new0 (TURNMessage, 1);
+
+ nice_address_copy_to_sockaddr (peer, &sa.addr);
+
+ if (!stun_agent_init_request (&priv->agent, &msg->message,
+ msg->buffer, sizeof(msg->buffer),
+ STUN_CHANNELBIND)) {
+ g_free (msg);
+ return FALSE;
+ }
+
+ if (stun_message_append32 (&msg->message, STUN_ATTRIBUTE_CHANNEL_NUMBER,
+ channel_attr) != STUN_MESSAGE_RETURN_SUCCESS) {
+ g_free (msg);
+ return FALSE;
+ }
+
+ if (stun_message_append_xor_addr (&msg->message, STUN_ATTRIBUTE_PEER_ADDRESS,
+ &sa.storage,
+ sizeof(sa))
+ != STUN_MESSAGE_RETURN_SUCCESS) {
+ g_free (msg);
+ return FALSE;
+ }
+
+ if (priv->username != NULL && priv->username_len > 0 &&
+ priv->cached_realm != NULL && priv->cached_realm_len > 0 &&
+ priv->cached_nonce != NULL && priv->cached_nonce_len > 0) {
+
+ if (stun_message_append_bytes (&msg->message, STUN_ATTRIBUTE_USERNAME,
+ priv->username, priv->username_len)
+ != STUN_MESSAGE_RETURN_SUCCESS) {
+ g_free (msg);
+ return FALSE;
+ }
+
+ if (stun_message_append_bytes (&msg->message, STUN_ATTRIBUTE_REALM,
+ priv->cached_realm, priv->cached_realm_len)
+ != STUN_MESSAGE_RETURN_SUCCESS) {
+ g_free (msg);
+ return 0;
+ }
+
+ if (stun_message_append_bytes (&msg->message, STUN_ATTRIBUTE_NONCE,
+ priv->cached_nonce, priv->cached_nonce_len)
+ != STUN_MESSAGE_RETURN_SUCCESS) {
+ g_free (msg);
+ return 0;
+ }
+ }
+
+ stun_len = stun_agent_finish_message (&priv->agent, &msg->message,
+ priv->password, priv->password_len);
+
+ if (stun_len > 0) {
+ priv_send_turn_message (priv, msg);
+ return TRUE;
+ }
+
+ g_free (msg);
+ return FALSE;
+}
+
+static gboolean
+priv_add_channel_binding (UdpTurnPriv *priv, const NiceAddress *peer)
+{
+ size_t stun_len;
+ union {
+ struct sockaddr_storage storage;
+ struct sockaddr addr;
+ } sa;
+
+ nice_address_copy_to_sockaddr (peer, &sa.addr);
+
+ if (priv->current_binding) {
+ NiceAddress * pending= nice_address_new ();
+ *pending = *peer;
+ priv->pending_bindings = g_list_append (priv->pending_bindings, pending);
+ return FALSE;
+ }
+
+ if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 ||
+ priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766) {
+ uint16_t channel = 0x4000;
+ GList *i = priv->channels;
+ for (; i; i = i->next) {
+ ChannelBinding *b = i->data;
+ if (channel == b->channel) {
+ i = priv->channels;
+ channel++;
+ continue;
+ }
+ }
+
+ if (channel >= 0x4000 && channel < 0xffff) {
+ gboolean ret = priv_send_channel_bind (priv, channel, peer);
+ if (ret) {
+ priv->current_binding = g_new0 (ChannelBinding, 1);
+ priv->current_binding->channel = channel;
+ priv->current_binding->peer = *peer;
+ }
+ return ret;
+ }
+ return FALSE;
+ } else if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_MSN ||
+ priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_OC2007) {
+ TURNMessage *msg = g_new0 (TURNMessage, 1);
+ if (!stun_agent_init_request (&priv->agent, &msg->message,
+ msg->buffer, sizeof(msg->buffer),
+ STUN_OLD_SET_ACTIVE_DST)) {
+ g_free (msg);
+ return FALSE;
+ }
+
+ if (stun_message_append32 (&msg->message, STUN_ATTRIBUTE_MAGIC_COOKIE,
+ TURN_MAGIC_COOKIE)
+ != STUN_MESSAGE_RETURN_SUCCESS) {
+ g_free (msg);
+ return FALSE;
+ }
+
+ if (priv->username != NULL && priv->username_len > 0) {
+ if (stun_message_append_bytes (&msg->message, STUN_ATTRIBUTE_USERNAME,
+ priv->username, priv->username_len)
+ != STUN_MESSAGE_RETURN_SUCCESS) {
+ g_free (msg);
+ return FALSE;
+ }
+ }
+
+ if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_OC2007) {
+ if (priv->ms_connection_id_valid)
+ stun_message_append_ms_connection_id(&msg->message,
+ priv->ms_connection_id, ++priv->ms_sequence_num);
+
+ stun_message_ensure_ms_realm(&msg->message, priv->ms_realm);
+ }
+
+ if (stun_message_append_addr (&msg->message,
+ STUN_ATTRIBUTE_DESTINATION_ADDRESS,
+ &sa.addr, sizeof(sa))
+ != STUN_MESSAGE_RETURN_SUCCESS) {
+ g_free (msg);
+ return FALSE;
+ }
+
+ stun_len = stun_agent_finish_message (&priv->agent, &msg->message,
+ priv->password, priv->password_len);
+
+ if (stun_len > 0) {
+ priv->current_binding = g_new0 (ChannelBinding, 1);
+ priv->current_binding->channel = 0;
+ priv->current_binding->peer = *peer;
+ priv_send_turn_message (priv, msg);
+ return TRUE;
+ }
+ g_free (msg);
+ return FALSE;
+ } else if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE) {
+ priv->current_binding = g_new0 (ChannelBinding, 1);
+ priv->current_binding->channel = 0;
+ priv->current_binding->peer = *peer;
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+
+ return FALSE;
+}
+
+void
+nice_udp_turn_socket_set_ms_realm(NiceSocket *sock, StunMessage *msg)
+{
+ UdpTurnPriv *priv = (UdpTurnPriv *)sock->priv;
+ uint16_t alen;
+ const uint8_t *realm = stun_message_find(msg, STUN_ATTRIBUTE_REALM, &alen);
+
+ if (realm && alen <= STUN_MAX_MS_REALM_LEN) {
+ g_mutex_lock (&mutex);
+ memcpy(priv->ms_realm, realm, alen);
+ priv->ms_realm[alen] = '\0';
+ g_mutex_unlock (&mutex);
+ }
+}
+
+void
+nice_udp_turn_socket_set_ms_connection_id (NiceSocket *sock, StunMessage *msg)
+{
+ UdpTurnPriv *priv = (UdpTurnPriv *)sock->priv;
+ uint16_t alen;
+ const uint8_t *ms_seq_num = stun_message_find(msg,
+ STUN_ATTRIBUTE_MS_SEQUENCE_NUMBER, &alen);
+
+
+ if (ms_seq_num && alen == 24) {
+ g_mutex_lock (&mutex);
+ memcpy (priv->ms_connection_id, ms_seq_num, 20);
+ priv->ms_sequence_num = ntohl((uint32_t)*(ms_seq_num + 20));
+ priv->ms_connection_id_valid = TRUE;
+ g_mutex_unlock (&mutex);
+ }
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2008 Nokia Corporation
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef _UDP_TURN_H
+#define _UDP_TURN_H
+
+
+typedef enum {
+ NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9,
+ NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE,
+ NICE_TURN_SOCKET_COMPATIBILITY_MSN,
+ NICE_TURN_SOCKET_COMPATIBILITY_OC2007,
+ NICE_TURN_SOCKET_COMPATIBILITY_RFC5766,
+} NiceTurnSocketCompatibility;
+
+#include "socket.h"
+#include "stun/stunmessage.h"
+
+
+G_BEGIN_DECLS
+
+guint
+nice_udp_turn_socket_parse_recv_message (NiceSocket *sock, NiceSocket **from_sock,
+ NiceInputMessage *message);
+
+gsize
+nice_udp_turn_socket_parse_recv (NiceSocket *sock, NiceSocket **from_sock,
+ NiceAddress *from, gsize len, guint8 *buf,
+ const NiceAddress *recv_from, const guint8 *recv_buf, gsize recv_len);
+
+gboolean
+nice_udp_turn_socket_set_peer (NiceSocket *sock, NiceAddress *peer);
+
+NiceSocket *
+nice_udp_turn_socket_new (GMainContext *ctx, NiceAddress *addr,
+ NiceSocket *base_socket, const NiceAddress *server_addr,
+ const gchar *username, const gchar *password,
+ NiceTurnSocketCompatibility compatibility);
+
+void
+nice_udp_turn_socket_set_ms_realm(NiceSocket *sock, StunMessage *msg);
+
+void
+nice_udp_turn_socket_set_ms_connection_id (NiceSocket *sock, StunMessage *msg);
+
+void
+nice_udp_turn_socket_cache_realm_nonce (NiceSocket *sock, StunMessage *msg);
+
+
+G_END_DECLS
+
+#endif /* _UDP_TURN_H */
+
--- /dev/null
+#
+# Makefile.am for the Nice Glib ICE library
+#
+# (C) 2006, 2007 Collabora Ltd.
+# (C) 2006, 2007 Nokia Corporation. All rights reserved.
+#
+# Licensed under MPL 1.1/LGPL 2.1. See file COPYING.
+
+SUBDIRS = . tools tests
+
+include $(top_srcdir)/common.mk
+
+AM_CFLAGS = \
+ -std=gnu99 \
+ -DG_LOG_DOMAIN=\"libnice-stun\" \
+ $(LIBNICE_CFLAGS) \
+ $(GNUTLS_CFLAGS) \
+ $(OPENSSL_INCLUDES) \
+ $(NULL)
+AM_CPPFLAGS = -I$(top_srcdir)
+
+if WINDOWS
+ AM_CFLAGS += -DWINVER=0x0501 # _WIN32_WINNT_WINXP
+endif
+
+noinst_LTLIBRARIES = libstun.la
+
+libstun_la_SOURCES = constants.h \
+ stunagent.c stunagent.h \
+ stunmessage.c stunmessage.h \
+ stun5389.c stun5389.h \
+ stuncrc32.c stuncrc32.h \
+ rand.c rand.h \
+ stunhmac.c stunhmac.h \
+ utils.c utils.h \
+ debug.c debug.h \
+ usages/ice.c usages/ice.h \
+ usages/bind.c usages/bind.h \
+ usages/turn.c usages/turn.h \
+ usages/timer.c usages/timer.h
+
+libstun_la_LIBADD = $(LIBRT) $(GNUTLS_LIBS) $(OPENSSL_LIBS) $(OPENSSL_LDFLAGS)
+
+EXTRA_DIST = win32_common.h meson.build
+
+libstun_la_includedir=$(includedir)/stun
+libstun_la_include_HEADERS = stunagent.h stunmessage.h win32_common.h debug.h constants.h
+
+libstun_usage_includedir=$(includedir)/stun/usages
+libstun_usage_include_HEADERS = usages/bind.h usages/ice.h usages/turn.h usages/timer.h
--- /dev/null
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+#
+# Makefile.am for the Nice Glib ICE library
+#
+# (C) 2006, 2007 Collabora Ltd.
+# (C) 2006, 2007 Nokia Corporation. All rights reserved.
+#
+# Licensed under MPL 1.1/LGPL 2.1. See file COPYING.
+
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+@WINDOWS_TRUE@am__append_1 = -DWINVER=0x0501 # _WIN32_WINNT_WINXP
+subdir = stun
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/as-compiler-flag.m4 \
+ $(top_srcdir)/m4/ax_check_openssl.m4 \
+ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/introspection.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(libstun_la_include_HEADERS) \
+ $(libstun_usage_include_HEADERS) $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libstun_la_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+am__dirstamp = $(am__leading_dot)dirstamp
+am_libstun_la_OBJECTS = stunagent.lo stunmessage.lo stun5389.lo \
+ stuncrc32.lo rand.lo stunhmac.lo utils.lo debug.lo \
+ usages/ice.lo usages/bind.lo usages/turn.lo usages/timer.lo
+libstun_la_OBJECTS = $(am_libstun_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/debug.Plo ./$(DEPDIR)/rand.Plo \
+ ./$(DEPDIR)/stun5389.Plo ./$(DEPDIR)/stunagent.Plo \
+ ./$(DEPDIR)/stuncrc32.Plo ./$(DEPDIR)/stunhmac.Plo \
+ ./$(DEPDIR)/stunmessage.Plo ./$(DEPDIR)/utils.Plo \
+ usages/$(DEPDIR)/bind.Plo usages/$(DEPDIR)/ice.Plo \
+ usages/$(DEPDIR)/timer.Plo usages/$(DEPDIR)/turn.Plo
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(libstun_la_SOURCES)
+DIST_SOURCES = $(libstun_la_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
+ ctags-recursive dvi-recursive html-recursive info-recursive \
+ install-data-recursive install-dvi-recursive \
+ install-exec-recursive install-html-recursive \
+ install-info-recursive install-pdf-recursive \
+ install-ps-recursive install-recursive installcheck-recursive \
+ installdirs-recursive pdf-recursive ps-recursive \
+ tags-recursive uninstall-recursive
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(libstun_la_includedir)" \
+ "$(DESTDIR)$(libstun_usage_includedir)"
+HEADERS = $(libstun_la_include_HEADERS) \
+ $(libstun_usage_include_HEADERS)
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+am__recursive_targets = \
+ $(RECURSIVE_TARGETS) \
+ $(RECURSIVE_CLEAN_TARGETS) \
+ $(am__extra_recursive_targets)
+AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
+ distdir distdir-am
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/common.mk \
+ $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+pkgincludedir = $(includedir)/nice
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCACHE_DISABLE = @CCACHE_DISABLE@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GST010_CFLAGS = @GST010_CFLAGS@
+GST010_LIBS = @GST010_LIBS@
+GST_CFLAGS = @GST_CFLAGS@
+GST_CHECK_CFLAGS = @GST_CHECK_CFLAGS@
+GST_CHECK_LIBS = @GST_CHECK_LIBS@
+GST_LIBS = @GST_LIBS@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@
+GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@
+GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@
+GTKDOC_MKPDF = @GTKDOC_MKPDF@
+GTKDOC_REBASE = @GTKDOC_REBASE@
+GUPNP_CFLAGS = @GUPNP_CFLAGS@
+GUPNP_LIBS = @GUPNP_LIBS@
+GUPNP_PACKAGES = @GUPNP_PACKAGES@
+GUPNP_PACKAGES_PRIVATE = @GUPNP_PACKAGES_PRIVATE@
+GUPNP_PACKAGES_PUBLIC = @GUPNP_PACKAGES_PUBLIC@
+HAVE_GUPNP = @HAVE_GUPNP@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@
+INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@
+INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@
+INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@
+INTROSPECTION_LIBS = @INTROSPECTION_LIBS@
+INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@
+INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
+INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBNICE_CFLAGS = @LIBNICE_CFLAGS@
+LIBNICE_LT_LDFLAGS = @LIBNICE_LT_LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBRT = @LIBRT@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NICE_PACKAGES_PRIVATE = @NICE_PACKAGES_PRIVATE@
+NICE_PACKAGES_PUBLIC = @NICE_PACKAGES_PUBLIC@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_INCLUDES = @OPENSSL_INCLUDES@
+OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+UPNP_ENABLED = @UPNP_ENABLED@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gstplugin010dir = @gstplugin010dir@
+gstplugindir = @gstplugindir@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = . tools tests
+CLEANFILES = *.gcno *.gcda
+LOG_DRIVER = $(top_srcdir)/scripts/valgrind-test-driver
+AM_CFLAGS = -std=gnu99 -DG_LOG_DOMAIN=\"libnice-stun\" \
+ $(LIBNICE_CFLAGS) $(GNUTLS_CFLAGS) $(OPENSSL_INCLUDES) $(NULL) \
+ $(am__append_1)
+AM_CPPFLAGS = -I$(top_srcdir)
+noinst_LTLIBRARIES = libstun.la
+libstun_la_SOURCES = constants.h \
+ stunagent.c stunagent.h \
+ stunmessage.c stunmessage.h \
+ stun5389.c stun5389.h \
+ stuncrc32.c stuncrc32.h \
+ rand.c rand.h \
+ stunhmac.c stunhmac.h \
+ utils.c utils.h \
+ debug.c debug.h \
+ usages/ice.c usages/ice.h \
+ usages/bind.c usages/bind.h \
+ usages/turn.c usages/turn.h \
+ usages/timer.c usages/timer.h
+
+libstun_la_LIBADD = $(LIBRT) $(GNUTLS_LIBS) $(OPENSSL_LIBS) $(OPENSSL_LDFLAGS)
+EXTRA_DIST = win32_common.h meson.build
+libstun_la_includedir = $(includedir)/stun
+libstun_la_include_HEADERS = stunagent.h stunmessage.h win32_common.h debug.h constants.h
+libstun_usage_includedir = $(includedir)/stun/usages
+libstun_usage_include_HEADERS = usages/bind.h usages/ice.h usages/turn.h usages/timer.h
+all: all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/common.mk $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu stun/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu stun/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+$(top_srcdir)/common.mk $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+usages/$(am__dirstamp):
+ @$(MKDIR_P) usages
+ @: > usages/$(am__dirstamp)
+usages/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) usages/$(DEPDIR)
+ @: > usages/$(DEPDIR)/$(am__dirstamp)
+usages/ice.lo: usages/$(am__dirstamp) usages/$(DEPDIR)/$(am__dirstamp)
+usages/bind.lo: usages/$(am__dirstamp) \
+ usages/$(DEPDIR)/$(am__dirstamp)
+usages/turn.lo: usages/$(am__dirstamp) \
+ usages/$(DEPDIR)/$(am__dirstamp)
+usages/timer.lo: usages/$(am__dirstamp) \
+ usages/$(DEPDIR)/$(am__dirstamp)
+
+libstun.la: $(libstun_la_OBJECTS) $(libstun_la_DEPENDENCIES) $(EXTRA_libstun_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(LINK) $(libstun_la_OBJECTS) $(libstun_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+ -rm -f usages/*.$(OBJEXT)
+ -rm -f usages/*.lo
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debug.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rand.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stun5389.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stunagent.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stuncrc32.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stunhmac.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stunmessage.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utils.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@usages/$(DEPDIR)/bind.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@usages/$(DEPDIR)/ice.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@usages/$(DEPDIR)/timer.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@usages/$(DEPDIR)/turn.Plo@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+ -rm -rf usages/.libs usages/_libs
+install-libstun_la_includeHEADERS: $(libstun_la_include_HEADERS)
+ @$(NORMAL_INSTALL)
+ @list='$(libstun_la_include_HEADERS)'; test -n "$(libstun_la_includedir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(libstun_la_includedir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(libstun_la_includedir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libstun_la_includedir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(libstun_la_includedir)" || exit $$?; \
+ done
+
+uninstall-libstun_la_includeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(libstun_la_include_HEADERS)'; test -n "$(libstun_la_includedir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(libstun_la_includedir)'; $(am__uninstall_files_from_dir)
+install-libstun_usage_includeHEADERS: $(libstun_usage_include_HEADERS)
+ @$(NORMAL_INSTALL)
+ @list='$(libstun_usage_include_HEADERS)'; test -n "$(libstun_usage_includedir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(libstun_usage_includedir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(libstun_usage_includedir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libstun_usage_includedir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(libstun_usage_includedir)" || exit $$?; \
+ done
+
+uninstall-libstun_usage_includeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(libstun_usage_include_HEADERS)'; test -n "$(libstun_usage_includedir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(libstun_usage_includedir)'; $(am__uninstall_files_from_dir)
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run 'make' without going through this Makefile.
+# To change the values of 'make' variables: instead of editing Makefiles,
+# (1) if the variable is set in 'config.status', edit 'config.status'
+# (which will cause the Makefiles to be regenerated when you run 'make');
+# (2) otherwise, pass the desired values on the 'make' command line.
+$(am__recursive_targets):
+ @fail=; \
+ if $(am__make_keepgoing); then \
+ failcom='fail=yes'; \
+ else \
+ failcom='exit 1'; \
+ fi; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-recursive
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-recursive
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-recursive
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ $(am__make_dryrun) \
+ || test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs: installdirs-recursive
+installdirs-am:
+ for dir in "$(DESTDIR)$(libstun_la_includedir)" "$(DESTDIR)$(libstun_usage_includedir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -rm -f usages/$(DEPDIR)/$(am__dirstamp)
+ -rm -f usages/$(am__dirstamp)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f ./$(DEPDIR)/debug.Plo
+ -rm -f ./$(DEPDIR)/rand.Plo
+ -rm -f ./$(DEPDIR)/stun5389.Plo
+ -rm -f ./$(DEPDIR)/stunagent.Plo
+ -rm -f ./$(DEPDIR)/stuncrc32.Plo
+ -rm -f ./$(DEPDIR)/stunhmac.Plo
+ -rm -f ./$(DEPDIR)/stunmessage.Plo
+ -rm -f ./$(DEPDIR)/utils.Plo
+ -rm -f usages/$(DEPDIR)/bind.Plo
+ -rm -f usages/$(DEPDIR)/ice.Plo
+ -rm -f usages/$(DEPDIR)/timer.Plo
+ -rm -f usages/$(DEPDIR)/turn.Plo
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am: install-libstun_la_includeHEADERS \
+ install-libstun_usage_includeHEADERS
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f ./$(DEPDIR)/debug.Plo
+ -rm -f ./$(DEPDIR)/rand.Plo
+ -rm -f ./$(DEPDIR)/stun5389.Plo
+ -rm -f ./$(DEPDIR)/stunagent.Plo
+ -rm -f ./$(DEPDIR)/stuncrc32.Plo
+ -rm -f ./$(DEPDIR)/stunhmac.Plo
+ -rm -f ./$(DEPDIR)/stunmessage.Plo
+ -rm -f ./$(DEPDIR)/utils.Plo
+ -rm -f usages/$(DEPDIR)/bind.Plo
+ -rm -f usages/$(DEPDIR)/ice.Plo
+ -rm -f usages/$(DEPDIR)/timer.Plo
+ -rm -f usages/$(DEPDIR)/turn.Plo
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-libstun_la_includeHEADERS \
+ uninstall-libstun_usage_includeHEADERS
+
+.MAKE: $(am__recursive_targets) install-am install-strip
+
+.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \
+ am--depfiles check check-am clean clean-generic clean-libtool \
+ clean-noinstLTLIBRARIES cscopelist-am ctags ctags-am distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am \
+ install-libstun_la_includeHEADERS \
+ install-libstun_usage_includeHEADERS install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs installdirs-am \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \
+ uninstall-libstun_la_includeHEADERS \
+ uninstall-libstun_usage_includeHEADERS
+
+.PRECIOUS: Makefile
+
+
+check-valgrind:
+ $(MAKE) TESTS_ENVIRONMENT="USE_VALGRIND=1 " check
+
+.PHONY: check-valgrind
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2008 Nokia Corporation. All rights reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef _STUN_CONSTANTS_H
+#define _STUN_CONSTANTS_H
+
+
+/**
+ * SECTION:stunconstants
+ * @short_description: STUN constants
+ * @include: stun/constants.h
+ * @stability: Stable
+ *
+ * Various constants defining parts of the STUN and TURN protocols and
+ * on-the-wire packet formats.
+ */
+
+/**
+ * STUN_ATTRIBUTE_LENGTH_LEN:
+ *
+ * Length of the length field of a STUN attribute (in bytes).
+ */
+/**
+ * STUN_ATTRIBUTE_LENGTH_POS:
+ *
+ * Offset of the length field of a STUN attribute (in bytes).
+ */
+/**
+ * STUN_ATTRIBUTE_TYPE_LEN:
+ *
+ * Length of the type field of a STUN attribute (in bytes).
+ */
+/**
+ * STUN_ATTRIBUTE_TYPE_POS:
+ *
+ * Offset of the type field of a STUN attribute (in bytes).
+ */
+/**
+ * STUN_ATTRIBUTE_VALUE_POS:
+ *
+ * Offset of the value field of a STUN attribute (in bytes).
+ */
+/**
+ * STUN_ID_LEN:
+ *
+ * Length of the ID field of a STUN message (in bytes).
+ */
+/**
+ * STUN_MAGIC_COOKIE:
+ *
+ * Magic cookie value used to identify STUN messages.
+ */
+/**
+ * TURN_MAGIC_COOKIE:
+ *
+ * Magic cookie value used to identify TURN messages.
+ */
+/**
+ * STUN_MAX_MESSAGE_SIZE_IPV4:
+ *
+ * Maximum size of a STUN message sent over IPv4 (in bytes).
+ */
+/**
+ * STUN_MAX_MESSAGE_SIZE_IPV6:
+ *
+ * Maximum size of a STUN message sent over IPv6 (in bytes).
+ */
+/**
+ * STUN_MESSAGE_ATTRIBUTES_POS:
+ *
+ * Offset of the attributes of a STUN message (in bytes).
+ */
+/**
+ * STUN_MESSAGE_HEADER_LENGTH:
+ *
+ * Total length of a STUN message header (in bytes).
+ */
+/**
+ * STUN_MESSAGE_LENGTH_LEN:
+ *
+ * Length of the length field of a STUN message (in bytes).
+ */
+/**
+ * STUN_MESSAGE_LENGTH_POS:
+ *
+ * Offset of the length field of a STUN message (in bytes).
+ */
+/**
+ * STUN_MESSAGE_TRANS_ID_LEN:
+ *
+ * Length of the transaction ID field of a STUN message (in bytes).
+ */
+/**
+ * STUN_MESSAGE_TRANS_ID_POS:
+ *
+ * Offset of the transaction ID field of a STUN message (in bytes).
+ */
+/**
+ * STUN_MESSAGE_TYPE_LEN:
+ *
+ * Length of the type field of a STUN message (in bytes).
+ */
+/**
+ * STUN_MESSAGE_TYPE_POS:
+ *
+ * Offset of the type field of a STUN message (in bytes).
+ */
+
+#define STUN_MESSAGE_TYPE_POS 0
+#define STUN_MESSAGE_TYPE_LEN 2
+#define STUN_MESSAGE_LENGTH_POS \
+ (STUN_MESSAGE_TYPE_POS + STUN_MESSAGE_TYPE_LEN)
+#define STUN_MESSAGE_LENGTH_LEN 2
+#define STUN_MESSAGE_TRANS_ID_POS \
+ (STUN_MESSAGE_LENGTH_POS + STUN_MESSAGE_LENGTH_LEN)
+#define STUN_MESSAGE_TRANS_ID_LEN 16
+#define STUN_MESSAGE_ATTRIBUTES_POS \
+ (STUN_MESSAGE_TRANS_ID_POS + STUN_MESSAGE_TRANS_ID_LEN)
+
+#define STUN_MESSAGE_HEADER_LENGTH STUN_MESSAGE_ATTRIBUTES_POS
+
+#define STUN_ATTRIBUTE_TYPE_POS 0
+#define STUN_ATTRIBUTE_TYPE_LEN 2
+#define STUN_ATTRIBUTE_LENGTH_POS \
+ (STUN_ATTRIBUTE_TYPE_POS + STUN_ATTRIBUTE_TYPE_LEN)
+#define STUN_ATTRIBUTE_LENGTH_LEN 2
+#define STUN_ATTRIBUTE_VALUE_POS \
+ (STUN_ATTRIBUTE_LENGTH_POS + STUN_ATTRIBUTE_LENGTH_LEN)
+
+/**
+ * STUN_ATTRIBUTE_HEADER_LENGTH:
+ *
+ * Length of a single STUN attribute header (in bytes).
+ */
+#define STUN_ATTRIBUTE_HEADER_LENGTH STUN_ATTRIBUTE_VALUE_POS
+
+
+#define STUN_MAX_MESSAGE_SIZE_IPV4 576
+#define STUN_MAX_MESSAGE_SIZE_IPV6 1280
+/* #define STUN_MAX_MESSAGE_SIZE STUN_MAX_MESSAGE_SIZE_IPV4 */
+
+#define STUN_ID_LEN 16
+
+/**
+ * STUN_AGENT_MAX_SAVED_IDS:
+ *
+ * Maximum number of simultaneously ongoing STUN transactions.
+ */
+#define STUN_AGENT_MAX_SAVED_IDS 200
+
+/**
+ * STUN_AGENT_MAX_UNKNOWN_ATTRIBUTES:
+ *
+ * Maximum number of unknown attribute which can be handled in a single STUN
+ * message.
+ */
+#define STUN_AGENT_MAX_UNKNOWN_ATTRIBUTES 256
+
+#define STUN_MAGIC_COOKIE 0x2112A442
+#define TURN_MAGIC_COOKIE 0x72c64bc6
+
+#ifndef TRUE
+#define TRUE (1 == 1)
+#endif
+
+#ifndef FALSE
+#define FALSE (0 == 1)
+#endif
+
+#endif /* _STUN_CONSTANTS_H */
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2007 Nokia Corporation. All rights reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "debug.h"
+
+
+static int debug_enabled = 0;
+
+void stun_debug_enable (void) {
+ debug_enabled = 1;
+}
+void stun_debug_disable (void) {
+ debug_enabled = 0;
+}
+
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
+#define GNUC_PRINTF(format_idx, arg_idx) \
+ __attribute__((__format__ (__printf__, format_idx, arg_idx)))
+#else
+#define GNUC_PRINTF( format_idx, arg_idx)
+#endif
+
+static void
+default_handler (const char *format, va_list ap) GNUC_PRINTF (1, 0);
+
+static void
+default_handler (const char *format, va_list ap)
+{
+ vfprintf (stderr, format, ap);
+ fprintf (stderr, "\n");
+}
+
+static StunDebugHandler handler = default_handler;
+
+void stun_debug (const char *fmt, ...)
+{
+ va_list ap;
+ if (debug_enabled) {
+ va_start (ap, fmt);
+ handler (fmt, ap);
+ va_end (ap);
+ }
+}
+
+void stun_debug_bytes (const char *prefix, const void *data, size_t len)
+{
+ size_t i;
+ size_t prefix_len = strlen (prefix);
+ char *bytes;
+ char *j;
+ unsigned char k;
+ const char *hex = "0123456789abcdef";
+
+ if (!debug_enabled)
+ return;
+
+ bytes = malloc (prefix_len + 2 + (len * 2) + 1);
+ bytes[0] = 0;
+ strcpy (bytes, prefix);
+ strcpy (bytes + prefix_len, "0x");
+
+ j = bytes + prefix_len + 2;
+ for (i = 0; i < len; i++) {
+ k = ((const unsigned char *)data)[i];
+ j[0] = hex[(k & 0xf0) >> 4];
+ j[1] = hex[k & 0xf];
+ j = j + 2;
+ }
+ j[0] = 0;
+ stun_debug ("%s", bytes);
+ free (bytes);
+}
+
+
+void stun_set_debug_handler (StunDebugHandler _handler)
+{
+ if (_handler == NULL)
+ _handler = default_handler;
+
+ handler = _handler;
+}
+
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2007 Nokia Corporation. All rights reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef STUN_DEBUG_H
+#define STUN_DEBUG_H
+
+#include <stddef.h>
+#include <stdarg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * stun_debug_enable:
+ *
+ * Enable debug messages to stderr
+ */
+void stun_debug_enable (void);
+
+/**
+ * stun_debug_disable:
+ *
+ * Disable debug messages to stderr
+ */
+void stun_debug_disable (void);
+
+/**
+ * StunDebugHandler:
+ * @format: printf()-style debug message format string
+ * @ap: Parameters to substitute into message placeholders
+ *
+ * Callback for a debug message from the STUN code.
+ */
+#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4))
+typedef void (*StunDebugHandler) (const char *format, va_list ap)
+ __attribute__((__format__ (__printf__, 1, 0)));
+#else
+typedef void (*StunDebugHandler) (const char *format, va_list ap);
+#endif
+
+/**
+ * stun_set_debug_handler:
+ * @handler: (nullable): Handler for STUN debug messages, or %NULL to use the
+ * default
+ *
+ * Set a callback function to be invoked for each debug message from the STUN
+ * code. The callback will only be invoked if STUN debugging is enabled using
+ * stun_debug_enable().
+ *
+ * The default callback prints the formatted debug message to stderr.
+ */
+void stun_set_debug_handler (StunDebugHandler handler);
+
+#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4))
+void stun_debug (const char *fmt, ...)
+ __attribute__((__format__ (__printf__, 1, 2)));
+#else
+void stun_debug (const char *fmt, ...);
+#endif
+void stun_debug_bytes (const char *prefix, const void *data, size_t len);
+
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif /* STUN_DEBUG_H */
--- /dev/null
+stun_sources = [
+ 'stunagent.c',
+ 'stunmessage.c',
+ 'stun5389.c',
+ 'stuncrc32.c',
+ 'rand.c',
+ 'stunhmac.c',
+ 'utils.c',
+ 'debug.c',
+ 'usages/ice.c',
+ 'usages/bind.c',
+ 'usages/turn.c',
+ 'usages/timer.c',
+]
+
+install_headers(
+ 'stunagent.h',
+ 'stunmessage.h',
+ 'win32_common.h', # installed unconditionally?!
+ 'debug.h',
+ 'constants.h', subdir: 'stun')
+
+install_headers(
+ 'usages/bind.h',
+ 'usages/ice.h',
+ 'usages/turn.h',
+ 'usages/timer.h', subdir: 'stun/usages')
+
+libstun = static_library('stun', stun_sources,
+ c_args: ['-DG_LOG_DOMAIN="libnice-stun"'],
+ include_directories: nice_incs,
+ dependencies: nice_deps,
+ install: false)
+
+subdir('tools')
+
+if not get_option('tests').disabled()
+ subdir('tests')
+endif
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008 Collabora Ltd. All rights reserved.
+ * Contact: Youness Alaoui
+ * (C) 2008 Nokia Corporation. All rights reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "rand.h"
+
+
+#ifdef _WIN32
+
+#include <windows.h>
+#include <wincrypt.h>
+
+void nice_RAND_nonce (uint8_t *dst, int len)
+{
+ HCRYPTPROV hCryptProv;
+ LPCSTR container = "Libnice key container";
+
+ if(!CryptAcquireContext(&hCryptProv, container, NULL, PROV_RSA_FULL, 0)) {
+ /* non existing container. try to create a new one */
+ // I hope this cast here doesn't cause issues
+ // gcc was complaining about comparing signed and unsigned values
+ if (GetLastError() == (DWORD) NTE_BAD_KEYSET) {
+ if(!CryptAcquireContext(&hCryptProv, container, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) {
+ return;
+ }
+ }
+ return;
+ }
+
+ CryptGenRandom (hCryptProv, len, dst);
+
+ CryptReleaseContext(hCryptProv,0);
+}
+#else
+
+#ifdef HAVE_OPENSSL
+
+#include <openssl/rand.h>
+
+void nice_RAND_nonce (uint8_t *dst, int len)
+{
+ RAND_bytes (dst, len);
+}
+
+#else
+
+#include <sys/types.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/crypto.h>
+
+void nice_RAND_nonce (uint8_t *dst, int len)
+{
+ gnutls_rnd (GNUTLS_RND_NONCE, dst, len);
+}
+
+#endif /* HAVE_OPENSSL */
+
+#endif /* _WIN32 */
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008 Collabora Ltd. All rights reserved.
+ * Contact: Youness Alaoui
+ * (C) 2008 Nokia Corporation. All rights reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+
+#ifndef RAND_H
+#define RAND_H
+
+
+#ifdef _WIN32
+#include "win32_common.h"
+#else
+#include <stdint.h>
+#endif
+
+void nice_RAND_nonce (uint8_t *dst, int len);
+
+#endif /* RAND_H */
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2007 Nokia Corporation. All rights reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef _WIN32
+#include <winsock2.h>
+#else
+#include <sys/socket.h>
+#include <netinet/in.h> /* htons() */
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "stun5389.h"
+#include "stuncrc32.h"
+#include "stunmessage.h"
+
+
+static const char utf8_skip_data[256] = {
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+ 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1
+};
+
+#define next_utf8_char(p) (char *)((p) + \
+ utf8_skip_data[*(const unsigned char *)(p)])
+
+uint32_t stun_fingerprint (const uint8_t *msg, size_t len,
+ bool wlm2009_stupid_crc32_typo)
+{
+ crc_data data[3];
+ uint16_t fakelen = htons (len - 20u);
+
+ // assert (len >= 28u);
+
+ data[0].buf = (void *)msg;
+ data[0].len = 2;
+ data[1].buf = (uint8_t *)&fakelen;
+ data[1].len = 2;
+ data[2].buf = (void *)(msg + 4);
+ /* first 4 bytes done, last 8 bytes not summed */
+ data[2].len = len - 12u;
+
+ return htonl (stun_crc32 (data, 3, wlm2009_stupid_crc32_typo) ^ 0x5354554e);
+}
+
+bool stun_message_has_cookie (const StunMessage *msg)
+{
+ StunTransactionId id;
+ uint32_t cookie = htonl (STUN_MAGIC_COOKIE);
+ stun_message_id (msg, id);
+ return memcmp (id, &cookie, sizeof (cookie)) == 0;
+}
+
+
+StunMessageReturn stun_message_append_software (StunMessage *msg,
+ const char *software)
+{
+ int len = 0;
+ const char *ptr = NULL;
+
+ if (software == NULL)
+ software = PACKAGE_STRING;
+
+ ptr = software;
+ while (*ptr && len < 128) {
+ ptr = next_utf8_char (ptr);
+ len++;
+ }
+
+ return stun_message_append_bytes (msg, STUN_ATTRIBUTE_SOFTWARE, software,
+ ptr - software);
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2006, 2007 Collabora Ltd.
+ * Contact: Dafydd Harries
+ * (C) 2006, 2007 Nokia Corporation. All rights reserved.
+ * Contact: Rémi Denis-Courmont
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Rémi Denis-Courmont, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+
+#ifndef _STUN_5389_H
+#define _STUN_5389_H
+
+
+#ifdef _WIN32
+#include "win32_common.h"
+#else
+# include <stdint.h>
+# include <stdbool.h>
+#endif
+# include <sys/types.h>
+
+#include "stunmessage.h"
+/*
+ * Computes the FINGERPRINT checksum of a STUN message.
+ * @param msg pointer to the STUN message
+ * @param len size of the message from header (inclusive) and up to
+ * FINGERPRINT attribute (inclusive)
+ *
+ * @return fingerprint value in <b>host</b> byte order.
+ */
+uint32_t stun_fingerprint (const uint8_t *msg, size_t len,
+ bool wlm2009_stupid_crc32_typo);
+
+StunMessageReturn stun_message_append_software (StunMessage *msg,
+ const char *software);
+
+
+#endif /* _STUN_5389_H */
+
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2008-2009 Nokia Corporation. All rights reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "stunmessage.h"
+#include "stunagent.h"
+#include "stunhmac.h"
+#include "stun5389.h"
+#include "utils.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+
+static bool stun_agent_is_unknown (StunAgent *agent, uint16_t type);
+static unsigned stun_agent_find_unknowns (StunAgent *agent,
+ const StunMessage * msg, uint16_t *list, unsigned max);
+
+void stun_agent_init (StunAgent *agent, const uint16_t *known_attributes,
+ StunCompatibility compatibility, StunAgentUsageFlags usage_flags)
+{
+ int i;
+
+ agent->known_attributes = (uint16_t *) known_attributes;
+ agent->compatibility = compatibility;
+ agent->usage_flags = usage_flags;
+ agent->software_attribute = NULL;
+ agent->ms_ice2_send_legacy_connchecks =
+ compatibility == STUN_COMPATIBILITY_MSICE2;
+
+ for (i = 0; i < STUN_AGENT_MAX_SAVED_IDS; i++) {
+ agent->sent_ids[i].valid = FALSE;
+ }
+}
+
+
+bool stun_agent_default_validater (StunAgent *agent,
+ StunMessage *message, uint8_t *username, uint16_t username_len,
+ uint8_t **password, size_t *password_len, void *user_data)
+{
+ StunDefaultValidaterData* val = (StunDefaultValidaterData *) user_data;
+ int i;
+
+ for (i = 0; val && val[i].username ; i++) {
+#if 0
+ stun_debug ("Comparing username of size %d and %" PRIuPTR ": %d",
+ username_len, val[i].username_len,
+ (memcmp (username, val[i].username, username_len) == 0));
+#endif
+ stun_debug_bytes (" First username: ", username, username_len);
+ stun_debug_bytes (" Second username: ", val[i].username,
+ val[i].username_len);
+ if (username_len == val[i].username_len &&
+ memcmp (username, val[i].username, username_len) == 0) {
+ *password = (uint8_t *) val[i].password;
+ *password_len = val[i].password_len;
+ stun_debug ("Found valid username, returning password : '%s'", *password);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+
+}
+
+static bool stun_agent_check_fingerprint(StunAgent *agent, StunMessage *msg)
+{
+ uint32_t fpr;
+ uint32_t crc32;
+ uint16_t msg_len;
+
+ /* Looks for FINGERPRINT */
+ if (stun_message_find32 (msg, STUN_ATTRIBUTE_FINGERPRINT, &fpr) !=
+ STUN_MESSAGE_RETURN_SUCCESS) {
+ stun_debug ("STUN demux error: no FINGERPRINT attribute!");
+ return FALSE;
+ }
+
+ msg_len = stun_message_length (msg);
+
+ /* Checks FINGERPRINT */
+ crc32 = stun_fingerprint (msg->buffer, msg_len, FALSE);
+ fpr = ntohl (fpr);
+ if (fpr != crc32) {
+ uint16_t palen;
+
+ /* [MS-ICE2] 3.1.4.8.2 Connectivity Checks Phase - legacy compatibility */
+ if (agent->compatibility == STUN_COMPATIBILITY_MSICE2 &&
+ stun_message_find (msg, STUN_ATTRIBUTE_MS_IMPLEMENTATION_VERSION,
+ &palen) == NULL &&
+ fpr == stun_fingerprint (msg->buffer, msg_len, TRUE)) {
+ return TRUE;
+ }
+
+ stun_debug ("STUN demux error: bad fingerprint: 0x%08x, expected: 0x%08x!",
+ fpr, crc32);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+StunValidationStatus stun_agent_validate (StunAgent *agent, StunMessage *msg,
+ const uint8_t *buffer, size_t buffer_len,
+ StunMessageIntegrityValidate validater, void * validater_data)
+{
+ StunTransactionId msg_id;
+ int len;
+ uint8_t *username = NULL;
+ uint16_t username_len;
+ uint8_t *key = NULL;
+ size_t key_len;
+ uint8_t *hash;
+ uint8_t sha[20];
+ uint16_t hlen;
+ uint32_t implementation_version;
+ int sent_id_idx = -1;
+ uint16_t unknown;
+ int error_code;
+ int ignore_credentials = 0;
+ uint8_t long_term_key[16] = { 0 };
+ bool long_term_key_valid = FALSE;
+
+ len = stun_message_validate_buffer_length (buffer, buffer_len,
+ !(agent->usage_flags & STUN_AGENT_USAGE_NO_ALIGNED_ATTRIBUTES));
+ if (len == STUN_MESSAGE_BUFFER_INVALID) {
+ return STUN_VALIDATION_NOT_STUN;
+ } else if (len == STUN_MESSAGE_BUFFER_INCOMPLETE) {
+ return STUN_VALIDATION_INCOMPLETE_STUN;
+ } else if (len != (int) buffer_len) {
+ return STUN_VALIDATION_NOT_STUN;
+ }
+
+ msg->buffer = (uint8_t *) buffer;
+ msg->buffer_len = buffer_len;
+ msg->agent = agent;
+ msg->key = NULL;
+ msg->key_len = 0;
+ msg->long_term_valid = FALSE;
+
+ /* TODO: reject it or not ? */
+ if ((agent->compatibility == STUN_COMPATIBILITY_RFC5389 ||
+ agent->compatibility == STUN_COMPATIBILITY_MSICE2) &&
+ !stun_message_has_cookie (msg)) {
+ stun_debug ("STUN demux error: no cookie!");
+ return STUN_VALIDATION_BAD_REQUEST;
+ }
+
+ if ((agent->compatibility == STUN_COMPATIBILITY_RFC5389 ||
+ agent->compatibility == STUN_COMPATIBILITY_MSICE2) &&
+ agent->usage_flags & STUN_AGENT_USAGE_USE_FINGERPRINT) {
+ if (stun_agent_check_fingerprint(agent, msg) == FALSE) {
+ return STUN_VALIDATION_BAD_REQUEST;
+ }
+
+ stun_debug ("STUN demux: OK!");
+ }
+
+ if (stun_message_get_class (msg) == STUN_RESPONSE ||
+ stun_message_get_class (msg) == STUN_ERROR) {
+ stun_message_id (msg, msg_id);
+ for (sent_id_idx = 0; sent_id_idx < STUN_AGENT_MAX_SAVED_IDS; sent_id_idx++) {
+ if (agent->sent_ids[sent_id_idx].valid == TRUE &&
+ agent->sent_ids[sent_id_idx].method == stun_message_get_method (msg) &&
+ memcmp (msg_id, agent->sent_ids[sent_id_idx].id,
+ sizeof(StunTransactionId)) == 0) {
+
+ key = agent->sent_ids[sent_id_idx].key;
+ key_len = agent->sent_ids[sent_id_idx].key_len;
+ memcpy (long_term_key, agent->sent_ids[sent_id_idx].long_term_key,
+ sizeof(long_term_key));
+ long_term_key_valid = agent->sent_ids[sent_id_idx].long_term_valid;
+ break;
+ }
+ }
+ if (sent_id_idx == STUN_AGENT_MAX_SAVED_IDS) {
+ return STUN_VALIDATION_UNMATCHED_RESPONSE;
+ }
+ }
+
+ ignore_credentials =
+ (agent->usage_flags & STUN_AGENT_USAGE_IGNORE_CREDENTIALS) ||
+ (stun_message_get_class (msg) == STUN_ERROR &&
+ stun_message_find_error (msg, &error_code) ==
+ STUN_MESSAGE_RETURN_SUCCESS &&
+ (error_code == STUN_ERROR_BAD_REQUEST ||
+ error_code == STUN_ERROR_UNAUTHORIZED ||
+ error_code == STUN_ERROR_STALE_NONCE ||
+ error_code == STUN_ERROR_TRY_ALTERNATE)) ||
+ (stun_message_get_class (msg) == STUN_INDICATION &&
+ (agent->usage_flags & STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS ||
+ agent->usage_flags & STUN_AGENT_USAGE_NO_INDICATION_AUTH));
+
+ if (key == NULL &&
+ ignore_credentials == 0 &&
+ (stun_message_get_class (msg) == STUN_REQUEST ||
+ stun_message_get_class (msg) == STUN_INDICATION) &&
+ (((agent->usage_flags & STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS) &&
+ (!stun_message_has_attribute (msg, STUN_ATTRIBUTE_USERNAME) ||
+ !stun_message_has_attribute (msg, STUN_ATTRIBUTE_MESSAGE_INTEGRITY))) ||
+ ((agent->usage_flags & STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS) &&
+ stun_message_get_class (msg) == STUN_REQUEST &&
+ (!stun_message_has_attribute (msg, STUN_ATTRIBUTE_USERNAME) ||
+ !stun_message_has_attribute (msg, STUN_ATTRIBUTE_MESSAGE_INTEGRITY) ||
+ !stun_message_has_attribute (msg, STUN_ATTRIBUTE_NONCE) ||
+ !stun_message_has_attribute (msg, STUN_ATTRIBUTE_REALM))) ||
+ ((agent->usage_flags & STUN_AGENT_USAGE_IGNORE_CREDENTIALS) == 0 &&
+ stun_message_has_attribute (msg, STUN_ATTRIBUTE_USERNAME) &&
+ !stun_message_has_attribute (msg, STUN_ATTRIBUTE_MESSAGE_INTEGRITY)))) {
+ return STUN_VALIDATION_UNAUTHORIZED_BAD_REQUEST;
+ }
+
+ if (stun_message_has_attribute (msg, STUN_ATTRIBUTE_MESSAGE_INTEGRITY) &&
+ ((key == NULL && ignore_credentials == 0) ||
+ (agent->usage_flags & STUN_AGENT_USAGE_FORCE_VALIDATER))) {
+ username_len = 0;
+ username = (uint8_t *) stun_message_find (msg, STUN_ATTRIBUTE_USERNAME,
+ &username_len);
+ if (validater == NULL ||
+ validater (agent, msg, username, username_len,
+ &key, &key_len, validater_data) == FALSE) {
+ return STUN_VALIDATION_UNAUTHORIZED;
+ }
+ }
+
+ if (ignore_credentials == 0 && key != NULL && key_len > 0) {
+ hash = (uint8_t *) stun_message_find (msg,
+ STUN_ATTRIBUTE_MESSAGE_INTEGRITY, &hlen);
+
+ if (hash) {
+ /* We must give the size from start to the end of the attribute
+ because you might have a FINGERPRINT attribute after it... */
+ if (agent->usage_flags & STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS) {
+ uint8_t *realm = NULL;
+ uint16_t realm_len;
+ uint8_t md5[16];
+
+ if (long_term_key_valid) {
+ memcpy (md5, long_term_key, sizeof (md5));
+ } else {
+ realm = (uint8_t *) stun_message_find (msg, STUN_ATTRIBUTE_REALM, &realm_len);
+ username = (uint8_t *) stun_message_find (msg,
+ STUN_ATTRIBUTE_USERNAME, &username_len);
+ if (username == NULL || realm == NULL) {
+ return STUN_VALIDATION_UNAUTHORIZED;
+ }
+ stun_hash_creds (realm, realm_len,
+ username, username_len,
+ key, key_len, md5);
+ }
+
+ memcpy (msg->long_term_key, md5, sizeof(md5));
+ msg->long_term_valid = TRUE;
+
+ if (agent->compatibility == STUN_COMPATIBILITY_RFC3489 ||
+ agent->compatibility == STUN_COMPATIBILITY_OC2007) {
+ stun_sha1 (msg->buffer, hash + 20 - msg->buffer, hash - msg->buffer,
+ sha, md5, sizeof(md5), TRUE);
+ } else if (agent->compatibility == STUN_COMPATIBILITY_MSICE2) {
+ stun_sha1 (msg->buffer, hash + 20 - msg->buffer,
+ stun_message_length (msg) - 20, sha, md5, sizeof(md5), TRUE);
+ } else {
+ stun_sha1 (msg->buffer, hash + 20 - msg->buffer,
+ hash - msg->buffer, sha, md5, sizeof(md5), FALSE);
+ }
+ } else {
+ if (agent->compatibility == STUN_COMPATIBILITY_RFC3489 ||
+ agent->compatibility == STUN_COMPATIBILITY_OC2007) {
+ stun_sha1 (msg->buffer, hash + 20 - msg->buffer, hash - msg->buffer,
+ sha, key, key_len, TRUE);
+ } else if (agent->compatibility == STUN_COMPATIBILITY_MSICE2) {
+ stun_sha1 (msg->buffer, hash + 20 - msg->buffer,
+ stun_message_length (msg) - 20, sha, key, key_len, TRUE);
+ } else {
+ stun_sha1 (msg->buffer, hash + 20 - msg->buffer,
+ hash - msg->buffer, sha, key, key_len, FALSE);
+ }
+ }
+
+ stun_debug (" Message HMAC-SHA1 fingerprint:");
+ stun_debug_bytes (" key : ", key, key_len);
+ stun_debug_bytes (" expected: ", sha, sizeof (sha));
+ stun_debug_bytes (" received: ", hash, sizeof (sha));
+
+ if (memcmp (sha, hash, sizeof (sha))) {
+ stun_debug ("STUN auth error: SHA1 fingerprint mismatch!");
+ return STUN_VALIDATION_UNAUTHORIZED;
+ }
+
+ stun_debug ("STUN auth: OK!");
+ msg->key = key;
+ msg->key_len = key_len;
+ } else if (!(stun_message_get_class (msg) == STUN_ERROR &&
+ stun_message_find_error (msg, &error_code) ==
+ STUN_MESSAGE_RETURN_SUCCESS &&
+ (error_code == STUN_ERROR_BAD_REQUEST ||
+ error_code == STUN_ERROR_UNAUTHORIZED))) {
+ stun_debug ("STUN auth error: No message integrity attribute!");
+ return STUN_VALIDATION_UNAUTHORIZED;
+ }
+ }
+
+
+ if (sent_id_idx != -1 && sent_id_idx < STUN_AGENT_MAX_SAVED_IDS) {
+ agent->sent_ids[sent_id_idx].valid = FALSE;
+ }
+
+ /* [MS-ICE2] 3.1.4.8.2 stop sending additional connectivity checks */
+ if (stun_message_find32(msg, STUN_ATTRIBUTE_MS_IMPLEMENTATION_VERSION,
+ &implementation_version) == STUN_MESSAGE_RETURN_SUCCESS) {
+ msg->agent->ms_ice2_send_legacy_connchecks = FALSE;
+ }
+
+ if (stun_agent_find_unknowns (agent, msg, &unknown, 1) > 0) {
+ if (stun_message_get_class (msg) == STUN_REQUEST)
+ return STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE;
+ else
+ return STUN_VALIDATION_UNKNOWN_ATTRIBUTE;
+ }
+ return STUN_VALIDATION_SUCCESS;
+
+}
+
+bool stun_agent_forget_transaction (StunAgent *agent, StunTransactionId id)
+{
+ int i;
+
+ for (i = 0; i < STUN_AGENT_MAX_SAVED_IDS; i++) {
+ if (agent->sent_ids[i].valid == TRUE &&
+ memcmp (id, agent->sent_ids[i].id,
+ sizeof(StunTransactionId)) == 0) {
+ agent->sent_ids[i].valid = FALSE;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+bool stun_agent_init_request (StunAgent *agent, StunMessage *msg,
+ uint8_t *buffer, size_t buffer_len, StunMethod m)
+{
+ bool ret;
+ StunTransactionId id;
+
+ msg->buffer = buffer;
+ msg->buffer_len = buffer_len;
+ msg->agent = agent;
+ msg->key = NULL;
+ msg->key_len = 0;
+ msg->long_term_valid = FALSE;
+
+ stun_make_transid (id);
+
+ ret = stun_message_init (msg, STUN_REQUEST, m, id);
+
+ if (ret) {
+ if (agent->compatibility == STUN_COMPATIBILITY_RFC5389 ||
+ agent->compatibility == STUN_COMPATIBILITY_MSICE2) {
+ uint32_t cookie = htonl (STUN_MAGIC_COOKIE);
+ memcpy (msg->buffer + STUN_MESSAGE_TRANS_ID_POS, &cookie, sizeof (cookie));
+ }
+ if ((agent->compatibility == STUN_COMPATIBILITY_RFC5389 ||
+ agent->compatibility == STUN_COMPATIBILITY_MSICE2) &&
+ (agent->software_attribute != NULL ||
+ agent->usage_flags & STUN_AGENT_USAGE_ADD_SOFTWARE)) {
+ stun_message_append_software (msg, agent->software_attribute);
+ }
+ }
+
+ return ret;
+}
+
+
+bool stun_agent_init_indication (StunAgent *agent, StunMessage *msg,
+ uint8_t *buffer, size_t buffer_len, StunMethod m)
+{
+ bool ret;
+ StunTransactionId id;
+
+ msg->buffer = buffer;
+ msg->buffer_len = buffer_len;
+ msg->agent = agent;
+ msg->key = NULL;
+ msg->key_len = 0;
+ msg->long_term_valid = FALSE;
+
+ stun_make_transid (id);
+ ret = stun_message_init (msg, STUN_INDICATION, m, id);
+
+ if (ret) {
+ if (agent->compatibility == STUN_COMPATIBILITY_RFC5389 ||
+ agent->compatibility == STUN_COMPATIBILITY_MSICE2) {
+ uint32_t cookie = htonl (STUN_MAGIC_COOKIE);
+ memcpy (msg->buffer + STUN_MESSAGE_TRANS_ID_POS, &cookie, sizeof (cookie));
+ }
+ }
+
+ return ret;
+}
+
+
+bool stun_agent_init_response (StunAgent *agent, StunMessage *msg,
+ uint8_t *buffer, size_t buffer_len, const StunMessage *request)
+{
+
+ StunTransactionId id;
+
+ if (stun_message_get_class (request) != STUN_REQUEST) {
+ return FALSE;
+ }
+
+ msg->buffer = buffer;
+ msg->buffer_len = buffer_len;
+ msg->agent = agent;
+ msg->key = request->key;
+ msg->key_len = request->key_len;
+ memmove (msg->long_term_key, request->long_term_key,
+ sizeof(msg->long_term_key));
+ msg->long_term_valid = request->long_term_valid;
+
+ stun_message_id (request, id);
+
+ if (stun_message_init (msg, STUN_RESPONSE,
+ stun_message_get_method (request), id)) {
+
+ if ((agent->compatibility == STUN_COMPATIBILITY_RFC5389 ||
+ agent->compatibility == STUN_COMPATIBILITY_MSICE2) &&
+ (agent->software_attribute != NULL ||
+ agent->usage_flags & STUN_AGENT_USAGE_ADD_SOFTWARE)) {
+ stun_message_append_software (msg, agent->software_attribute);
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+bool stun_agent_init_error (StunAgent *agent, StunMessage *msg,
+ uint8_t *buffer, size_t buffer_len, const StunMessage *request,
+ StunError err)
+{
+ StunTransactionId id;
+
+ if (stun_message_get_class (request) != STUN_REQUEST) {
+ return FALSE;
+ }
+
+ msg->buffer = buffer;
+ msg->buffer_len = buffer_len;
+ msg->agent = agent;
+ msg->key = request->key;
+ msg->key_len = request->key_len;
+ memmove (msg->long_term_key, request->long_term_key,
+ sizeof(msg->long_term_key));
+ msg->long_term_valid = request->long_term_valid;
+
+ stun_message_id (request, id);
+
+
+ if (stun_message_init (msg, STUN_ERROR,
+ stun_message_get_method (request), id)) {
+
+ if ((agent->compatibility == STUN_COMPATIBILITY_RFC5389 ||
+ agent->compatibility == STUN_COMPATIBILITY_MSICE2) &&
+ (agent->software_attribute != NULL ||
+ agent->usage_flags & STUN_AGENT_USAGE_ADD_SOFTWARE)) {
+ stun_message_append_software (msg, agent->software_attribute);
+ }
+ if (stun_message_append_error (msg, err) == STUN_MESSAGE_RETURN_SUCCESS) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
+size_t stun_agent_build_unknown_attributes_error (StunAgent *agent,
+ StunMessage *msg, uint8_t *buffer, size_t buffer_len,
+ const StunMessage *request)
+{
+
+ unsigned counter;
+ uint16_t ids[STUN_AGENT_MAX_UNKNOWN_ATTRIBUTES];
+
+ counter = stun_agent_find_unknowns (agent, request,
+ ids, STUN_AGENT_MAX_UNKNOWN_ATTRIBUTES);
+
+ if (stun_agent_init_error (agent, msg, buffer, buffer_len,
+ request, STUN_ERROR_UNKNOWN_ATTRIBUTE) == FALSE) {
+ return 0;
+ }
+
+ /* NOTE: Old RFC3489 compatibility:
+ * When counter is odd, duplicate one value for 32-bits padding. */
+ if (!stun_message_has_cookie (request) && (counter & 1))
+ ids[counter++] = ids[0];
+
+ if (stun_message_append_bytes (msg, STUN_ATTRIBUTE_UNKNOWN_ATTRIBUTES,
+ ids, counter * 2) == STUN_MESSAGE_RETURN_SUCCESS) {
+ return stun_agent_finish_message (agent, msg, request->key, request->key_len);
+ }
+
+ return 0;
+}
+
+
+size_t stun_agent_finish_message (StunAgent *agent, StunMessage *msg,
+ const uint8_t *key, size_t key_len)
+{
+ uint8_t *ptr;
+ uint32_t fpr;
+ int saved_id_idx = 0;
+ uint8_t md5[16];
+ bool remember_transaction;
+
+ remember_transaction = (stun_message_get_class (msg) == STUN_REQUEST);
+
+ if (agent->compatibility == STUN_COMPATIBILITY_OC2007 &&
+ stun_message_get_method (msg) == STUN_SEND) {
+ /* As per [MS-TURN] Section 2.2.1, the TURN server doesn't send responses to
+ * STUN_SEND requests, so don't bother waiting for them. More details at
+ * https://msdn.microsoft.com/en-us/library/dd946797%28v=office.12%29.aspx.
+ */
+ remember_transaction = FALSE;
+ }
+
+ if (remember_transaction) {
+ for (saved_id_idx = 0; saved_id_idx < STUN_AGENT_MAX_SAVED_IDS; saved_id_idx++) {
+ if (agent->sent_ids[saved_id_idx].valid == FALSE) {
+ break;
+ }
+ }
+ }
+ if (saved_id_idx == STUN_AGENT_MAX_SAVED_IDS) {
+ stun_debug ("WARNING: Saved IDs full. STUN message dropped.");
+ return 0;
+ }
+
+ if (msg->key != NULL) {
+ key = msg->key;
+ key_len = msg->key_len;
+ }
+
+ if (key != NULL) {
+ bool skip = FALSE;
+
+ if (msg->long_term_valid) {
+ memcpy (md5, msg->long_term_key, sizeof(msg->long_term_key));
+ } else if (agent->usage_flags & STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS) {
+ uint8_t *realm = NULL;
+ uint8_t *username = NULL;
+ uint16_t realm_len;
+ uint16_t username_len;
+
+ realm = (uint8_t *) stun_message_find (msg,
+ STUN_ATTRIBUTE_REALM, &realm_len);
+ username = (uint8_t *) stun_message_find (msg,
+ STUN_ATTRIBUTE_USERNAME, &username_len);
+ if (username == NULL || realm == NULL) {
+ skip = TRUE;
+ } else {
+ stun_hash_creds (realm, realm_len,
+ username, username_len,
+ key, key_len, md5);
+ memcpy (msg->long_term_key, md5, sizeof(msg->long_term_key));
+ msg->long_term_valid = TRUE;
+ }
+ }
+
+ /* If no realm/username and long term credentials,
+ then don't send the message integrity */
+ if (skip == FALSE) {
+ ptr = stun_message_append (msg, STUN_ATTRIBUTE_MESSAGE_INTEGRITY, 20);
+ if (ptr == NULL) {
+ return 0;
+ }
+ if (agent->usage_flags & STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS) {
+ if (agent->compatibility == STUN_COMPATIBILITY_RFC3489 ||
+ agent->compatibility == STUN_COMPATIBILITY_OC2007) {
+ stun_sha1 (msg->buffer, stun_message_length (msg),
+ stun_message_length (msg) - 20, ptr, md5, sizeof(md5), TRUE);
+ } else if (agent->compatibility == STUN_COMPATIBILITY_MSICE2) {
+ size_t minus = 20;
+ if (agent->usage_flags & STUN_AGENT_USAGE_USE_FINGERPRINT)
+ minus -= 8;
+
+ stun_sha1 (msg->buffer, stun_message_length (msg),
+ stun_message_length (msg) - minus, ptr, md5, sizeof(md5), TRUE);
+ } else {
+ stun_sha1 (msg->buffer, stun_message_length (msg),
+ stun_message_length (msg) - 20, ptr, md5, sizeof(md5), FALSE);
+ }
+ } else {
+ if (agent->compatibility == STUN_COMPATIBILITY_RFC3489 ||
+ agent->compatibility == STUN_COMPATIBILITY_OC2007) {
+ stun_sha1 (msg->buffer, stun_message_length (msg),
+ stun_message_length (msg) - 20, ptr, key, key_len, TRUE);
+ } else if (agent->compatibility == STUN_COMPATIBILITY_MSICE2) {
+ size_t minus = 20;
+ if (agent->usage_flags & STUN_AGENT_USAGE_USE_FINGERPRINT)
+ minus -= 8;
+
+ stun_sha1 (msg->buffer, stun_message_length (msg),
+ stun_message_length (msg) - minus, ptr, key, key_len, TRUE);
+ } else {
+ stun_sha1 (msg->buffer, stun_message_length (msg),
+ stun_message_length (msg) - 20, ptr, key, key_len, FALSE);
+ }
+ }
+
+ stun_debug (" Message HMAC-SHA1 message integrity:");
+ stun_debug_bytes (" key : ", key, key_len);
+ stun_debug_bytes (" sent : ", ptr, 20);
+ }
+ }
+
+ if ((agent->compatibility == STUN_COMPATIBILITY_RFC5389 ||
+ agent->compatibility == STUN_COMPATIBILITY_MSICE2) &&
+ agent->usage_flags & STUN_AGENT_USAGE_USE_FINGERPRINT) {
+ ptr = stun_message_append (msg, STUN_ATTRIBUTE_FINGERPRINT, 4);
+ if (ptr == NULL) {
+ return 0;
+ }
+
+ fpr = stun_fingerprint (msg->buffer, stun_message_length (msg), FALSE);
+ memcpy (ptr, &fpr, sizeof (fpr));
+
+ stun_debug_bytes (" Message HMAC-SHA1 fingerprint: ", ptr, 4);
+ }
+
+
+ if (remember_transaction) {
+ stun_message_id (msg, agent->sent_ids[saved_id_idx].id);
+ agent->sent_ids[saved_id_idx].method = stun_message_get_method (msg);
+ agent->sent_ids[saved_id_idx].key = (uint8_t *) key;
+ agent->sent_ids[saved_id_idx].key_len = key_len;
+ memcpy (agent->sent_ids[saved_id_idx].long_term_key, msg->long_term_key,
+ sizeof(msg->long_term_key));
+ agent->sent_ids[saved_id_idx].long_term_valid = msg->long_term_valid;
+ agent->sent_ids[saved_id_idx].valid = TRUE;
+ }
+
+ msg->key = (uint8_t *) key;
+ msg->key_len = key_len;
+ return stun_message_length (msg);
+
+}
+
+static bool stun_agent_is_unknown (StunAgent *agent, uint16_t type)
+{
+
+ uint16_t *known_attr = agent->known_attributes;
+
+ while(*known_attr != 0) {
+ if (*known_attr == type) {
+ return FALSE;
+ }
+ known_attr++;
+ }
+
+ return TRUE;
+
+}
+
+
+static unsigned
+stun_agent_find_unknowns (StunAgent *agent, const StunMessage * msg,
+ uint16_t *list, unsigned max)
+{
+ unsigned count = 0;
+ uint16_t len = stun_message_length (msg);
+ size_t offset = 0;
+
+ offset = STUN_MESSAGE_ATTRIBUTES_POS;
+
+ while ((offset < len) && (count < max))
+ {
+ size_t alen = stun_getw (msg->buffer + offset + STUN_ATTRIBUTE_TYPE_LEN);
+ uint16_t atype = stun_getw (msg->buffer + offset);
+
+ if (!stun_optional (atype) && stun_agent_is_unknown (agent, atype))
+ {
+ stun_debug ("STUN unknown: attribute 0x%04x(%u bytes)",
+ (unsigned)atype, (unsigned)alen);
+ list[count++] = htons (atype);
+ }
+
+ if (!(agent->usage_flags & STUN_AGENT_USAGE_NO_ALIGNED_ATTRIBUTES))
+ alen = stun_align (alen);
+
+ offset += STUN_ATTRIBUTE_VALUE_POS + alen;
+ }
+
+ stun_debug ("STUN unknown: %u mandatory attribute(s)!", count);
+ return count;
+}
+
+void stun_agent_set_software (StunAgent *agent, const char *software)
+{
+ agent->software_attribute = software;
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2008-2009 Nokia Corporation. All rights reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef _STUN_AGENT_H
+#define _STUN_AGENT_H
+
+/**
+ * SECTION:stunagent
+ * @short_description: STUN agent for building and validating STUN messages
+ * @include: stun/stunagent.h
+ * @see_also: #StunMessage
+ * @stability: Stable
+ *
+ * The STUN Agent allows you to create and validate STUN messages easily.
+ * It's main purpose is to make sure the building and validation methods used
+ * are compatible with the RFC you create it with. It also tracks the transaction
+ * ids of the requests you send, so you can validate if a STUN response you
+ * received should be processed by that agent or not.
+ *
+ */
+
+
+#ifdef _WIN32
+#include "win32_common.h"
+#else
+#include <stdint.h>
+#endif
+
+#include <stdbool.h>
+#include <sys/types.h>
+
+/**
+ * StunAgent:
+ *
+ * An opaque structure representing the STUN agent.
+ */
+typedef struct stun_agent_t StunAgent;
+
+#include "stunmessage.h"
+#include "debug.h"
+
+/**
+ * StunCompatibility:
+ * @STUN_COMPATIBILITY_RFC3489: Use the STUN specifications compatible with
+ * RFC 3489
+ * @STUN_COMPATIBILITY_RFC5389: Use the STUN specifications compatible with
+ * RFC 5389
+ * @STUN_COMPATIBILITY_MSICE2: Use the STUN specifications compatible with
+ * [MS-ICE2] (a mix between RFC3489 and RFC5389)
+ * @STUN_COMPATIBILITY_OC2007: Use the STUN specifications compatible with
+ * Microsoft Office Communicator 2007 (basically RFC3489 with swapped
+ * REALM and NONCE attribute hex IDs, attributes are not aligned)
+ * @STUN_COMPATIBILITY_WLM2009: An alias for @STUN_COMPATIBILITY_MSICE2
+ * @STUN_COMPATIBILITY_LAST: Dummy last compatibility mode
+ *
+ * Enum that specifies the STUN compatibility mode of the #StunAgent
+ *
+ * <warning>@STUN_COMPATIBILITY_WLM2009 is deprecated and should not be used
+ * in newly-written code. It is kept for compatibility reasons and represents
+ * the same compatibility as @STUN_COMPATIBILITY_MSICE2.</warning>
+ */
+typedef enum {
+ STUN_COMPATIBILITY_RFC3489,
+ STUN_COMPATIBILITY_RFC5389,
+ STUN_COMPATIBILITY_MSICE2,
+ STUN_COMPATIBILITY_OC2007,
+ STUN_COMPATIBILITY_WLM2009 = STUN_COMPATIBILITY_MSICE2,
+ STUN_COMPATIBILITY_LAST = STUN_COMPATIBILITY_OC2007
+} StunCompatibility;
+
+
+/**
+ * StunValidationStatus:
+ * @STUN_VALIDATION_SUCCESS: The message is validated
+ * @STUN_VALIDATION_NOT_STUN: This is not a valid STUN message
+ * @STUN_VALIDATION_INCOMPLETE_STUN: The message seems to be valid but incomplete
+ * @STUN_VALIDATION_BAD_REQUEST: The message does not have the cookie or the
+ * fingerprint while the agent needs it with its usage
+ * @STUN_VALIDATION_UNAUTHORIZED_BAD_REQUEST: The message is valid but
+ * unauthorized with no username and message-integrity attributes.
+ * A BAD_REQUEST error must be generated
+ * @STUN_VALIDATION_UNAUTHORIZED: The message is valid but unauthorized as
+ * the username/password do not match.
+ * An UNAUTHORIZED error must be generated
+ * @STUN_VALIDATION_UNMATCHED_RESPONSE: The message is valid but this is a
+ * response/error that doesn't match a previously sent request
+ * @STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE: The message is valid but
+ * contains one or more unknown comprehension attributes.
+ * stun_agent_build_unknown_attributes_error() should be called
+ * @STUN_VALIDATION_UNKNOWN_ATTRIBUTE: The message is valid but contains one
+ * or more unknown comprehension attributes. This is a response, or error,
+ * or indication message and no error response should be sent
+ *
+ * This enum is used as the return value of stun_agent_validate() and represents
+ * the status result of the validation of a STUN message.
+ */
+typedef enum {
+ STUN_VALIDATION_SUCCESS,
+ STUN_VALIDATION_NOT_STUN,
+ STUN_VALIDATION_INCOMPLETE_STUN,
+ STUN_VALIDATION_BAD_REQUEST,
+ STUN_VALIDATION_UNAUTHORIZED_BAD_REQUEST,
+ STUN_VALIDATION_UNAUTHORIZED,
+ STUN_VALIDATION_UNMATCHED_RESPONSE,
+ STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE,
+ STUN_VALIDATION_UNKNOWN_ATTRIBUTE,
+} StunValidationStatus;
+
+/**
+ * StunAgentUsageFlags:
+ * @STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS: The agent should be using the short
+ * term credentials mechanism for authenticating STUN messages
+ * @STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS: The agent should be using the long
+ * term credentials mechanism for authenticating STUN messages
+ * @STUN_AGENT_USAGE_USE_FINGERPRINT: The agent should add the FINGERPRINT
+ * attribute to the STUN messages it creates.
+ * @STUN_AGENT_USAGE_ADD_SOFTWARE: The agent should add the SOFTWARE attribute
+ * to the STUN messages it creates. Calling nice_agent_set_software() will have
+ * the same effect as enabling this Usage. STUN Indications do not have the
+ * SOFTWARE attributes added to them though. The SOFTWARE attribute is only
+ * added for the RFC5389 and MSICE2 compatibility modes.
+ * @STUN_AGENT_USAGE_IGNORE_CREDENTIALS: The agent should ignore any credentials
+ * in the STUN messages it receives (the MESSAGE-INTEGRITY attribute
+ * will never be validated by stun_agent_validate())
+ * @STUN_AGENT_USAGE_NO_INDICATION_AUTH: The agent should ignore credentials
+ * in the STUN messages it receives if the #StunClass of the message is
+ * #STUN_INDICATION (some implementation require #STUN_INDICATION messages to
+ * be authenticated, while others never add a MESSAGE-INTEGRITY attribute to a
+ * #STUN_INDICATION message)
+ * @STUN_AGENT_USAGE_FORCE_VALIDATER: The agent should always try to validate
+ * the password of a STUN message, even if it already knows what the password
+ * should be (a response to a previously created request). This means that the
+ * #StunMessageIntegrityValidate callback will always be called when there is
+ * a MESSAGE-INTEGRITY attribute.
+ * @STUN_AGENT_USAGE_NO_ALIGNED_ATTRIBUTES: The agent should not assume STUN
+ * attributes are aligned on 32-bit boundaries when parsing messages and also
+ * do not add padding when creating messages.
+ *
+ * This enum defines a bitflag usages for a #StunAgent and they will define how
+ * the agent should behave, independently of the compatibility mode it uses.
+ * <para> See also: stun_agent_init() </para>
+ * <para> See also: stun_agent_validate() </para>
+ */
+typedef enum {
+ STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS = (1 << 0),
+ STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS = (1 << 1),
+ STUN_AGENT_USAGE_USE_FINGERPRINT = (1 << 2),
+ STUN_AGENT_USAGE_ADD_SOFTWARE = (1 << 3),
+ STUN_AGENT_USAGE_IGNORE_CREDENTIALS = (1 << 4),
+ STUN_AGENT_USAGE_NO_INDICATION_AUTH = (1 << 5),
+ STUN_AGENT_USAGE_FORCE_VALIDATER = (1 << 6),
+ STUN_AGENT_USAGE_NO_ALIGNED_ATTRIBUTES = (1 << 7),
+} StunAgentUsageFlags;
+
+
+typedef struct {
+ StunTransactionId id;
+ StunMethod method;
+ uint8_t *key;
+ size_t key_len;
+ uint8_t long_term_key[16];
+ bool long_term_valid;
+ bool valid;
+} StunAgentSavedIds;
+
+struct stun_agent_t {
+ StunCompatibility compatibility;
+ StunAgentSavedIds sent_ids[STUN_AGENT_MAX_SAVED_IDS];
+ uint16_t *known_attributes;
+ StunAgentUsageFlags usage_flags;
+ const char *software_attribute;
+ bool ms_ice2_send_legacy_connchecks;
+};
+
+/**
+ * StunDefaultValidaterData:
+ * @username: The username
+ * @username_len: The length of the @username
+ * @password: The password
+ * @password_len: The length of the @password
+ *
+ * This structure is used as an element of the user_data to the
+ * stun_agent_default_validater() function for authenticating a STUN
+ * message during validationg.
+ * <para> See also: stun_agent_default_validater() </para>
+ */
+typedef struct {
+ uint8_t *username;
+ size_t username_len;
+ uint8_t *password;
+ size_t password_len;
+} StunDefaultValidaterData;
+
+
+/**
+ * StunMessageIntegrityValidate:
+ * @agent: The #StunAgent
+ * @message: The #StunMessage being validated
+ * @username: The username found in the @message
+ * @username_len: The length of @username
+ * @password: The password associated with that username. This argument is a
+ * pointer to a byte array that must be set by the validater function.
+ * @password_len: The length of @password which must also be set by the
+ * validater function.
+ * @user_data: Data to give the function
+ *
+ * This is the prototype for the @validater argument of the stun_agent_validate()
+ * function.
+ * <para> See also: stun_agent_validate() </para>
+ * Returns: %TRUE if the authentication was successful,
+ * %FALSE if the authentication failed
+ */
+typedef bool (*StunMessageIntegrityValidate) (StunAgent *agent,
+ StunMessage *message, uint8_t *username, uint16_t username_len,
+ uint8_t **password, size_t *password_len, void *user_data);
+
+/**
+ * stun_agent_default_validater:
+ * @agent: The #StunAgent
+ * @message: The #StunMessage being validated
+ * @username: The username found in the @message
+ * @username_len: The length of @username
+ * @password: The password associated with that username. This argument is a
+ * pointer to a byte array that must be set by the validater function.
+ * @password_len: The length of @password which must also be set by the
+ * validater function.
+ * @user_data: This must be an array of #StunDefaultValidaterData structures.
+ * The last element in the array must have a username set to NULL
+ *
+ * This is a helper function to be used with stun_agent_validate(). If no
+ * complicated processing of the username needs to be done, this function can
+ * be used with stun_agent_validate() to quickly and easily match the username
+ * of a STUN message with its password. Its @user_data argument must be an array
+ * of #StunDefaultValidaterData which will allow us to map a username to a
+ * password
+ * <para> See also: stun_agent_validate() </para>
+ * Returns: %TRUE if the authentication was successful,
+ * %FALSE if the authentication failed
+ */
+bool stun_agent_default_validater (StunAgent *agent,
+ StunMessage *message, uint8_t *username, uint16_t username_len,
+ uint8_t **password, size_t *password_len, void *user_data);
+
+/**
+ * stun_agent_init:
+ * @agent: The #StunAgent to initialize
+ * @known_attributes: An array of #uint16_t specifying which attributes should
+ * be known by the agent. Any STUN message received that contains a mandatory
+ * attribute that is not in this array will yield a
+ * #STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE or a
+ * #STUN_VALIDATION_UNKNOWN_ATTRIBUTE error when calling stun_agent_validate()
+ * @compatibility: The #StunCompatibility to use for this agent. This will affect
+ * how the agent builds and validates the STUN messages
+ * @usage_flags: A bitflag using #StunAgentUsageFlags values to define which
+ * STUN usages the agent should use.
+ *
+ * This function must be called to initialize an agent before it is being used.
+ *
+ <note>
+ <para>
+ The @known_attributes data must exist in memory as long as the @agent is used
+ </para>
+ <para>
+ If the #STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS and
+ #STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS usage flags are not set, then the
+ agent will default in using the short term credentials mechanism
+ </para>
+ <para>
+ The #STUN_AGENT_USAGE_USE_FINGERPRINT and #STUN_AGENT_USAGE_ADD_SOFTWARE
+ usage flags are only valid if the #STUN_COMPATIBILITY_RFC5389 or
+ #STUN_COMPATIBILITY_MSICE2 @compatibility is used
+ </para>
+ </note>
+ */
+void stun_agent_init (StunAgent *agent, const uint16_t *known_attributes,
+ StunCompatibility compatibility, StunAgentUsageFlags usage_flags);
+
+/**
+ * stun_agent_validate:
+ * @agent: The #StunAgent
+ * @msg: The #StunMessage to build
+ * @buffer: The data buffer of the STUN message
+ * @buffer_len: The length of @buffer
+ * @validater: A #StunMessageIntegrityValidate function callback that will
+ * be called if the agent needs to validate a MESSAGE-INTEGRITY attribute. It
+ * will only be called if the agent finds a message that needs authentication
+ * and a USERNAME is present in the STUN message, but no password is known.
+ * The validater will not be called if the #STUN_AGENT_USAGE_IGNORE_CREDENTIALS
+ * usage flag is set on the agent, and it will always be called if the
+ * #STUN_AGENT_USAGE_FORCE_VALIDATER usage flag is set on the agent.
+ * @validater_data: A user data to give to the @validater callback when it gets
+ * called.
+ *
+ * This function is used to validate an inbound STUN message and transform its
+ * data buffer into a #StunMessage. It will take care of various validation
+ * algorithms to make sure that the STUN message is valid and correctly
+ * authenticated.
+ * <para> See also: stun_agent_default_validater() </para>
+ * Returns: A #StunValidationStatus
+ <note>
+ <para>
+ if the return value is different from #STUN_VALIDATION_NOT_STUN or
+ #STUN_VALIDATION_INCOMPLETE_STUN, then the @msg argument will contain a valid
+ STUN message that can be used.
+ This means that you can use the @msg variable as the @request argument to
+ functions like stun_agent_init_error() or
+ stun_agent_build_unknown_attributes_error().
+ If the return value is #STUN_VALIDATION_BAD_REQUEST,
+ #STUN_VALIDATION_UNAUTHORIZED or #STUN_VALIDATION_UNAUTHORIZED_BAD_REQUEST
+ then the @key in the #StunMessage will not be set, so that error responses
+ will not have a MESSAGE-INTEGRITY attribute.
+ </para>
+ </note>
+ */
+StunValidationStatus stun_agent_validate (StunAgent *agent, StunMessage *msg,
+ const uint8_t *buffer, size_t buffer_len,
+ StunMessageIntegrityValidate validater, void * validater_data);
+
+/**
+ * stun_agent_init_request:
+ * @agent: The #StunAgent
+ * @msg: The #StunMessage to build
+ * @buffer: The buffer to use in the #StunMessage
+ * @buffer_len: The length of the buffer
+ * @m: The #StunMethod of the request
+ *
+ * Creates a new STUN message of class #STUN_REQUEST and with the method @m
+ * Returns: %TRUE if the message was initialized correctly, %FALSE otherwise
+ */
+bool stun_agent_init_request (StunAgent *agent, StunMessage *msg,
+ uint8_t *buffer, size_t buffer_len, StunMethod m);
+
+/**
+ * stun_agent_init_indication:
+ * @agent: The #StunAgent
+ * @msg: The #StunMessage to build
+ * @buffer: The buffer to use in the #StunMessage
+ * @buffer_len: The length of the buffer
+ * @m: The #StunMethod of the indication
+ *
+ * Creates a new STUN message of class #STUN_INDICATION and with the method @m
+ * Returns: %TRUE if the message was initialized correctly, %FALSE otherwise
+ */
+bool stun_agent_init_indication (StunAgent *agent, StunMessage *msg,
+ uint8_t *buffer, size_t buffer_len, StunMethod m);
+
+/**
+ * stun_agent_init_response:
+ * @agent: The #StunAgent
+ * @msg: The #StunMessage to build
+ * @buffer: The buffer to use in the #StunMessage
+ * @buffer_len: The length of the buffer
+ * @request: The #StunMessage of class #STUN_REQUEST that this response is for
+ *
+ * Creates a new STUN message of class #STUN_RESPONSE and with the same method
+ * and transaction ID as the message @request. This will also copy the pointer
+ * to the key that was used to authenticate the request, so you won't need to
+ * specify the key with stun_agent_finish_message()
+ * Returns: %TRUE if the message was initialized correctly, %FALSE otherwise
+ */
+bool stun_agent_init_response (StunAgent *agent, StunMessage *msg,
+ uint8_t *buffer, size_t buffer_len, const StunMessage *request);
+
+/**
+ * stun_agent_init_error:
+ * @agent: The #StunAgent
+ * @msg: The #StunMessage to build
+ * @buffer: The buffer to use in the #StunMessage
+ * @buffer_len: The length of the buffer
+ * @request: The #StunMessage of class #STUN_REQUEST that this error response
+ * is for
+ * @err: The #StunError to put in the ERROR-CODE attribute of the error response
+ *
+ * Creates a new STUN message of class #STUN_ERROR and with the same method
+ * and transaction ID as the message @request. This will also copy the pointer
+ * to the key that was used to authenticate the request (if authenticated),
+ * so you won't need to specify the key with stun_agent_finish_message().
+ * It will then add the ERROR-CODE attribute with code @err and the associated
+ * string.
+ * Returns: %TRUE if the message was initialized correctly, %FALSE otherwise
+ */
+bool stun_agent_init_error (StunAgent *agent, StunMessage *msg,
+ uint8_t *buffer, size_t buffer_len, const StunMessage *request,
+ StunError err);
+
+/**
+ * stun_agent_build_unknown_attributes_error:
+ * @agent: The #StunAgent
+ * @msg: The #StunMessage to build
+ * @buffer: The buffer to use in the #StunMessage
+ * @buffer_len: The length of the buffer
+ * @request: The #StunMessage of class #STUN_REQUEST that this response is for
+ *
+ * Creates a new STUN message of class #STUN_ERROR and with the same method
+ * and transaction ID as the message @request. It will then add the ERROR-CODE
+ * attribute with code #STUN_ERROR_UNKNOWN_ATTRIBUTE and add all the unknown
+ * mandatory attributes from the @request STUN message in the
+ * #STUN_ATTRIBUTE_UNKNOWN_ATTRIBUTES attribute, it will then finish the message
+ * by calling stun_agent_finish_message()
+ * Returns: The size of the message built
+ */
+size_t stun_agent_build_unknown_attributes_error (StunAgent *agent,
+ StunMessage *msg, uint8_t *buffer, size_t buffer_len,
+ const StunMessage *request);
+
+
+/**
+ * stun_agent_finish_message:
+ * @agent: The #StunAgent
+ * @msg: The #StunMessage to finish
+ * @key: The key to use for the MESSAGE-INTEGRITY attribute
+ * @key_len: The length of the @key
+ *
+ * This function will 'finish' a message and make it ready to be sent. It will
+ * add the MESSAGE-INTEGRITY and FINGERPRINT attributes if necessary. If the
+ * STUN message has a #STUN_REQUEST class, it will save the transaction id of
+ * the message in the agent for future matching of the response.
+ * <para>See also: stun_agent_forget_transaction()</para>
+ * Returns: The final size of the message built or 0 if an error occured
+ * <note>
+ <para>
+ The return value must always be checked. a value of 0 means the either
+ the buffer's size is too small to contain the finishing attributes
+ (MESSAGE-INTEGRITY, FINGERPRINT), or that there is no more free slots
+ for saving the sent id in the agent's state.
+ </para>
+ <para>
+ Everytime stun_agent_finish_message() is called for a #STUN_REQUEST
+ message, you must make sure to call stun_agent_forget_transaction() in
+ case the response times out and is never received. This is to avoid
+ filling up the #StunAgent's sent ids state preventing any further
+ use of the stun_agent_finish_message()
+ </para>
+ </note>
+ */
+size_t stun_agent_finish_message (StunAgent *agent, StunMessage *msg,
+ const uint8_t *key, size_t key_len);
+
+/**
+ * stun_agent_forget_transaction:
+ * @agent: The #StunAgent
+ * @id: The #StunTransactionId of the transaction to forget
+ *
+ * This function is used to make the #StunAgent forget about a previously
+ * created transaction.
+ * <para>
+ * This function should be called when a STUN request was previously
+ * created with stun_agent_finish_message() and for which no response was ever
+ * received (timed out). The #StunAgent keeps a list of the sent transactions
+ * in order to validate the responses received. If the response is never received
+ * this will allow the #StunAgent to forget about the timed out transaction and
+ * free its slot for future transactions.
+ * </para>
+ * Since: 0.0.6
+ * Returns: %TRUE if the transaction was found, %FALSE otherwise
+ */
+bool stun_agent_forget_transaction (StunAgent *agent, StunTransactionId id);
+
+
+/**
+ * stun_agent_set_software:
+ * @agent: The #StunAgent
+ * @software: The value of the SOFTWARE attribute to add.
+ *
+ * This function will set the value of the SOFTWARE attribute to be added to
+ * STUN requests, responses and error responses.
+ * <para>
+ * Calling this function will automatically enable the addition of the SOFTWARE
+ * attribute for RFC5389 and MSICE2 compatibility modes.
+ *
+ * </para>
+ * <note>
+ <para>
+ The @software argument must be in UTF-8 encoding and only the first
+ 128 characters will be sent.
+ </para>
+ <para>
+ The value of the @software argument must stay valid throughout the life of
+ the StunAgent's life. Do not free its content.
+ </para>
+ </note>
+ *
+ * Since: 0.0.10
+ *
+ */
+void stun_agent_set_software (StunAgent *agent, const char *software);
+
+#endif /* _STUN_AGENT_H */
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2007-2009 Nokia Corporation. All rights reserved.
+ * Contact: Rémi Denis-Courmont
+ * COPYRIGHT (C) 1986 Gary S. Brown
+ * See documentation of the function crc32() below.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ * Rémi Denis-Courmont, Nokia
+ * Gary S. Brown
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+/*-
+ * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
+ * code or tables extracted from it, as desired without restriction.
+ *
+ * Extracted from FreeBSD CVS (src/sys/libkern/crc32.c)
+ * and adapted by Rémi Denis-Courmont, 2007.
+ */
+
+/*
+ * First, the polynomial itself and its table of feedback terms. The
+ * polynomial is
+ * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
+ *
+ * Note that we take it "backwards" and put the highest-order term in
+ * the lowest-order bit. The X^32 term is "implied"; the LSB is the
+ * X^31 term, etc. The X^0 term (usually shown as "+1") results in
+ * the MSB being 1
+ *
+ * Note that the usual hardware shift register implementation, which
+ * is what we're using (we're merely optimizing it by doing eight-bit
+ * chunks at a time) shifts bits into the lowest-order term. In our
+ * implementation, that means shifting towards the right. Why do we
+ * do it this way? Because the calculated CRC must be transmitted in
+ * order from highest-order term to lowest-order term. UARTs transmit
+ * characters in order from LSB to MSB. By storing the CRC this way
+ * we hand it to the UART in the order low-byte to high-byte; the UART
+ * sends each low-bit to hight-bit; and the result is transmission bit
+ * by bit from highest- to lowest-order term without requiring any bit
+ * shuffling on our part. Reception works similarly
+ *
+ * The feedback terms table consists of 256, 32-bit entries. Notes
+ *
+ * The table can be generated at runtime if desired; code to do so
+ * is shown later. It might not be obvious, but the feedback
+ * terms simply represent the results of eight shift/xor opera
+ * tions for all combinations of data and CRC register values
+ *
+ * The values must be right-shifted by eight bits by the "updcrc
+ * logic; the shift must be unsigned (bring in zeroes). On some
+ * hardware you could probably optimize the shift in assembler by
+ * using byte-swap instructions
+ * polynomial $edb88320
+ *
+ *
+ * CRC32 code derived from work by Gary S. Brown.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "stuncrc32.h"
+
+static const uint32_t crc32_tab[] = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
+ 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
+ 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
+ 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
+ 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
+ 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
+ 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
+ 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
+ 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
+ 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
+ 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
+ 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
+ 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
+ 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
+ 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
+ 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
+ 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
+ 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+};
+
+
+uint32_t stun_crc32 (const crc_data *data, size_t n, bool wlm2009_stupid_crc32_typo)
+{
+ size_t i;
+ uint32_t crc = 0xffffffff;
+
+ for (i = 0; i < n; i++)
+ {
+ const uint8_t *p = data[i].buf;
+ size_t size = data[i].len;
+
+ while (size--) {
+ uint32_t lkp = crc32_tab[(crc ^ *p++) & 0xFF];
+ if (lkp == 0x8bbeb8ea && wlm2009_stupid_crc32_typo)
+ lkp = 0x8bbe8ea;
+ crc = lkp ^ (crc >> 8);
+ }
+ }
+
+ return crc ^ 0xffffffff;
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2006-2007 Nokia Corporation. All rights reserved.
+ * Contact: Rémi Denis-Courmont
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef _CRC32_H
+#define _CRC32_H
+
+
+#ifdef _WIN32
+#include "win32_common.h"
+#else
+#include <stdint.h>
+#endif
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+typedef struct {
+ uint8_t *buf;
+ size_t len;
+} crc_data;
+
+
+uint32_t stun_crc32 (const crc_data *data, size_t n, bool wlm2009_stupid_crc32_typo);
+
+#endif /* _CRC32_H */
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2007-2009 Nokia Corporation. All rights reserved.
+ * Contact: Rémi Denis-Courmont
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ * Rémi Denis-Courmont, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "rand.h"
+
+#include "stunmessage.h"
+#include "stunhmac.h"
+
+#include <string.h>
+#include <assert.h>
+
+#ifdef HAVE_OPENSSL
+#include <openssl/hmac.h>
+#include <openssl/sha.h>
+#else
+#include <gnutls/gnutls.h>
+#include <gnutls/crypto.h>
+#endif
+
+void stun_sha1 (const uint8_t *msg, size_t len, size_t msg_len, uint8_t *sha,
+ const void *key, size_t keylen, int padding)
+{
+ uint16_t fakelen = htons (msg_len);
+ uint8_t pad_char[64] = {0};
+
+ assert (len >= 44u);
+
+#ifdef HAVE_OPENSSL
+{
+#ifdef NDEBUG
+#define TRY(x) x;
+#else
+ int ret;
+#define TRY(x) \
+ ret = x; \
+ assert (ret == 1);
+#endif
+
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
+ (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
+ HMAC_CTX stackctx;
+ HMAC_CTX *ctx = &stackctx;
+ HMAC_CTX_init (ctx);
+#else
+ HMAC_CTX *ctx = HMAC_CTX_new ();
+#endif /* OPENSSL_VERSION_NUMBER */
+
+ assert (SHA_DIGEST_LENGTH == 20);
+
+ TRY (HMAC_Init_ex (ctx, key, keylen, EVP_sha1(), NULL));
+
+ TRY (HMAC_Update (ctx, msg, 2));
+ TRY (HMAC_Update (ctx, (unsigned char *)&fakelen, 2));
+ TRY (HMAC_Update (ctx, msg + 4, len - 28));
+
+ /* RFC 3489 specifies that the message's size should be 64 bytes,
+ and \x00 padding should be done */
+ if (padding && ((len - 24) % 64) > 0) {
+ uint16_t pad_size = 64 - ((len - 24) % 64);
+
+ TRY (HMAC_Update (ctx, pad_char, pad_size));
+ }
+
+ TRY (HMAC_Final (ctx, sha, NULL));
+
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
+ (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
+ HMAC_CTX_cleanup (ctx);
+#else
+ HMAC_CTX_free (ctx);
+#endif /* OPENSSL_VERSION_NUMBER */
+}
+#else
+{
+ gnutls_hmac_hd_t handle;
+
+#ifdef NDEBUG
+#define TRY(x) x;
+#else
+ int ret;
+#define TRY(x) \
+ ret = x; \
+ assert (ret >= 0);
+#endif
+
+ assert (gnutls_hmac_get_len (GNUTLS_MAC_SHA1) == 20);
+ TRY (gnutls_hmac_init (&handle, GNUTLS_MAC_SHA1, key, keylen));
+
+ TRY (gnutls_hmac (handle, msg, 2));
+ TRY (gnutls_hmac (handle, &fakelen, 2));
+ TRY (gnutls_hmac (handle, msg + 4, len - 28));
+
+ /* RFC 3489 specifies that the message's size should be 64 bytes,
+ and \x00 padding should be done */
+ if (padding && ((len - 24) % 64) > 0) {
+ uint16_t pad_size = 64 - ((len - 24) % 64);
+
+ TRY (gnutls_hmac (handle, pad_char, pad_size));
+ }
+
+ gnutls_hmac_deinit (handle, sha);
+
+#undef TRY
+}
+#endif /* HAVE_OPENSSL */
+}
+
+static const uint8_t *priv_trim_var (const uint8_t *var, size_t *var_len)
+{
+ const uint8_t *ptr = var;
+
+ while (*ptr == '"') {
+ ptr++;
+ (*var_len)--;
+ }
+ while(ptr[*var_len-1] == '"' ||
+ ptr[*var_len-1] == 0) {
+ (*var_len)--;
+ }
+
+ return ptr;
+}
+
+
+void stun_hash_creds (const uint8_t *realm, size_t realm_len,
+ const uint8_t *username, size_t username_len,
+ const uint8_t *password, size_t password_len,
+ unsigned char md5[16])
+{
+ const uint8_t *username_trimmed = priv_trim_var (username, &username_len);
+ const uint8_t *password_trimmed = priv_trim_var (password, &password_len);
+ const uint8_t *realm_trimmed = priv_trim_var (realm, &realm_len);
+ const uint8_t *colon = (uint8_t *)":";
+
+#ifdef HAVE_OPENSSL
+ EVP_MD_CTX *ctx;
+
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
+ (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
+ ctx = EVP_MD_CTX_create ();
+#else
+ ctx = EVP_MD_CTX_new ();
+#endif /* OPENSSL_VERSION_NUMBER */
+
+ EVP_DigestInit_ex (ctx, EVP_md5(), NULL);
+ EVP_DigestUpdate (ctx, username_trimmed, username_len);
+ EVP_DigestUpdate (ctx, colon, 1);
+ EVP_DigestUpdate (ctx, realm_trimmed, realm_len);
+ EVP_DigestUpdate (ctx, colon, 1);
+ EVP_DigestUpdate (ctx, password_trimmed, password_len);
+ EVP_DigestFinal_ex (ctx, md5, NULL);
+
+#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
+ (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
+ EVP_MD_CTX_destroy (ctx);
+#else
+ EVP_MD_CTX_free (ctx);
+#endif /* OPENSSL_VERSION_NUMBER */
+
+#else
+ gnutls_hash_hd_t handle;
+
+ gnutls_hash_init (&handle, GNUTLS_DIG_MD5);
+ gnutls_hash (handle, username_trimmed, username_len);
+ gnutls_hash (handle, colon, 1);
+ gnutls_hash (handle, realm_trimmed, realm_len);
+ gnutls_hash (handle, colon, 1);
+ gnutls_hash (handle, password_trimmed, password_len);
+
+ gnutls_hash_deinit (handle, md5);
+#endif /* HAVE_OPENSSL */
+}
+
+
+void stun_make_transid (StunTransactionId id)
+{
+ nice_RAND_nonce (id, 16);
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2008 Nokia Corporation. All rights reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef _STUN_HMAC_H
+#define _STUN_HMAC_H
+
+#include "stunmessage.h"
+
+/*
+ * Computes the MESSAGE-INTEGRITY hash of a STUN message.
+ * @param msg pointer to the STUN message
+ * @param len size of the message from header (inclusive) and up to
+ * MESSAGE-INTEGRITY attribute (inclusive)
+ * @param sha output buffer for SHA1 hash (20 bytes)
+ * @param key HMAC key
+ * @param keylen HMAC key bytes length
+ *
+ * @return fingerprint value in <b>host</b> byte order.
+ */
+void stun_sha1 (const uint8_t *msg, size_t len, size_t msg_len,
+ uint8_t *sha, const void *key, size_t keylen, int padding);
+
+/*
+ * SIP H(A1) computation
+ */
+
+void stun_hash_creds (const uint8_t *realm, size_t realm_len,
+ const uint8_t *username, size_t username_len,
+ const uint8_t *password, size_t password_len,
+ unsigned char md5[16]);
+/*
+ * Generates a pseudo-random secure STUN transaction ID.
+ */
+void stun_make_transid (StunTransactionId id);
+
+
+#endif /* _STUN_HMAC_H */
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2007-2009 Nokia Corporation. All rights reserved.
+ * Contact: Rémi Denis-Courmont
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ * Rémi Denis-Courmont, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "stunmessage.h"
+#include "utils.h"
+
+#ifdef _WIN32
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#endif
+
+
+#include <string.h>
+#include <stdlib.h>
+
+bool stun_message_init (StunMessage *msg, StunClass c, StunMethod m,
+ const StunTransactionId id)
+{
+
+ if (msg->buffer_len < STUN_MESSAGE_HEADER_LENGTH)
+ return FALSE;
+
+ memset (msg->buffer, 0, 4);
+ stun_set_type (msg->buffer, c, m);
+
+ memcpy (msg->buffer + STUN_MESSAGE_TRANS_ID_POS,
+ id, STUN_MESSAGE_TRANS_ID_LEN);
+
+ return TRUE;
+}
+
+uint16_t stun_message_length (const StunMessage *msg)
+{
+ return stun_getw (msg->buffer + STUN_MESSAGE_LENGTH_POS) +
+ STUN_MESSAGE_HEADER_LENGTH;
+}
+
+
+
+
+const void *
+stun_message_find (const StunMessage *msg, StunAttribute type,
+ uint16_t *palen)
+{
+ size_t length = stun_message_length (msg);
+ size_t offset = 0;
+
+ /* In MS-TURN, IDs of REALM and NONCE STUN attributes are swapped. */
+ if (msg->agent && msg->agent->compatibility == STUN_COMPATIBILITY_OC2007)
+ {
+ if (type == STUN_ATTRIBUTE_REALM)
+ type = STUN_ATTRIBUTE_NONCE;
+ else if (type == STUN_ATTRIBUTE_NONCE)
+ type = STUN_ATTRIBUTE_REALM;
+ }
+
+ offset = STUN_MESSAGE_ATTRIBUTES_POS;
+
+ while (offset < length)
+ {
+ uint16_t atype = stun_getw (msg->buffer + offset);
+ size_t alen = stun_getw (msg->buffer + offset + STUN_ATTRIBUTE_TYPE_LEN);
+
+
+ offset += STUN_ATTRIBUTE_VALUE_POS;
+
+ if (atype == type)
+ {
+ *palen = alen;
+ return msg->buffer + offset;
+ }
+
+ /* Look for and ignore misordered attributes */
+ switch (atype)
+ {
+ case STUN_ATTRIBUTE_MESSAGE_INTEGRITY:
+ /* Only fingerprint may come after M-I */
+ if (type == STUN_ATTRIBUTE_FINGERPRINT)
+ break;
+ return NULL;
+
+ case STUN_ATTRIBUTE_FINGERPRINT:
+ /* Nothing may come after FPR */
+ return NULL;
+
+ default:
+ /* Nothing misordered. */
+ break;
+ }
+
+ if (!(msg->agent &&
+ (msg->agent->usage_flags & STUN_AGENT_USAGE_NO_ALIGNED_ATTRIBUTES)))
+ alen = stun_align (alen);
+
+ offset += alen;
+ }
+
+ return NULL;
+}
+
+
+StunMessageReturn
+stun_message_find_flag (const StunMessage *msg, StunAttribute type)
+{
+ const void *ptr;
+ uint16_t len = 0;
+
+ ptr = stun_message_find (msg, type, &len);
+ if (ptr == NULL)
+ return STUN_MESSAGE_RETURN_NOT_FOUND;
+ return (len == 0) ? STUN_MESSAGE_RETURN_SUCCESS :
+ STUN_MESSAGE_RETURN_INVALID;
+}
+
+
+StunMessageReturn
+stun_message_find32 (const StunMessage *msg, StunAttribute type,
+ uint32_t *pval)
+{
+ const void *ptr;
+ uint16_t len = 0;
+
+ ptr = stun_message_find (msg, type, &len);
+ if (ptr == NULL)
+ return STUN_MESSAGE_RETURN_NOT_FOUND;
+
+ if (len == 4)
+ {
+ uint32_t val;
+
+ memcpy (&val, ptr, sizeof (val));
+ *pval = ntohl (val);
+ return STUN_MESSAGE_RETURN_SUCCESS;
+ }
+ return STUN_MESSAGE_RETURN_INVALID;
+}
+
+
+StunMessageReturn
+stun_message_find64 (const StunMessage *msg, StunAttribute type,
+ uint64_t *pval)
+{
+ const void *ptr;
+ uint16_t len = 0;
+
+ ptr = stun_message_find (msg, type, &len);
+ if (ptr == NULL)
+ return STUN_MESSAGE_RETURN_NOT_FOUND;
+
+ if (len == 8)
+ {
+ uint32_t tab[2];
+
+ memcpy (tab, ptr, sizeof (tab));
+ *pval = ((uint64_t)ntohl (tab[0]) << 32) | ntohl (tab[1]);
+ return STUN_MESSAGE_RETURN_SUCCESS;
+ }
+ return STUN_MESSAGE_RETURN_INVALID;
+}
+
+
+StunMessageReturn
+stun_message_find_string (const StunMessage *msg, StunAttribute type,
+ char *buf, size_t buflen)
+{
+ const unsigned char *ptr;
+ uint16_t len = 0;
+
+ ptr = stun_message_find (msg, type, &len);
+ if (ptr == NULL)
+ return STUN_MESSAGE_RETURN_NOT_FOUND;
+
+ if (len >= buflen)
+ return STUN_MESSAGE_RETURN_NOT_ENOUGH_SPACE;
+
+ memcpy (buf, ptr, len);
+ buf[len] = '\0';
+ return STUN_MESSAGE_RETURN_SUCCESS;
+}
+
+
+StunMessageReturn
+stun_message_find_addr (const StunMessage *msg, StunAttribute type,
+ struct sockaddr_storage *addr, socklen_t *addrlen)
+{
+ const uint8_t *ptr;
+ uint16_t len = 0;
+
+ ptr = stun_message_find (msg, type, &len);
+ if (ptr == NULL)
+ return STUN_MESSAGE_RETURN_NOT_FOUND;
+
+ if (len < 4)
+ return STUN_MESSAGE_RETURN_INVALID;
+
+ switch (ptr[1])
+ {
+ case 1:
+ {
+ struct sockaddr_in *ip4 = (struct sockaddr_in *)addr;
+ if (((size_t) *addrlen < sizeof (*ip4)) || (len != 8))
+ {
+ *addrlen = sizeof (*ip4);
+ return STUN_MESSAGE_RETURN_INVALID;
+ }
+
+ memset (ip4, 0, *addrlen);
+ ip4->sin_family = AF_INET;
+#ifdef HAVE_SA_LEN
+ ip4->sin_len =
+#endif
+ *addrlen = sizeof (*ip4);
+ memcpy (&ip4->sin_port, ptr + 2, 2);
+ memcpy (&ip4->sin_addr, ptr + 4, 4);
+ return STUN_MESSAGE_RETURN_SUCCESS;
+ }
+
+ case 2:
+ {
+ struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)addr;
+ if (((size_t) *addrlen < sizeof (*ip6)) || (len != 20))
+ {
+ *addrlen = sizeof (*ip6);
+ return STUN_MESSAGE_RETURN_INVALID;
+ }
+
+ memset (ip6, 0, *addrlen);
+ ip6->sin6_family = AF_INET6;
+#ifdef HAVE_SA_LEN
+ ip6->sin6_len =
+#endif
+ *addrlen = sizeof (*ip6);
+ memcpy (&ip6->sin6_port, ptr + 2, 2);
+ memcpy (&ip6->sin6_addr, ptr + 4, 16);
+ return STUN_MESSAGE_RETURN_SUCCESS;
+ }
+
+ default:
+ return STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS;
+ }
+}
+
+StunMessageReturn
+stun_message_find_xor_addr (const StunMessage *msg, StunAttribute type,
+ struct sockaddr_storage *addr, socklen_t *addrlen)
+{
+ StunMessageReturn val = stun_message_find_addr (msg, type, addr, addrlen);
+ if (val)
+ return val;
+
+ return stun_xor_address (msg, addr, *addrlen, STUN_MAGIC_COOKIE);
+}
+
+StunMessageReturn
+stun_message_find_xor_addr_full (const StunMessage *msg, StunAttribute type,
+ struct sockaddr_storage *addr, socklen_t *addrlen, uint32_t magic_cookie)
+{
+ StunMessageReturn val = stun_message_find_addr (msg, type, addr, addrlen);
+ if (val)
+ return val;
+
+ return stun_xor_address (msg, addr, *addrlen, magic_cookie);
+}
+
+StunMessageReturn
+stun_message_find_error (const StunMessage *msg, int *code)
+{
+ uint16_t alen = 0;
+ const uint8_t *ptr = stun_message_find (msg, STUN_ATTRIBUTE_ERROR_CODE, &alen);
+ uint8_t class, number;
+
+ if (ptr == NULL)
+ return STUN_MESSAGE_RETURN_NOT_FOUND;
+ if (alen < 4)
+ return STUN_MESSAGE_RETURN_INVALID;
+
+ class = ptr[2] & 0x7;
+ number = ptr[3];
+ if ((class < 3) || (class > 6) || (number > 99))
+ return STUN_MESSAGE_RETURN_INVALID;
+
+ *code = (class * 100) + number;
+ return STUN_MESSAGE_RETURN_SUCCESS;
+}
+
+void *
+stun_message_append (StunMessage *msg, StunAttribute type, size_t length)
+{
+ uint8_t *a;
+ uint16_t mlen = stun_message_length (msg);
+
+ /* In MS-TURN, IDs of REALM and NONCE STUN attributes are swapped. */
+ if (msg->agent && msg->agent->compatibility == STUN_COMPATIBILITY_OC2007)
+ {
+ if (type == STUN_ATTRIBUTE_NONCE)
+ type = STUN_ATTRIBUTE_REALM;
+ else if (type == STUN_ATTRIBUTE_REALM)
+ type = STUN_ATTRIBUTE_NONCE;
+ }
+
+ if ((size_t)mlen + STUN_ATTRIBUTE_HEADER_LENGTH + length > msg->buffer_len)
+ return NULL;
+
+
+ a = msg->buffer + mlen;
+ a = stun_setw (a, type);
+ if (msg->agent &&
+ (msg->agent->usage_flags & STUN_AGENT_USAGE_NO_ALIGNED_ATTRIBUTES))
+ {
+ a = stun_setw (a, length);
+ } else {
+ /* NOTE: If cookie is not present, we need to force the attribute length
+ * to a multiple of 4 for compatibility with old RFC3489 */
+ a = stun_setw (a, stun_message_has_cookie (msg) ? length : stun_align (length));
+
+ /* Add padding if needed. Avoid a zero-length memset() call. */
+ if (stun_padding (length) > 0) {
+ memset (a + length, ' ', stun_padding (length));
+ mlen += stun_padding (length);
+ }
+ }
+
+ mlen += 4 + length;
+
+ stun_setw (msg->buffer + STUN_MESSAGE_LENGTH_POS, mlen - STUN_MESSAGE_HEADER_LENGTH);
+ return a;
+}
+
+
+StunMessageReturn
+stun_message_append_bytes (StunMessage *msg, StunAttribute type,
+ const void *data, size_t len)
+{
+ void *ptr = stun_message_append (msg, type, len);
+ if (ptr == NULL)
+ return STUN_MESSAGE_RETURN_NOT_ENOUGH_SPACE;
+
+ if (len > 0)
+ memcpy (ptr, data, len);
+
+ return STUN_MESSAGE_RETURN_SUCCESS;
+}
+
+
+StunMessageReturn
+stun_message_append_flag (StunMessage *msg, StunAttribute type)
+{
+ return stun_message_append_bytes (msg, type, NULL, 0);
+}
+
+
+StunMessageReturn
+stun_message_append32 (StunMessage *msg, StunAttribute type,
+ uint32_t value)
+{
+ value = htonl (value);
+ return stun_message_append_bytes (msg, type, &value, 4);
+}
+
+
+StunMessageReturn
+stun_message_append64 (StunMessage *msg, StunAttribute type,
+ uint64_t value)
+{
+ uint32_t tab[2];
+ tab[0] = htonl ((uint32_t)(value >> 32));
+ tab[1] = htonl ((uint32_t)value);
+ return stun_message_append_bytes (msg, type, tab, 8);
+}
+
+
+StunMessageReturn
+stun_message_append_string (StunMessage * msg, StunAttribute type,
+ const char *str)
+{
+ return stun_message_append_bytes (msg, type, str, strlen (str));
+}
+
+StunMessageReturn
+stun_message_append_addr (StunMessage *msg, StunAttribute type,
+ const struct sockaddr *addr, socklen_t addrlen)
+{
+ const void *pa;
+ uint8_t *ptr;
+ uint16_t alen, port;
+ uint8_t family;
+
+ union {
+ const struct sockaddr *addr;
+ const struct sockaddr_in *in;
+ const struct sockaddr_in6 *in6;
+ } sa;
+
+ if ((size_t) addrlen < sizeof (struct sockaddr))
+ return STUN_MESSAGE_RETURN_INVALID;
+
+ sa.addr = addr;
+
+ switch (addr->sa_family)
+ {
+ case AF_INET:
+ {
+ const struct sockaddr_in *ip4 = sa.in;
+ family = 1;
+ port = ip4->sin_port;
+ alen = 4;
+ pa = &ip4->sin_addr;
+ break;
+ }
+
+ case AF_INET6:
+ {
+ const struct sockaddr_in6 *ip6 = sa.in6;
+ if ((size_t) addrlen < sizeof (*ip6))
+ return STUN_MESSAGE_RETURN_INVALID;
+
+ family = 2;
+ port = ip6->sin6_port;
+ alen = 16;
+ pa = &ip6->sin6_addr;
+ break;
+ }
+
+ default:
+ return STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS;
+ }
+
+ ptr = stun_message_append (msg, type, 4 + alen);
+ if (ptr == NULL)
+ return STUN_MESSAGE_RETURN_NOT_ENOUGH_SPACE;
+
+ ptr[0] = 0;
+ ptr[1] = family;
+ memcpy (ptr + 2, &port, 2);
+ memcpy (ptr + 4, pa, alen);
+ return STUN_MESSAGE_RETURN_SUCCESS;
+}
+
+
+StunMessageReturn
+stun_message_append_xor_addr (StunMessage *msg, StunAttribute type,
+ const struct sockaddr_storage *addr, socklen_t addrlen)
+{
+ StunMessageReturn val;
+ /* Must be big enough to hold any supported address: */
+ struct sockaddr_storage tmpaddr;
+
+ if ((size_t) addrlen > sizeof (tmpaddr))
+ addrlen = sizeof (tmpaddr);
+ memcpy (&tmpaddr, addr, addrlen);
+
+ val = stun_xor_address (msg, &tmpaddr, addrlen,
+ STUN_MAGIC_COOKIE);
+ if (val)
+ return val;
+
+ return stun_message_append_addr (msg, type, (struct sockaddr *) &tmpaddr,
+ addrlen);
+}
+
+StunMessageReturn
+stun_message_append_xor_addr_full (StunMessage *msg, StunAttribute type,
+ const struct sockaddr_storage *addr, socklen_t addrlen,
+ uint32_t magic_cookie)
+{
+ StunMessageReturn val;
+ /* Must be big enough to hold any supported address: */
+ struct sockaddr_storage tmpaddr;
+
+ if ((size_t) addrlen > sizeof (tmpaddr))
+ addrlen = sizeof (tmpaddr);
+ memcpy (&tmpaddr, addr, addrlen);
+
+ val = stun_xor_address (msg, &tmpaddr, addrlen, magic_cookie);
+ if (val)
+ return val;
+
+ return stun_message_append_addr (msg, type, (struct sockaddr *) &tmpaddr,
+ addrlen);
+}
+
+
+
+StunMessageReturn
+stun_message_append_error (StunMessage *msg, StunError code)
+{
+ const char *str = stun_strerror (code);
+ size_t len = strlen (str);
+
+ uint8_t *ptr = stun_message_append (msg, STUN_ATTRIBUTE_ERROR_CODE, 4 + len);
+ if (ptr == NULL)
+ return STUN_MESSAGE_RETURN_NOT_ENOUGH_SPACE;
+
+ memset (ptr, 0, 2);
+ ptr[2] = code / 100;
+ ptr[3] = code % 100;
+ memcpy (ptr + 4, str, len);
+ return STUN_MESSAGE_RETURN_SUCCESS;
+}
+
+/* Fast validity check for a potential STUN packet. Examines the type and
+ * length, but none of the attributes. Designed to allow vectored I/O on all
+ * incoming packets, filtering packets for closer inspection as to whether
+ * they’re STUN packets. If they look like they might be, their buffers are
+ * compacted to allow a more thorough check. */
+ssize_t stun_message_validate_buffer_length_fast (StunInputVector *buffers,
+ int n_buffers, size_t total_length, bool has_padding)
+{
+ size_t mlen;
+
+ if (total_length < 1 || n_buffers == 0 || buffers[0].buffer == NULL)
+ {
+ stun_debug ("STUN error: No data!");
+ return STUN_MESSAGE_BUFFER_INVALID;
+ }
+
+ if (buffers[0].buffer[0] >> 6)
+ {
+ return STUN_MESSAGE_BUFFER_INVALID; // RTP or other non-STUN packet
+ }
+
+ if (total_length < STUN_MESSAGE_LENGTH_POS + STUN_MESSAGE_LENGTH_LEN)
+ {
+ stun_debug ("STUN error: Incomplete STUN message header!");
+ return STUN_MESSAGE_BUFFER_INCOMPLETE;
+ }
+
+ if (buffers[0].size >= STUN_MESSAGE_LENGTH_POS + STUN_MESSAGE_LENGTH_LEN) {
+ /* Fast path. */
+ mlen = stun_getw (buffers[0].buffer + STUN_MESSAGE_LENGTH_POS);
+ } else {
+ /* Slow path. Tiny buffers abound. */
+ size_t skip_remaining = STUN_MESSAGE_LENGTH_POS;
+ unsigned int i;
+
+ /* Skip bytes. */
+ for (i = 0; (n_buffers >= 0 && i < (unsigned int) n_buffers) ||
+ (n_buffers < 0 && buffers[i].buffer != NULL); i++) {
+ if (buffers[i].size <= skip_remaining)
+ skip_remaining -= buffers[i].size;
+ else
+ break;
+ }
+
+ /* Read bytes. May be split over two buffers. We’ve already checked that
+ * @total_length is long enough, so @n_buffers should be too. */
+ if (buffers[i].size - skip_remaining > 1) {
+ mlen = stun_getw (buffers[i].buffer + skip_remaining);
+ } else {
+ mlen = (*(buffers[i].buffer + skip_remaining) << 8) |
+ (*(buffers[i + 1].buffer));
+ }
+ }
+
+ mlen += STUN_MESSAGE_HEADER_LENGTH;
+
+ if (has_padding && stun_padding (mlen)) {
+ stun_debug ("STUN error: Invalid message length: %u!", (unsigned)mlen);
+ return STUN_MESSAGE_BUFFER_INVALID; // wrong padding
+ }
+
+ if (total_length < mlen) {
+ stun_debug ("STUN error: Incomplete message: %u of %u bytes!",
+ (unsigned) total_length, (unsigned) mlen);
+ return STUN_MESSAGE_BUFFER_INCOMPLETE; // partial message
+ }
+
+ return mlen;
+}
+
+int stun_message_validate_buffer_length (const uint8_t *msg, size_t length,
+ bool has_padding)
+{
+ ssize_t fast_retval;
+ size_t mlen;
+ size_t len;
+ StunInputVector input_buffer = { msg, length };
+
+ /* Fast pre-check first. */
+ fast_retval = stun_message_validate_buffer_length_fast (&input_buffer, 1,
+ length, has_padding);
+ if (fast_retval <= 0)
+ return fast_retval;
+
+ mlen = fast_retval;
+
+ /* Skip past the header (validated above). */
+ msg += 20;
+ len = mlen - 20;
+
+ /* from then on, we know we have the entire packet in buffer */
+ while (len > 0)
+ {
+ size_t alen;
+
+ if (len < 4)
+ {
+ stun_debug ("STUN error: Incomplete STUN attribute header of length "
+ "%u bytes!", (unsigned)len);
+ return STUN_MESSAGE_BUFFER_INVALID;
+ }
+
+ alen = stun_getw (msg + STUN_ATTRIBUTE_TYPE_LEN);
+ if (has_padding)
+ alen = stun_align (alen);
+
+ /* thanks to padding check, if (end > msg) then there is not only one
+ * but at least 4 bytes left */
+ len -= 4;
+
+ if (len < alen)
+ {
+ stun_debug ("STUN error: %u instead of %u bytes for attribute!",
+ (unsigned)len, (unsigned)alen);
+ return STUN_MESSAGE_BUFFER_INVALID; // no room for attribute value + padding
+ }
+
+ len -= alen;
+ msg += 4 + alen;
+ }
+
+ return mlen;
+}
+
+void stun_message_id (const StunMessage *msg, StunTransactionId id)
+{
+ memcpy (id, msg->buffer + STUN_MESSAGE_TRANS_ID_POS, STUN_MESSAGE_TRANS_ID_LEN);
+}
+
+StunMethod stun_message_get_method (const StunMessage *msg)
+{
+ uint16_t t = stun_getw (msg->buffer);
+ /* HACK HACK HACK
+ A google/msn data indication is 0x0115 which is contrary to the RFC 5389
+ which states that 8th and 12th bits are for the class and that 0x01 is
+ for indications...
+ So 0x0115 is reported as a "connect error response", while it should be
+ a data indication, which message type should actually be 0x0017
+ This should fix the issue, and it's considered safe since the "connect"
+ method doesn't exist anymore */
+ if (t == 0x0115)
+ t = 0x0017;
+ return (StunMethod)(((t & 0x3e00) >> 2) | ((t & 0x00e0) >> 1) |
+ (t & 0x000f));
+}
+
+
+StunClass stun_message_get_class (const StunMessage *msg)
+{
+ uint16_t t = stun_getw (msg->buffer);
+ /* HACK HACK HACK
+ A google/msn data indication is 0x0115 which is contrary to the RFC 5389
+ which states that 8th and 12th bits are for the class and that 0x01 is
+ for indications...
+ So 0x0115 is reported as a "connect error response", while it should be
+ a data indication, which message type should actually be 0x0017
+ This should fix the issue, and it's considered safe since the "connect"
+ method doesn't exist anymore */
+ if (t == 0x0115)
+ t = 0x0017;
+ return (StunClass)(((t & 0x0100) >> 7) | ((t & 0x0010) >> 4));
+}
+
+bool stun_message_has_attribute (const StunMessage *msg, StunAttribute type)
+{
+ uint16_t dummy;
+ return stun_message_find (msg, type, &dummy) != NULL;
+}
+
+
+bool stun_optional (uint16_t t)
+{
+ return (t >> 15) == 1;
+}
+
+const char *stun_strerror (StunError code)
+{
+ static const struct
+ {
+ StunError code;
+ char phrase[32];
+ } tab[] =
+ {
+ { STUN_ERROR_TRY_ALTERNATE, "Try alternate server" },
+ { STUN_ERROR_BAD_REQUEST, "Bad request" },
+ { STUN_ERROR_UNAUTHORIZED, "Unauthorized" },
+ { STUN_ERROR_UNKNOWN_ATTRIBUTE, "Unknown Attribute" },
+ { STUN_ERROR_ALLOCATION_MISMATCH, "Allocation Mismatch" },
+ { STUN_ERROR_STALE_NONCE, "Stale Nonce" },
+ { STUN_ERROR_ACT_DST_ALREADY, "Active Destination Already Set" },
+ { STUN_ERROR_UNSUPPORTED_FAMILY, "Address Family not Supported" },
+ { STUN_ERROR_UNSUPPORTED_TRANSPORT, "Unsupported Transport Protocol" },
+ { STUN_ERROR_INVALID_IP, "Invalid IP Address" },
+ { STUN_ERROR_INVALID_PORT, "Invalid Port" },
+ { STUN_ERROR_OP_TCP_ONLY, "Operation for TCP Only" },
+ { STUN_ERROR_CONN_ALREADY, "Connection Already Exists" },
+ { STUN_ERROR_ALLOCATION_QUOTA_REACHED, "Allocation Quota Reached" },
+ { STUN_ERROR_ROLE_CONFLICT, "Role conflict" },
+ { STUN_ERROR_SERVER_ERROR, "Server Error" },
+ { STUN_ERROR_SERVER_CAPACITY, "Insufficient Capacity" },
+ { STUN_ERROR_INSUFFICIENT_CAPACITY, "Insufficient Capacity" },
+ };
+ const char *str = "Unknown error";
+ size_t i;
+
+ for (i = 0; i < (sizeof (tab) / sizeof (tab[0])); i++)
+ {
+ if (tab[i].code == code)
+ {
+ str = tab[i].phrase;
+ break;
+ }
+ }
+
+ /* Maximum allowed error message length */
+ // assert (strlen (str) < 128);
+ return str;
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2008-2009 Nokia Corporation. All rights reserved.
+ * Contact: Rémi Denis-Courmont
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ * Rémi Denis-Courmont, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef _STUN_MESSAGE_H
+#define _STUN_MESSAGE_H
+
+
+/**
+ * SECTION:stunmessage
+ * @short_description: STUN messages parsing and formatting functions
+ * @include: stun/stunmessage.h
+ * @see_also: #StunAgent
+ * @stability: Stable
+ *
+ * The STUN Messages API allows you to create STUN messages easily as well as to
+ * parse existing messages.
+ *
+ */
+
+
+#ifdef _WIN32
+#include "win32_common.h"
+#else
+#include <stdint.h>
+#include <stdbool.h>
+#endif
+
+#include <sys/types.h>
+
+#ifdef _WIN32
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#endif
+
+#include "constants.h"
+
+typedef struct _StunMessage StunMessage;
+
+/**
+ * StunClass:
+ * @STUN_REQUEST: A STUN Request message
+ * @STUN_INDICATION: A STUN indication message
+ * @STUN_RESPONSE: A STUN Response message
+ * @STUN_ERROR: A STUN Error message
+ *
+ * This enum is used to represent the class of
+ * a STUN message, as defined in RFC5389
+ */
+
+/* Message classes */
+typedef enum
+{
+ STUN_REQUEST=0,
+ STUN_INDICATION=1,
+ STUN_RESPONSE=2,
+ STUN_ERROR=3
+} StunClass;
+
+
+/**
+ * StunMethod:
+ * @STUN_BINDING: The Binding method as defined by the RFC5389
+ * @STUN_SHARED_SECRET: The Shared-Secret method as defined by the RFC3489
+ * @STUN_ALLOCATE: The Allocate method as defined by the TURN draft 12
+ * @STUN_SET_ACTIVE_DST: The Set-Active-Destination method as defined by
+ * the TURN draft 4
+ * @STUN_REFRESH: The Refresh method as defined by the TURN draft 12
+ * @STUN_SEND: The Send method as defined by the TURN draft 00
+ * @STUN_CONNECT: The Connect method as defined by the TURN draft 4
+ * @STUN_OLD_SET_ACTIVE_DST: The older Set-Active-Destination method as
+ * defined by the TURN draft 0
+ * @STUN_IND_SEND: The Send method used in indication messages as defined
+ * by the TURN draft 12
+ * @STUN_IND_DATA: The Data method used in indication messages as defined
+ * by the TURN draft 12
+ * @STUN_IND_CONNECT_STATUS: The Connect-Status method used in indication
+ * messages as defined by the TURN draft 4
+ * @STUN_CREATEPERMISSION: The CreatePermission method as defined by
+ * the TURN draft 12
+ * @STUN_CHANNELBIND: The ChannelBind method as defined by the TURN draft 12
+ *
+ * This enum is used to represent the method of
+ * a STUN message, as defined by various RFCs
+ */
+/* Message methods */
+typedef enum
+{
+ STUN_BINDING=0x001, /* RFC5389 */
+ STUN_SHARED_SECRET=0x002, /* old RFC3489 */
+ STUN_ALLOCATE=0x003, /* TURN-12 */
+ STUN_SET_ACTIVE_DST=0x004, /* TURN-04 */
+ STUN_REFRESH=0x004, /* TURN-12 */
+ STUN_SEND=0x004, /* TURN-00 */
+ STUN_CONNECT=0x005, /* TURN-04 */
+ STUN_OLD_SET_ACTIVE_DST=0x006, /* TURN-00 */
+ STUN_IND_SEND=0x006, /* TURN-12 */
+ STUN_IND_DATA=0x007, /* TURN-12 */
+ STUN_IND_CONNECT_STATUS=0x008, /* TURN-04 */
+ STUN_CREATEPERMISSION= 0x008, /* TURN-12 */
+ STUN_CHANNELBIND= 0x009 /* TURN-12 */
+} StunMethod;
+
+/**
+ * StunAttribute:
+ * @STUN_ATTRIBUTE_MAPPED_ADDRESS: The MAPPED-ADDRESS attribute as defined
+ * by RFC5389
+ * @STUN_ATTRIBUTE_RESPONSE_ADDRESS: The RESPONSE-ADDRESS attribute as defined
+ * by RFC3489
+ * @STUN_ATTRIBUTE_CHANGE_REQUEST: The CHANGE-REQUEST attribute as defined by
+ * RFC3489
+ * @STUN_ATTRIBUTE_SOURCE_ADDRESS: The SOURCE-ADDRESS attribute as defined by
+ * RFC3489
+ * @STUN_ATTRIBUTE_CHANGED_ADDRESS: The CHANGED-ADDRESS attribute as defined
+ * by RFC3489
+ * @STUN_ATTRIBUTE_USERNAME: The USERNAME attribute as defined by RFC5389
+ * @STUN_ATTRIBUTE_PASSWORD: The PASSWORD attribute as defined by RFC3489
+ * @STUN_ATTRIBUTE_MESSAGE_INTEGRITY: The MESSAGE-INTEGRITY attribute as defined
+ * by RFC5389
+ * @STUN_ATTRIBUTE_ERROR_CODE: The ERROR-CODE attribute as defined by RFC5389
+ * @STUN_ATTRIBUTE_UNKNOWN_ATTRIBUTES: The UNKNOWN-ATTRIBUTES attribute as
+ * defined by RFC5389
+ * @STUN_ATTRIBUTE_REFLECTED_FROM: The REFLECTED-FROM attribute as defined
+ * by RFC3489
+ * @STUN_ATTRIBUTE_CHANNEL_NUMBER: The CHANNEL-NUMBER attribute as defined by
+ * TURN draft 09 and 12
+ * @STUN_ATTRIBUTE_LIFETIME: The LIFETIME attribute as defined by TURN
+ * draft 04, 09 and 12
+ * @STUN_ATTRIBUTE_MS_ALTERNATE_SERVER: The ALTERNATE-SERVER attribute as
+ * defined by [MS-TURN]
+ * @STUN_ATTRIBUTE_MAGIC_COOKIE: The MAGIC-COOKIE attribute as defined by
+ * the rosenberg-midcom TURN draft 08
+ * @STUN_ATTRIBUTE_BANDWIDTH: The BANDWIDTH attribute as defined by TURN draft 04
+ * @STUN_ATTRIBUTE_DESTINATION_ADDRESS: The DESTINATION-ADDRESS attribute as
+ * defined by the rosenberg-midcom TURN draft 08
+ * @STUN_ATTRIBUTE_REMOTE_ADDRESS: The REMOTE-ADDRESS attribute as defined by
+ * TURN draft 04
+ * @STUN_ATTRIBUTE_PEER_ADDRESS: The PEER-ADDRESS attribute as defined by
+ * TURN draft 09
+ * @STUN_ATTRIBUTE_XOR_PEER_ADDRESS: The XOR-PEER-ADDRESS attribute as defined
+ * by TURN draft 12
+ * @STUN_ATTRIBUTE_DATA: The DATA attribute as defined by TURN draft 04,
+ * 09 and 12
+ * @STUN_ATTRIBUTE_REALM: The REALM attribute as defined by RFC5389
+ * @STUN_ATTRIBUTE_NONCE: The NONCE attribute as defined by RFC5389
+ * @STUN_ATTRIBUTE_RELAY_ADDRESS: The RELAY-ADDRESS attribute as defined by
+ * TURN draft 04
+ * @STUN_ATTRIBUTE_RELAYED_ADDRESS: The RELAYED-ADDRESS attribute as defined by
+ * TURN draft 09
+ * @STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS: The XOR-RELAYED-ADDRESS attribute as
+ * defined by TURN draft 12
+ * @STUN_ATTRIBUTE_REQUESTED_ADDRESS_TYPE: The REQUESTED-ADDRESS-TYPE attribute
+ * as defined by TURN-IPV6 draft 05
+ * @STUN_ATTRIBUTE_REQUESTED_PORT_PROPS: The REQUESTED-PORT-PROPS attribute
+ * as defined by TURN draft 04
+ * @STUN_ATTRIBUTE_REQUESTED_PROPS: The REQUESTED-PROPS attribute as defined
+ * by TURN draft 09
+ * @STUN_ATTRIBUTE_EVEN_PORT: The EVEN-PORT attribute as defined by TURN draft 12
+ * @STUN_ATTRIBUTE_REQUESTED_TRANSPORT: The REQUESTED-TRANSPORT attribute as
+ * defined by TURN draft 12
+ * @STUN_ATTRIBUTE_DONT_FRAGMENT: The DONT-FRAGMENT attribute as defined
+ * by TURN draft 12
+ * @STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS: The XOR-MAPPED-ADDRESS attribute as
+ * defined by RFC5389
+ * @STUN_ATTRIBUTE_TIMER_VAL: The TIMER-VAL attribute as defined by TURN draft 04
+ * @STUN_ATTRIBUTE_REQUESTED_IP: The REQUESTED-IP attribute as defined by
+ * TURN draft 04
+ * @STUN_ATTRIBUTE_RESERVATION_TOKEN: The RESERVATION-TOKEN attribute as defined
+ * by TURN draft 09 and 12
+ * @STUN_ATTRIBUTE_CONNECT_STAT: The CONNECT-STAT attribute as defined by TURN
+ * draft 04
+ * @STUN_ATTRIBUTE_PRIORITY: The PRIORITY attribute as defined by ICE draft 19
+ * @STUN_ATTRIBUTE_USE_CANDIDATE: The USE-CANDIDATE attribute as defined by
+ * ICE draft 19
+ * @STUN_ATTRIBUTE_OPTIONS: The OPTIONS optional attribute as defined by
+ * libjingle
+ * @STUN_ATTRIBUTE_MS_VERSION: The MS-VERSION optional attribute as defined
+ * by [MS-TURN]
+ * @STUN_ATTRIBUTE_MS_XOR_MAPPED_ADDRESS: The XOR-MAPPED-ADDRESS optional
+ * attribute as defined by [MS-TURN]
+ * @STUN_ATTRIBUTE_SOFTWARE: The SOFTWARE optional attribute as defined by RFC5389
+ * @STUN_ATTRIBUTE_ALTERNATE_SERVER: The ALTERNATE-SERVER optional attribute as
+ * defined by RFC5389
+ * @STUN_ATTRIBUTE_FINGERPRINT: The FINGERPRINT optional attribute as defined
+ * by RFC5389
+ * @STUN_ATTRIBUTE_ICE_CONTROLLED: The ICE-CONTROLLED optional attribute as
+ * defined by ICE draft 19
+ * @STUN_ATTRIBUTE_ICE_CONTROLLING: The ICE-CONTROLLING optional attribute as
+ * defined by ICE draft 19
+ * @STUN_ATTRIBUTE_MS_SEQUENCE_NUMBER: The MS-SEQUENCE NUMBER optional attribute
+ * as defined by [MS-TURN]
+ * @STUN_ATTRIBUTE_CANDIDATE_IDENTIFIER: The CANDIDATE-IDENTIFIER optional
+ * attribute as defined by [MS-ICE2]
+ * @STUN_ATTRIBUTE_MS_IMPLEMENTATION_VERSION: The IMPLEMENTATION-VERSION
+ * optional attribute as defined by [MS-ICE2]
+ * @STUN_ATTRIBUTE_NOMINATION: The NOMINATION attribute as defined by
+ * draft-thatcher-ice-renomination-00 and deployed in Google Chrome
+ *
+ * Known STUN attribute types as defined by various RFCs and drafts
+ */
+/* Should be in sync with stun_is_unknown() */
+typedef enum
+{
+ /* Mandatory attributes */
+ /* 0x0000 */ /* reserved */
+ STUN_ATTRIBUTE_MAPPED_ADDRESS=0x0001, /* RFC5389 */
+ STUN_ATTRIBUTE_RESPONSE_ADDRESS=0x0002, /* old RFC3489 */
+ STUN_ATTRIBUTE_CHANGE_REQUEST=0x0003, /* old RFC3489 */
+ STUN_ATTRIBUTE_SOURCE_ADDRESS=0x0004, /* old RFC3489 */
+ STUN_ATTRIBUTE_CHANGED_ADDRESS=0x0005, /* old RFC3489 */
+ STUN_ATTRIBUTE_USERNAME=0x0006, /* RFC5389 */
+ STUN_ATTRIBUTE_PASSWORD=0x0007, /* old RFC3489 */
+ STUN_ATTRIBUTE_MESSAGE_INTEGRITY=0x0008, /* RFC5389 */
+ STUN_ATTRIBUTE_ERROR_CODE=0x0009, /* RFC5389 */
+ STUN_ATTRIBUTE_UNKNOWN_ATTRIBUTES=0x000A, /* RFC5389 */
+ STUN_ATTRIBUTE_REFLECTED_FROM=0x000B, /* old RFC3489 */
+ STUN_ATTRIBUTE_CHANNEL_NUMBER=0x000C, /* TURN-12 */
+ STUN_ATTRIBUTE_LIFETIME=0x000D, /* TURN-12 */
+ /* MS_ALTERNATE_SERVER is only used by Microsoft's dialect, probably should
+ * not to be placed in STUN_ALL_KNOWN_ATTRIBUTES */
+ STUN_ATTRIBUTE_MS_ALTERNATE_SERVER=0x000E, /* MS-TURN */
+ STUN_ATTRIBUTE_MAGIC_COOKIE=0x000F, /* midcom-TURN 08 */
+ STUN_ATTRIBUTE_BANDWIDTH=0x0010, /* TURN-04 */
+ STUN_ATTRIBUTE_DESTINATION_ADDRESS=0x0011, /* midcom-TURN 08 */
+ STUN_ATTRIBUTE_REMOTE_ADDRESS=0x0012, /* TURN-04 */
+ STUN_ATTRIBUTE_PEER_ADDRESS=0x0012, /* TURN-09 */
+ STUN_ATTRIBUTE_XOR_PEER_ADDRESS=0x0012, /* TURN-12 */
+ STUN_ATTRIBUTE_DATA=0x0013, /* TURN-12 */
+ STUN_ATTRIBUTE_REALM=0x0014, /* RFC5389 */
+ STUN_ATTRIBUTE_NONCE=0x0015, /* RFC5389 */
+ STUN_ATTRIBUTE_RELAY_ADDRESS=0x0016, /* TURN-04 */
+ STUN_ATTRIBUTE_RELAYED_ADDRESS=0x0016, /* TURN-09 */
+ STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS=0x0016, /* TURN-12 */
+ STUN_ATTRIBUTE_REQUESTED_ADDRESS_TYPE=0x0017, /* TURN-IPv6-05 */
+ STUN_ATTRIBUTE_REQUESTED_PORT_PROPS=0x0018, /* TURN-04 */
+ STUN_ATTRIBUTE_REQUESTED_PROPS=0x0018, /* TURN-09 */
+ STUN_ATTRIBUTE_EVEN_PORT=0x0018, /* TURN-12 */
+ STUN_ATTRIBUTE_REQUESTED_TRANSPORT=0x0019, /* TURN-12 */
+ STUN_ATTRIBUTE_DONT_FRAGMENT=0x001A, /* TURN-12 */
+ /* 0x001B */ /* reserved */
+ /* 0x001C */ /* reserved */
+ /* 0x001D */ /* reserved */
+ /* 0x001E */ /* reserved */
+ /* 0x001F */ /* reserved */
+ STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS=0x0020, /* RFC5389 */
+ STUN_ATTRIBUTE_TIMER_VAL=0x0021, /* TURN-04 */
+ STUN_ATTRIBUTE_REQUESTED_IP=0x0022, /* TURN-04 */
+ STUN_ATTRIBUTE_RESERVATION_TOKEN=0x0022, /* TURN-09 */
+ STUN_ATTRIBUTE_CONNECT_STAT=0x0023, /* TURN-04 */
+ STUN_ATTRIBUTE_PRIORITY=0x0024, /* ICE-19 */
+ STUN_ATTRIBUTE_USE_CANDIDATE=0x0025, /* ICE-19 */
+ /* 0x0026 */ /* reserved */
+ /* 0x0027 */ /* reserved */
+ /* 0x0028 */ /* reserved */
+ /* 0x0029 */ /* reserved */
+ /* 0x002A-0x7fff */ /* reserved */
+
+ /* Optional attributes */
+ /* 0x8000-0x8021 */ /* reserved */
+ STUN_ATTRIBUTE_OPTIONS=0x8001, /* libjingle */
+ STUN_ATTRIBUTE_MS_VERSION=0x8008, /* MS-TURN */
+ STUN_ATTRIBUTE_MS_XOR_MAPPED_ADDRESS=0x8020, /* MS-TURN */
+ STUN_ATTRIBUTE_SOFTWARE=0x8022, /* RFC5389 */
+ STUN_ATTRIBUTE_ALTERNATE_SERVER=0x8023, /* RFC5389 */
+ /* 0x8024 */ /* reserved */
+ /* 0x8025 */ /* reserved */
+ /* 0x8026 */ /* reserved */
+ /* 0x8027 */ /* reserved */
+ STUN_ATTRIBUTE_FINGERPRINT=0x8028, /* RFC5389 */
+ STUN_ATTRIBUTE_ICE_CONTROLLED=0x8029, /* ICE-19 */
+ STUN_ATTRIBUTE_ICE_CONTROLLING=0x802A, /* ICE-19 */
+ /* 0x802B-0x804F */ /* reserved */
+ STUN_ATTRIBUTE_MS_SEQUENCE_NUMBER=0x8050, /* MS-TURN */
+ /* 0x8051-0x8053 */ /* reserved */
+ STUN_ATTRIBUTE_CANDIDATE_IDENTIFIER=0x8054, /* MS-ICE2 */
+ /* 0x8055-0x806F */ /* reserved */
+ STUN_ATTRIBUTE_MS_IMPLEMENTATION_VERSION=0x8070, /* MS-ICE2 */
+ /* 0x8071-0xC000 */ /* reserved */
+ STUN_ATTRIBUTE_NOMINATION=0xC001 /* https://tools.ietf.org/html/draft-thatcher-ice-renomination-00 */
+ /* 0xC002-0xFFFF */ /* reserved */
+} StunAttribute;
+
+
+/**
+ * STUN_ALL_KNOWN_ATTRIBUTES:
+ *
+ * An array containing all the currently known and defined mandatory attributes
+ * from StunAttribute
+ */
+/* Should be in sync with StunAttribute */
+static const uint16_t STUN_ALL_KNOWN_ATTRIBUTES[] =
+ {
+ STUN_ATTRIBUTE_MAPPED_ADDRESS,
+ STUN_ATTRIBUTE_RESPONSE_ADDRESS,
+ STUN_ATTRIBUTE_CHANGE_REQUEST,
+ STUN_ATTRIBUTE_SOURCE_ADDRESS,
+ STUN_ATTRIBUTE_CHANGED_ADDRESS,
+ STUN_ATTRIBUTE_USERNAME,
+ STUN_ATTRIBUTE_PASSWORD,
+ STUN_ATTRIBUTE_MESSAGE_INTEGRITY,
+ STUN_ATTRIBUTE_ERROR_CODE,
+ STUN_ATTRIBUTE_UNKNOWN_ATTRIBUTES,
+ STUN_ATTRIBUTE_REFLECTED_FROM,
+ STUN_ATTRIBUTE_CHANNEL_NUMBER,
+ STUN_ATTRIBUTE_LIFETIME,
+ STUN_ATTRIBUTE_MAGIC_COOKIE,
+ STUN_ATTRIBUTE_BANDWIDTH,
+ STUN_ATTRIBUTE_DESTINATION_ADDRESS,
+ STUN_ATTRIBUTE_REMOTE_ADDRESS,
+ STUN_ATTRIBUTE_PEER_ADDRESS,
+ STUN_ATTRIBUTE_XOR_PEER_ADDRESS,
+ STUN_ATTRIBUTE_DATA,
+ STUN_ATTRIBUTE_REALM,
+ STUN_ATTRIBUTE_NONCE,
+ STUN_ATTRIBUTE_RELAY_ADDRESS,
+ STUN_ATTRIBUTE_RELAYED_ADDRESS,
+ STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS,
+ STUN_ATTRIBUTE_REQUESTED_ADDRESS_TYPE,
+ STUN_ATTRIBUTE_REQUESTED_PORT_PROPS,
+ STUN_ATTRIBUTE_REQUESTED_PROPS,
+ STUN_ATTRIBUTE_EVEN_PORT,
+ STUN_ATTRIBUTE_REQUESTED_TRANSPORT,
+ STUN_ATTRIBUTE_DONT_FRAGMENT,
+ STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
+ STUN_ATTRIBUTE_TIMER_VAL,
+ STUN_ATTRIBUTE_REQUESTED_IP,
+ STUN_ATTRIBUTE_RESERVATION_TOKEN,
+ STUN_ATTRIBUTE_CONNECT_STAT,
+ STUN_ATTRIBUTE_PRIORITY,
+ STUN_ATTRIBUTE_USE_CANDIDATE,
+ 0
+ };
+
+/**
+ * STUN_MSOC_KNOWN_ATTRIBUTES:
+ *
+ * An array containing all the currently known mandatory attributes used by
+ * Microsoft Office Communicator as defined in [MS-TURN]
+ */
+static const uint16_t STUN_MSOC_KNOWN_ATTRIBUTES[] =
+ {
+ STUN_ATTRIBUTE_MAPPED_ADDRESS,
+ STUN_ATTRIBUTE_USERNAME,
+ STUN_ATTRIBUTE_MESSAGE_INTEGRITY,
+ STUN_ATTRIBUTE_ERROR_CODE,
+ STUN_ATTRIBUTE_UNKNOWN_ATTRIBUTES,
+ STUN_ATTRIBUTE_LIFETIME,
+ STUN_ATTRIBUTE_MS_ALTERNATE_SERVER,
+ STUN_ATTRIBUTE_MAGIC_COOKIE,
+ STUN_ATTRIBUTE_BANDWIDTH,
+ STUN_ATTRIBUTE_DESTINATION_ADDRESS,
+ STUN_ATTRIBUTE_REMOTE_ADDRESS,
+ STUN_ATTRIBUTE_DATA,
+ /* REALM and NONCE have swapped hexadecimal IDs in [MS-TURN]. Libnice users
+ * or developers can still use these enumeration values in their original
+ * meanings from StunAttribute anywhere in the code, as stun_message_find()
+ * and stun_message_append() will choose correct ID in MSOC compatibility
+ * modes. */
+ STUN_ATTRIBUTE_NONCE,
+ STUN_ATTRIBUTE_REALM,
+ 0
+ };
+
+/**
+ * StunTransactionId:
+ *
+ * A type that holds a STUN transaction id.
+ */
+typedef uint8_t StunTransactionId[STUN_MESSAGE_TRANS_ID_LEN];
+
+
+/**
+ * StunError:
+ * @STUN_ERROR_TRY_ALTERNATE: The ERROR-CODE value for the
+ * "Try Alternate" error as defined in RFC5389
+ * @STUN_ERROR_BAD_REQUEST: The ERROR-CODE value for the
+ * "Bad Request" error as defined in RFC5389
+ * @STUN_ERROR_UNAUTHORIZED: The ERROR-CODE value for the
+ * "Unauthorized" error as defined in RFC5389
+ * @STUN_ERROR_UNKNOWN_ATTRIBUTE: The ERROR-CODE value for the
+ * "Unknown Attribute" error as defined in RFC5389
+ * @STUN_ERROR_ALLOCATION_MISMATCH:The ERROR-CODE value for the
+ * "Allocation Mismatch" error as defined in TURN draft 12.
+ * Equivalent to the "No Binding" error defined in TURN draft 04.
+ * @STUN_ERROR_STALE_NONCE: The ERROR-CODE value for the
+ * "Stale Nonce" error as defined in RFC5389
+ * @STUN_ERROR_ACT_DST_ALREADY: The ERROR-CODE value for the
+ * "Active Destination Already Set" error as defined in TURN draft 04.
+ * @STUN_ERROR_UNSUPPORTED_FAMILY: The ERROR-CODE value for the
+ * "Address Family not Supported" error as defined in TURN IPV6 Draft 05.
+ * @STUN_ERROR_WRONG_CREDENTIALS: The ERROR-CODE value for the
+ * "Wrong Credentials" error as defined in TURN Draft 12.
+ * @STUN_ERROR_UNSUPPORTED_TRANSPORT:he ERROR-CODE value for the
+ * "Unsupported Transport Protocol" error as defined in TURN Draft 12.
+ * @STUN_ERROR_INVALID_IP: The ERROR-CODE value for the
+ * "Invalid IP Address" error as defined in TURN draft 04.
+ * @STUN_ERROR_INVALID_PORT: The ERROR-CODE value for the
+ * "Invalid Port" error as defined in TURN draft 04.
+ * @STUN_ERROR_OP_TCP_ONLY: The ERROR-CODE value for the
+ * "Operation for TCP Only" error as defined in TURN draft 04.
+ * @STUN_ERROR_CONN_ALREADY: The ERROR-CODE value for the
+ * "Connection Already Exists" error as defined in TURN draft 04.
+ * @STUN_ERROR_ALLOCATION_QUOTA_REACHED: The ERROR-CODE value for the
+ * "Allocation Quota Reached" error as defined in TURN draft 12.
+ * @STUN_ERROR_ROLE_CONFLICT:The ERROR-CODE value for the
+ * "Role Conflict" error as defined in ICE draft 19.
+ * @STUN_ERROR_SERVER_ERROR: The ERROR-CODE value for the
+ * "Server Error" error as defined in RFC5389
+ * @STUN_ERROR_SERVER_CAPACITY: The ERROR-CODE value for the
+ * "Insufficient Capacity" error as defined in TURN draft 04.
+ * @STUN_ERROR_INSUFFICIENT_CAPACITY: The ERROR-CODE value for the
+ * "Insufficient Capacity" error as defined in TURN draft 12.
+ * @STUN_ERROR_MAX: The maximum possible ERROR-CODE value as defined by RFC 5389.
+ *
+ * STUN error codes as defined by various RFCs and drafts
+ */
+/* Should be in sync with stun_strerror() */
+typedef enum
+{
+ STUN_ERROR_TRY_ALTERNATE=300, /* RFC5389 */
+ STUN_ERROR_BAD_REQUEST=400, /* RFC5389 */
+ STUN_ERROR_UNAUTHORIZED=401, /* RFC5389 */
+ STUN_ERROR_UNKNOWN_ATTRIBUTE=420, /* RFC5389 */
+ STUN_ERROR_ALLOCATION_MISMATCH=437, /* TURN-12 */
+ STUN_ERROR_STALE_NONCE=438, /* RFC5389 */
+ STUN_ERROR_ACT_DST_ALREADY=439, /* TURN-04 */
+ STUN_ERROR_UNSUPPORTED_FAMILY=440, /* TURN-IPv6-05 */
+ STUN_ERROR_WRONG_CREDENTIALS=441, /* TURN-12 */
+ STUN_ERROR_UNSUPPORTED_TRANSPORT=442, /* TURN-12 */
+ STUN_ERROR_INVALID_IP=443, /* TURN-04 */
+ STUN_ERROR_INVALID_PORT=444, /* TURN-04 */
+ STUN_ERROR_OP_TCP_ONLY=445, /* TURN-04 */
+ STUN_ERROR_CONN_ALREADY=446, /* TURN-04 */
+ STUN_ERROR_ALLOCATION_QUOTA_REACHED=486, /* TURN-12 */
+ STUN_ERROR_ROLE_CONFLICT=487, /* ICE-19 */
+ STUN_ERROR_SERVER_ERROR=500, /* RFC5389 */
+ STUN_ERROR_SERVER_CAPACITY=507, /* TURN-04 */
+ STUN_ERROR_INSUFFICIENT_CAPACITY=508, /* TURN-12 */
+ STUN_ERROR_MAX=699
+} StunError;
+
+
+/**
+ * StunMessageReturn:
+ * @STUN_MESSAGE_RETURN_SUCCESS: The operation was successful
+ * @STUN_MESSAGE_RETURN_NOT_FOUND: The attribute was not found
+ * @STUN_MESSAGE_RETURN_INVALID: The argument or data is invalid
+ * @STUN_MESSAGE_RETURN_NOT_ENOUGH_SPACE: There is not enough space in the
+ * message to append data to it, or not enough in an argument to fill it with
+ * the data requested.
+ * @STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS: The address in the arguments or in
+ * the STUN message is not supported.
+ *
+ * The return value of most stun_message_* functions.
+ * This enum will report on whether an operation was successful or not
+ * and what error occured if any.
+ */
+typedef enum
+{
+ STUN_MESSAGE_RETURN_SUCCESS,
+ STUN_MESSAGE_RETURN_NOT_FOUND,
+ STUN_MESSAGE_RETURN_INVALID,
+ STUN_MESSAGE_RETURN_NOT_ENOUGH_SPACE,
+ STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS
+} StunMessageReturn;
+
+#include "stunagent.h"
+
+/**
+ * STUN_MAX_MESSAGE_SIZE:
+ *
+ * The Maximum size of a STUN message
+ */
+#define STUN_MAX_MESSAGE_SIZE 65552
+
+/**
+ * StunMessage:
+ * @agent: The agent that created or validated this message
+ * @buffer: The buffer containing the STUN message
+ * @buffer_len: The length of the buffer (not the size of the message)
+ * @key: The short term credentials key to use for authentication validation
+ * or that was used to finalize this message
+ * @key_len: The length of the associated key
+ * @long_term_key: The long term credential key to use for authentication
+ * validation or that was used to finalize this message
+ * @long_term_valid: Whether or not the #long_term_key variable contains valid
+ * data
+ *
+ * This structure represents a STUN message
+ */
+struct _StunMessage {
+ StunAgent *agent;
+ uint8_t *buffer;
+ size_t buffer_len;
+ uint8_t *key;
+ size_t key_len;
+ uint8_t long_term_key[16];
+ bool long_term_valid;
+};
+
+/**
+ * stun_message_init:
+ * @msg: The #StunMessage to initialize
+ * @c: STUN message class (host byte order)
+ * @m: STUN message method (host byte order)
+ * @id: 16-bytes transaction ID
+ *
+ * Initializes a STUN message buffer, with no attributes.
+ * Returns: %TRUE if the initialization was successful
+ */
+bool stun_message_init (StunMessage *msg, StunClass c, StunMethod m,
+ const StunTransactionId id);
+
+/**
+ * stun_message_length:
+ * @msg: The #StunMessage
+ *
+ * Get the length of the message (including the header)
+ *
+ * Returns: The length of the message
+ */
+uint16_t stun_message_length (const StunMessage *msg);
+
+/**
+ * stun_message_find:
+ * @msg: The #StunMessage
+ * @type: The #StunAttribute to find
+ * @palen: A pointer to store the length of the attribute
+ *
+ * Finds an attribute in a STUN message and fetches its content
+ *
+ * Returns: A pointer to the start of the attribute payload if found,
+ * otherwise NULL.
+ */
+const void * stun_message_find (const StunMessage * msg, StunAttribute type,
+ uint16_t *palen);
+
+
+/**
+ * stun_message_find_flag:
+ * @msg: The #StunMessage
+ * @type: The #StunAttribute to find
+ *
+ * Looks for a flag attribute within a valid STUN message.
+ *
+ * Returns: A #StunMessageReturn value.
+ * %STUN_MESSAGE_RETURN_INVALID is returned if the attribute's size is not zero.
+ */
+StunMessageReturn stun_message_find_flag (const StunMessage *msg,
+ StunAttribute type);
+
+/**
+ * stun_message_find32:
+ * @msg: The #StunMessage
+ * @type: The #StunAttribute to find
+ * @pval: A pointer where to store the value (host byte order)
+ *
+ * Extracts a 32-bits attribute from a STUN message.
+ *
+ * Returns: A #StunMessageReturn value.
+ * %STUN_MESSAGE_RETURN_INVALID is returned if the attribute's size is not
+ * 4 bytes.
+ */
+StunMessageReturn stun_message_find32 (const StunMessage *msg,
+ StunAttribute type, uint32_t *pval);
+
+/**
+ * stun_message_find64:
+ * @msg: The #StunMessage
+ * @type: The #StunAttribute to find
+ * @pval: A pointer where to store the value (host byte order)
+ *
+ * Extracts a 64-bits attribute from a STUN message.
+ *
+ * Returns: A #StunMessageReturn value.
+ * %STUN_MESSAGE_RETURN_INVALID is returned if the attribute's size is not
+ * 8 bytes.
+ */
+StunMessageReturn stun_message_find64 (const StunMessage *msg,
+ StunAttribute type, uint64_t *pval);
+
+/**
+ * stun_message_find_string:
+ * @msg: The #StunMessage
+ * @type: The #StunAttribute to find
+ * @buf: A pointer where to store the data
+ * @buflen: The length of the buffer
+ *
+ * Extracts an UTF-8 string from a valid STUN message.
+ *
+ * Returns: A #StunMessageReturn value.
+ * %STUN_MESSAGE_RETURN_INVALID is returned if the attribute is improperly
+ * encoded
+ * %STUN_MESSAGE_RETURN_NOT_ENOUGH_SPACE is return if the buffer size is too
+ * small to hold the string
+ *
+ <note>
+ <para>
+ The string will be nul-terminated.
+ </para>
+ </note>
+ *
+ */
+StunMessageReturn stun_message_find_string (const StunMessage *msg,
+ StunAttribute type, char *buf, size_t buflen);
+
+/**
+ * stun_message_find_addr:
+ * @msg: The #StunMessage
+ * @type: The #StunAttribute to find
+ * @addr: The #sockaddr to be filled
+ * @addrlen: The size of the @addr variable. Must be set to the size of the
+ * @addr socket address and will be set to the size of the extracted socket
+ * address.
+ *
+ * Extracts a network address attribute from a STUN message.
+ *
+ * Returns: A #StunMessageReturn value.
+ * %STUN_MESSAGE_RETURN_INVALID is returned if the attribute payload size is
+ * wrong or if the @addrlen is too small
+ * %STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS if the address family is unknown.
+ */
+StunMessageReturn stun_message_find_addr (const StunMessage *msg,
+ StunAttribute type, struct sockaddr_storage *addr, socklen_t *addrlen);
+
+/**
+ * stun_message_find_xor_addr:
+ * @msg: The #StunMessage
+ * @type: The #StunAttribute to find
+ * @addr: The #sockaddr to be filled
+ * @addrlen: The size of the @addr variable. Must be set to the size of the
+ * @addr socket address and will be set to the size of the
+ * extracted socket address.
+ *
+ * Extracts an obfuscated network address attribute from a STUN message.
+ *
+ * Returns: A #StunMessageReturn value.
+ * %STUN_MESSAGE_RETURN_INVALID is returned if the attribute payload size is
+ * wrong or if the @addrlen is too small
+ * %STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS if the address family is unknown.
+ */
+StunMessageReturn stun_message_find_xor_addr (const StunMessage *msg,
+ StunAttribute type, struct sockaddr_storage *addr, socklen_t *addrlen);
+
+/**
+ * stun_message_find_xor_addr_full:
+ * @msg: The #StunMessage
+ * @type: The #StunAttribute to find
+ * @addr: The #sockaddr to be filled
+ * @addrlen: The size of the @addr variable. Must be set to the size of the
+ * @addr socket address and will be set to the size of the
+ * extracted socket address.
+ * @magic_cookie: The magic cookie to use to XOR the address.
+ *
+ * Extracts an obfuscated network address attribute from a STUN message.
+ *
+ * Returns: A #StunMessageReturn value.
+ * %STUN_MESSAGE_RETURN_INVALID is returned if the attribute payload size is
+ * wrong or if the @addrlen is too small
+ * %STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS if the address family is unknown.
+ */
+StunMessageReturn stun_message_find_xor_addr_full (const StunMessage *msg,
+ StunAttribute type, struct sockaddr_storage *addr,
+ socklen_t *addrlen, uint32_t magic_cookie);
+
+
+/**
+ * stun_message_find_error:
+ * @msg: The #StunMessage
+ * @code: A pointer where to store the value
+ *
+ * Extract the error response code from a STUN message
+ *
+ * Returns: A #StunMessageReturn value.
+ * %STUN_MESSAGE_RETURN_INVALID is returned if the value is invalid
+ */
+StunMessageReturn stun_message_find_error (const StunMessage *msg, int *code);
+
+
+/**
+ * stun_message_append:
+ * @msg: The #StunMessage
+ * @type: The #StunAttribute to append
+ * @length: The length of the attribute
+ *
+ * Reserves room for appending an attribute to an unfinished STUN message.
+ *
+ * Returns: A pointer to an unitialized buffer of @length bytes to
+ * where the attribute payload must be written, or NULL if there is not
+ * enough room in the STUN message buffer.
+ */
+void *stun_message_append (StunMessage *msg, StunAttribute type,
+ size_t length);
+
+/**
+ * stun_message_append_bytes:
+ * @msg: The #StunMessage
+ * @type: The #StunAttribute to append
+ * @data: The data to append
+ * @len: The length of the attribute
+ *
+ * Appends a binary value to a STUN message
+ *
+ * Returns: A #StunMessageReturn value.
+ */
+StunMessageReturn stun_message_append_bytes (StunMessage *msg,
+ StunAttribute type, const void *data, size_t len);
+
+/**
+ * stun_message_append_flag:
+ * @msg: The #StunMessage
+ * @type: The #StunAttribute to append
+ *
+ * Appends an empty flag attribute to a STUN message
+ *
+ * Returns: A #StunMessageReturn value.
+ */
+StunMessageReturn stun_message_append_flag (StunMessage *msg,
+ StunAttribute type);
+
+/**
+ * stun_message_append32:
+ * @msg: The #StunMessage
+ * @type: The #StunAttribute to append
+ * @value: The value to append (host byte order)
+ *
+ * Appends a 32-bits value attribute to a STUN message
+ *
+ * Returns: A #StunMessageReturn value.
+ */
+StunMessageReturn stun_message_append32 (StunMessage *msg,
+ StunAttribute type, uint32_t value);
+
+/**
+ * stun_message_append64:
+ * @msg: The #StunMessage
+ * @type: The #StunAttribute to append
+ * @value: The value to append (host byte order)
+ *
+ * Appends a 64-bits value attribute to a STUN message
+ *
+ * Returns: A #StunMessageReturn value.
+ */
+StunMessageReturn stun_message_append64 (StunMessage *msg,
+ StunAttribute type, uint64_t value);
+
+/**
+ * stun_message_append_string:
+ * @msg: The #StunMessage
+ * @type: The #StunAttribute to append
+ * @str: The string to append
+ *
+ * Adds an attribute from a nul-terminated string to a STUN message
+ *
+ * Returns: A #StunMessageReturn value.
+ */
+StunMessageReturn stun_message_append_string (StunMessage *msg,
+ StunAttribute type, const char *str);
+
+/**
+ * stun_message_append_addr:
+ * @msg: The #StunMessage
+ * @type: The #StunAttribute to append
+ * @addr: The #sockaddr to be append
+ * @addrlen: The size of the @addr variable.
+ *
+ * Append a network address attribute to a STUN message
+ *
+ * Returns: A #StunMessageReturn value.
+ * %STUN_MESSAGE_RETURN_INVALID is returned if the @addrlen is too small
+ * %STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS if the address family is unknown.
+ */
+StunMessageReturn stun_message_append_addr (StunMessage * msg,
+ StunAttribute type, const struct sockaddr *addr, socklen_t addrlen);
+
+/**
+ * stun_message_append_xor_addr:
+ * @msg: The #StunMessage
+ * @type: The #StunAttribute to append
+ * @addr: The #sockaddr to be append
+ * @addrlen: The size of the @addr variable.
+ *
+ * Append an obfuscated network address attribute to a STUN message
+ *
+ * Returns: A #StunMessageReturn value.
+ * %STUN_MESSAGE_RETURN_INVALID is returned if the @addrlen is too small
+ * %STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS if the address family is unknown.
+ */
+StunMessageReturn stun_message_append_xor_addr (StunMessage * msg,
+ StunAttribute type, const struct sockaddr_storage *addr, socklen_t addrlen);
+
+/**
+ * stun_message_append_xor_addr_full:
+ * @msg: The #StunMessage
+ * @type: The #StunAttribute to append
+ * @addr: The #sockaddr to be append
+ * @addrlen: The size of the @addr variable.
+ * @magic_cookie: The magic cookie to use to XOR the address.
+ *
+ * Append an obfuscated network address attribute from a STUN message.
+ *
+ * Returns: A #StunMessageReturn value.
+ * %STUN_MESSAGE_RETURN_INVALID is returned if the @addrlen is too small
+ * %STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS if the address family is unknown.
+ */
+StunMessageReturn stun_message_append_xor_addr_full (StunMessage * msg,
+ StunAttribute type, const struct sockaddr_storage *addr, socklen_t addrlen,
+ uint32_t magic_cookie);
+
+/**
+ * stun_message_append_error:
+ * @msg: The #StunMessage
+ * @code: The error code value
+ *
+ * Appends the ERROR-CODE attribute to the STUN message and fills it according
+ * to #code
+ *
+ * Returns: A #StunMessageReturn value.
+ */
+StunMessageReturn stun_message_append_error (StunMessage * msg,
+ StunError code);
+
+/**
+ * STUN_MESSAGE_BUFFER_INCOMPLETE:
+ *
+ * Convenience macro for stun_message_validate_buffer_length() meaning that the
+ * data to validate does not hold a complete STUN message
+ */
+#define STUN_MESSAGE_BUFFER_INCOMPLETE 0
+
+/**
+ * STUN_MESSAGE_BUFFER_INVALID:
+ *
+ * Convenience macro for stun_message_validate_buffer_length() meaning that the
+ * data to validate is not a valid STUN message
+ */
+#define STUN_MESSAGE_BUFFER_INVALID -1
+
+
+/**
+ * stun_message_validate_buffer_length:
+ * @msg: The buffer to validate
+ * @length: The length of the buffer
+ * @has_padding: Set TRUE if attributes should be padded to multiple of 4 bytes
+ *
+ * This function will take a data buffer and will try to validate whether it is
+ * a STUN message or if it's not or if it's an incomplete STUN message and will
+ * provide us with the length of the STUN message.
+ *
+ * Returns: The length of the valid STUN message in the buffer.
+ * <para> See also: #STUN_MESSAGE_BUFFER_INCOMPLETE </para>
+ * <para> See also: #STUN_MESSAGE_BUFFER_INVALID </para>
+ */
+int stun_message_validate_buffer_length (const uint8_t *msg, size_t length,
+ bool has_padding);
+
+/**
+ * StunInputVector:
+ * @buffer: a buffer containing already-received binary data
+ * @size: length of @buffer, in bytes
+ *
+ * Container for a single buffer which also stores its length. This is designed
+ * for vectored I/O: typically an array of #StunInputVectors is passed to
+ * functions, providing multiple buffers which store logically contiguous
+ * received data.
+ *
+ * This is guaranteed to be layed out identically in memory to #GInputVector.
+ *
+ * Since: 0.1.5
+ */
+typedef struct {
+ const uint8_t *buffer;
+ size_t size;
+} StunInputVector;
+
+/**
+ * stun_message_validate_buffer_length_fast:
+ * @buffers: (array length=n_buffers) (in caller-allocated): array of contiguous
+ * #StunInputVectors containing already-received message data
+ * @n_buffers: number of entries in @buffers or if -1 , then buffers is
+ * terminated by a #StunInputVector with the buffer pointer being %NULL.
+ * @total_length: total number of valid bytes stored consecutively in @buffers
+ * @has_padding: %TRUE if attributes should be padded to 4-byte boundaries
+ *
+ * Quickly validate whether the message in the given @buffers is potentially a
+ * valid STUN message, an incomplete STUN message, or if it’s definitely not one
+ * at all.
+ *
+ * This is designed as a first-pass validation only, and does not check the
+ * message’s attributes for validity. If this function returns success, the
+ * buffers can be compacted and a more thorough validation can be performed
+ * using stun_message_validate_buffer_length(). If it fails, the buffers
+ * definitely do not contain a complete, valid STUN message.
+ *
+ * Returns: The length of the valid STUN message in the buffer, or zero or -1 on
+ * failure
+ * <para> See also: #STUN_MESSAGE_BUFFER_INCOMPLETE </para>
+ * <para> See also: #STUN_MESSAGE_BUFFER_INVALID </para>
+ *
+ * Since: 0.1.5
+ */
+ssize_t stun_message_validate_buffer_length_fast (StunInputVector *buffers,
+ int n_buffers, size_t total_length, bool has_padding);
+
+/**
+ * stun_message_id:
+ * @msg: The #StunMessage
+ * @id: The #StunTransactionId to fill
+ *
+ * Retreive the STUN transaction id from a STUN message
+ */
+void stun_message_id (const StunMessage *msg, StunTransactionId id);
+
+/**
+ * stun_message_get_class:
+ * @msg: The #StunMessage
+ *
+ * Retreive the STUN class from a STUN message
+ *
+ * Returns: The #StunClass
+ */
+StunClass stun_message_get_class (const StunMessage *msg);
+
+/**
+ * stun_message_get_method:
+ * @msg: The #StunMessage
+ *
+ * Retreive the STUN method from a STUN message
+ *
+ * Returns: The #StunMethod
+ */
+StunMethod stun_message_get_method (const StunMessage *msg);
+
+/**
+ * stun_message_has_attribute:
+ * @msg: The #StunMessage
+ * @type: The #StunAttribute to look for
+ *
+ * Checks if an attribute is present within a STUN message.
+ *
+ * Returns: %TRUE if the attribute is found, %FALSE otherwise
+ */
+bool stun_message_has_attribute (const StunMessage *msg, StunAttribute type);
+
+
+/* Defined in stun5389.c */
+/**
+ * stun_message_has_cookie:
+ * @msg: The #StunMessage
+ *
+ * Checks if the STUN message has a RFC5389 compatible cookie
+ *
+ * Returns: %TRUE if the cookie is present, %FALSE otherwise
+ */
+bool stun_message_has_cookie (const StunMessage *msg);
+
+
+/**
+ * stun_optional:
+ * @t: An attribute type
+ *
+ * Helper function that checks whether a STUN attribute is a mandatory
+ * or an optional attribute
+ *
+ * Returns: %TRUE if the attribute is an optional one
+ */
+bool stun_optional (uint16_t t);
+
+/**
+ * stun_strerror:
+ * @code: host-byte order error code
+ *
+ * Transforms a STUN error-code into a human readable string
+ *
+ * Returns: A static pointer to a nul-terminated error message string.
+ */
+const char *stun_strerror (StunError code);
+
+
+#endif /* _STUN_MESSAGE_H */
--- /dev/null
+#
+# Makefile.am for the Nice Glib ICE library
+#
+# (C) 2007 Nokia Corporation. All rights reserved.
+#
+# Licensed under MPL 1.1/LGPL 2.1. See file COPYING.
+
+include $(top_srcdir)/common.mk
+AM_CPPFLAGS = -I$(top_srcdir)
+AM_CFLAGS = -std=gnu99
+LDADD = $(top_builddir)/stun/libstun.la
+
+check_PROGRAMS = \
+ test-parse \
+ test-format \
+ test-bind \
+ test-conncheck \
+ test-hmac
+
+if WINDOWS
+ AM_CFLAGS += -DWINVER=0x0501 # _WIN32_WINNT_WINXP
+ LDADD += -lws2_32
+endif
+
+dist_check_SCRIPTS = check-bind.sh
+
+TESTS = $(check_PROGRAMS)
+#$(dist_check_SCRIPTS)
+
+EXTRA_DIST = meson.build
--- /dev/null
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+#
+# Makefile.am for the Nice Glib ICE library
+#
+# (C) 2007 Nokia Corporation. All rights reserved.
+#
+# Licensed under MPL 1.1/LGPL 2.1. See file COPYING.
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+check_PROGRAMS = test-parse$(EXEEXT) test-format$(EXEEXT) \
+ test-bind$(EXEEXT) test-conncheck$(EXEEXT) test-hmac$(EXEEXT)
+@WINDOWS_TRUE@am__append_1 = -DWINVER=0x0501 # _WIN32_WINNT_WINXP
+@WINDOWS_TRUE@am__append_2 = -lws2_32
+subdir = stun/tests
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/as-compiler-flag.m4 \
+ $(top_srcdir)/m4/ax_check_openssl.m4 \
+ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/introspection.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(dist_check_SCRIPTS) \
+ $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+test_bind_SOURCES = test-bind.c
+test_bind_OBJECTS = test-bind.$(OBJEXT)
+test_bind_LDADD = $(LDADD)
+am__DEPENDENCIES_1 =
+test_bind_DEPENDENCIES = $(top_builddir)/stun/libstun.la \
+ $(am__DEPENDENCIES_1)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+test_conncheck_SOURCES = test-conncheck.c
+test_conncheck_OBJECTS = test-conncheck.$(OBJEXT)
+test_conncheck_LDADD = $(LDADD)
+test_conncheck_DEPENDENCIES = $(top_builddir)/stun/libstun.la \
+ $(am__DEPENDENCIES_1)
+test_format_SOURCES = test-format.c
+test_format_OBJECTS = test-format.$(OBJEXT)
+test_format_LDADD = $(LDADD)
+test_format_DEPENDENCIES = $(top_builddir)/stun/libstun.la \
+ $(am__DEPENDENCIES_1)
+test_hmac_SOURCES = test-hmac.c
+test_hmac_OBJECTS = test-hmac.$(OBJEXT)
+test_hmac_LDADD = $(LDADD)
+test_hmac_DEPENDENCIES = $(top_builddir)/stun/libstun.la \
+ $(am__DEPENDENCIES_1)
+test_parse_SOURCES = test-parse.c
+test_parse_OBJECTS = test-parse.$(OBJEXT)
+test_parse_LDADD = $(LDADD)
+test_parse_DEPENDENCIES = $(top_builddir)/stun/libstun.la \
+ $(am__DEPENDENCIES_1)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/test-bind.Po \
+ ./$(DEPDIR)/test-conncheck.Po ./$(DEPDIR)/test-format.Po \
+ ./$(DEPDIR)/test-hmac.Po ./$(DEPDIR)/test-parse.Po
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = test-bind.c test-conncheck.c test-format.c test-hmac.c \
+ test-parse.c
+DIST_SOURCES = test-bind.c test-conncheck.c test-format.c test-hmac.c \
+ test-parse.c
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__tty_colors_dummy = \
+ mgn= red= grn= lgn= blu= brg= std=; \
+ am__color_tests=no
+am__tty_colors = { \
+ $(am__tty_colors_dummy); \
+ if test "X$(AM_COLOR_TESTS)" = Xno; then \
+ am__color_tests=no; \
+ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
+ am__color_tests=yes; \
+ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
+ am__color_tests=yes; \
+ fi; \
+ if test $$am__color_tests = yes; then \
+ red='\e[0;31m'; \
+ grn='\e[0;32m'; \
+ lgn='\e[1;32m'; \
+ blu='\e[1;34m'; \
+ mgn='\e[0;35m'; \
+ brg='\e[1m'; \
+ std='\e[m'; \
+ fi; \
+}
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__recheck_rx = ^[ ]*:recheck:[ ]*
+am__global_test_result_rx = ^[ ]*:global-test-result:[ ]*
+am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]*
+# A command that, given a newline-separated list of test names on the
+# standard input, print the name of the tests that are to be re-run
+# upon "make recheck".
+am__list_recheck_tests = $(AWK) '{ \
+ recheck = 1; \
+ while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+ { \
+ if (rc < 0) \
+ { \
+ if ((getline line2 < ($$0 ".log")) < 0) \
+ recheck = 0; \
+ break; \
+ } \
+ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \
+ { \
+ recheck = 0; \
+ break; \
+ } \
+ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \
+ { \
+ break; \
+ } \
+ }; \
+ if (recheck) \
+ print $$0; \
+ close ($$0 ".trs"); \
+ close ($$0 ".log"); \
+}'
+# A command that, given a newline-separated list of test names on the
+# standard input, create the global log from their .trs and .log files.
+am__create_global_log = $(AWK) ' \
+function fatal(msg) \
+{ \
+ print "fatal: making $@: " msg | "cat >&2"; \
+ exit 1; \
+} \
+function rst_section(header) \
+{ \
+ print header; \
+ len = length(header); \
+ for (i = 1; i <= len; i = i + 1) \
+ printf "="; \
+ printf "\n\n"; \
+} \
+{ \
+ copy_in_global_log = 1; \
+ global_test_result = "RUN"; \
+ while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+ { \
+ if (rc < 0) \
+ fatal("failed to read from " $$0 ".trs"); \
+ if (line ~ /$(am__global_test_result_rx)/) \
+ { \
+ sub("$(am__global_test_result_rx)", "", line); \
+ sub("[ ]*$$", "", line); \
+ global_test_result = line; \
+ } \
+ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \
+ copy_in_global_log = 0; \
+ }; \
+ if (copy_in_global_log) \
+ { \
+ rst_section(global_test_result ": " $$0); \
+ while ((rc = (getline line < ($$0 ".log"))) != 0) \
+ { \
+ if (rc < 0) \
+ fatal("failed to read from " $$0 ".log"); \
+ print line; \
+ }; \
+ printf "\n"; \
+ }; \
+ close ($$0 ".trs"); \
+ close ($$0 ".log"); \
+}'
+# Restructured Text title.
+am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; }
+# Solaris 10 'make', and several other traditional 'make' implementations,
+# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it
+# by disabling -e (using the XSI extension "set +e") if it's set.
+am__sh_e_setup = case $$- in *e*) set +e;; esac
+# Default flags passed to test drivers.
+am__common_driver_flags = \
+ --color-tests "$$am__color_tests" \
+ --enable-hard-errors "$$am__enable_hard_errors" \
+ --expect-failure "$$am__expect_failure"
+# To be inserted before the command running the test. Creates the
+# directory for the log if needed. Stores in $dir the directory
+# containing $f, in $tst the test, in $log the log. Executes the
+# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and
+# passes TESTS_ENVIRONMENT. Set up options for the wrapper that
+# will run the test scripts (or their associated LOG_COMPILER, if
+# thy have one).
+am__check_pre = \
+$(am__sh_e_setup); \
+$(am__vpath_adj_setup) $(am__vpath_adj) \
+$(am__tty_colors); \
+srcdir=$(srcdir); export srcdir; \
+case "$@" in \
+ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \
+ *) am__odir=.;; \
+esac; \
+test "x$$am__odir" = x"." || test -d "$$am__odir" \
+ || $(MKDIR_P) "$$am__odir" || exit $$?; \
+if test -f "./$$f"; then dir=./; \
+elif test -f "$$f"; then dir=; \
+else dir="$(srcdir)/"; fi; \
+tst=$$dir$$f; log='$@'; \
+if test -n '$(DISABLE_HARD_ERRORS)'; then \
+ am__enable_hard_errors=no; \
+else \
+ am__enable_hard_errors=yes; \
+fi; \
+case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \
+ am__expect_failure=yes;; \
+ *) \
+ am__expect_failure=no;; \
+esac; \
+$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT)
+# A shell command to get the names of the tests scripts with any registered
+# extension removed (i.e., equivalently, the names of the test logs, with
+# the '.log' extension removed). The result is saved in the shell variable
+# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly,
+# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)",
+# since that might cause problem with VPATH rewrites for suffix-less tests.
+# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'.
+am__set_TESTS_bases = \
+ bases='$(TEST_LOGS)'; \
+ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \
+ bases=`echo $$bases`
+RECHECK_LOGS = $(TEST_LOGS)
+AM_RECURSIVE_TARGETS = check recheck
+TEST_SUITE_LOG = test-suite.log
+TEST_EXTENSIONS = @EXEEXT@ .test
+LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS)
+am__set_b = \
+ case '$@' in \
+ */*) \
+ case '$*' in \
+ */*) b='$*';; \
+ *) b=`echo '$@' | sed 's/\.log$$//'`; \
+ esac;; \
+ *) \
+ b='$*';; \
+ esac
+am__test_logs1 = $(TESTS:=.log)
+am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log)
+TEST_LOGS = $(am__test_logs2:.test.log=.log)
+TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver
+TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \
+ $(TEST_LOG_FLAGS)
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/common.mk \
+ $(top_srcdir)/depcomp $(top_srcdir)/test-driver
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+pkgincludedir = $(includedir)/nice
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCACHE_DISABLE = @CCACHE_DISABLE@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GST010_CFLAGS = @GST010_CFLAGS@
+GST010_LIBS = @GST010_LIBS@
+GST_CFLAGS = @GST_CFLAGS@
+GST_CHECK_CFLAGS = @GST_CHECK_CFLAGS@
+GST_CHECK_LIBS = @GST_CHECK_LIBS@
+GST_LIBS = @GST_LIBS@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@
+GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@
+GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@
+GTKDOC_MKPDF = @GTKDOC_MKPDF@
+GTKDOC_REBASE = @GTKDOC_REBASE@
+GUPNP_CFLAGS = @GUPNP_CFLAGS@
+GUPNP_LIBS = @GUPNP_LIBS@
+GUPNP_PACKAGES = @GUPNP_PACKAGES@
+GUPNP_PACKAGES_PRIVATE = @GUPNP_PACKAGES_PRIVATE@
+GUPNP_PACKAGES_PUBLIC = @GUPNP_PACKAGES_PUBLIC@
+HAVE_GUPNP = @HAVE_GUPNP@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@
+INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@
+INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@
+INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@
+INTROSPECTION_LIBS = @INTROSPECTION_LIBS@
+INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@
+INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
+INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBNICE_CFLAGS = @LIBNICE_CFLAGS@
+LIBNICE_LT_LDFLAGS = @LIBNICE_LT_LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBRT = @LIBRT@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NICE_PACKAGES_PRIVATE = @NICE_PACKAGES_PRIVATE@
+NICE_PACKAGES_PUBLIC = @NICE_PACKAGES_PUBLIC@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_INCLUDES = @OPENSSL_INCLUDES@
+OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+UPNP_ENABLED = @UPNP_ENABLED@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gstplugin010dir = @gstplugin010dir@
+gstplugindir = @gstplugindir@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+CLEANFILES = *.gcno *.gcda
+LOG_DRIVER = $(top_srcdir)/scripts/valgrind-test-driver
+AM_CPPFLAGS = -I$(top_srcdir)
+AM_CFLAGS = -std=gnu99 $(am__append_1)
+LDADD = $(top_builddir)/stun/libstun.la $(am__append_2)
+dist_check_SCRIPTS = check-bind.sh
+TESTS = $(check_PROGRAMS)
+#$(dist_check_SCRIPTS)
+EXTRA_DIST = meson.build
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/common.mk $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu stun/tests/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu stun/tests/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+$(top_srcdir)/common.mk $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-checkPROGRAMS:
+ @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+
+test-bind$(EXEEXT): $(test_bind_OBJECTS) $(test_bind_DEPENDENCIES) $(EXTRA_test_bind_DEPENDENCIES)
+ @rm -f test-bind$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_bind_OBJECTS) $(test_bind_LDADD) $(LIBS)
+
+test-conncheck$(EXEEXT): $(test_conncheck_OBJECTS) $(test_conncheck_DEPENDENCIES) $(EXTRA_test_conncheck_DEPENDENCIES)
+ @rm -f test-conncheck$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_conncheck_OBJECTS) $(test_conncheck_LDADD) $(LIBS)
+
+test-format$(EXEEXT): $(test_format_OBJECTS) $(test_format_DEPENDENCIES) $(EXTRA_test_format_DEPENDENCIES)
+ @rm -f test-format$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_format_OBJECTS) $(test_format_LDADD) $(LIBS)
+
+test-hmac$(EXEEXT): $(test_hmac_OBJECTS) $(test_hmac_DEPENDENCIES) $(EXTRA_test_hmac_DEPENDENCIES)
+ @rm -f test-hmac$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_hmac_OBJECTS) $(test_hmac_LDADD) $(LIBS)
+
+test-parse$(EXEEXT): $(test_parse_OBJECTS) $(test_parse_DEPENDENCIES) $(EXTRA_test_parse_DEPENDENCIES)
+ @rm -f test-parse$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_parse_OBJECTS) $(test_parse_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-bind.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-conncheck.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-format.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-hmac.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-parse.Po@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+# Recover from deleted '.trs' file; this should ensure that
+# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create
+# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells
+# to avoid problems with "make -n".
+.log.trs:
+ rm -f $< $@
+ $(MAKE) $(AM_MAKEFLAGS) $<
+
+# Leading 'am--fnord' is there to ensure the list of targets does not
+# expand to empty, as could happen e.g. with make check TESTS=''.
+am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck)
+am--force-recheck:
+ @:
+
+$(TEST_SUITE_LOG): $(TEST_LOGS)
+ @$(am__set_TESTS_bases); \
+ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \
+ redo_bases=`for i in $$bases; do \
+ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \
+ done`; \
+ if test -n "$$redo_bases"; then \
+ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \
+ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \
+ if $(am__make_dryrun); then :; else \
+ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \
+ fi; \
+ fi; \
+ if test -n "$$am__remaking_logs"; then \
+ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \
+ "recursion detected" >&2; \
+ elif test -n "$$redo_logs"; then \
+ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \
+ fi; \
+ if $(am__make_dryrun); then :; else \
+ st=0; \
+ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \
+ for i in $$redo_bases; do \
+ test -f $$i.trs && test -r $$i.trs \
+ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \
+ test -f $$i.log && test -r $$i.log \
+ || { echo "$$errmsg $$i.log" >&2; st=1; }; \
+ done; \
+ test $$st -eq 0 || exit 1; \
+ fi
+ @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \
+ ws='[ ]'; \
+ results=`for b in $$bases; do echo $$b.trs; done`; \
+ test -n "$$results" || results=/dev/null; \
+ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \
+ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \
+ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \
+ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \
+ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \
+ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \
+ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \
+ if test `expr $$fail + $$xpass + $$error` -eq 0; then \
+ success=true; \
+ else \
+ success=false; \
+ fi; \
+ br='==================='; br=$$br$$br$$br$$br; \
+ result_count () \
+ { \
+ if test x"$$1" = x"--maybe-color"; then \
+ maybe_colorize=yes; \
+ elif test x"$$1" = x"--no-color"; then \
+ maybe_colorize=no; \
+ else \
+ echo "$@: invalid 'result_count' usage" >&2; exit 4; \
+ fi; \
+ shift; \
+ desc=$$1 count=$$2; \
+ if test $$maybe_colorize = yes && test $$count -gt 0; then \
+ color_start=$$3 color_end=$$std; \
+ else \
+ color_start= color_end=; \
+ fi; \
+ echo "$${color_start}# $$desc $$count$${color_end}"; \
+ }; \
+ create_testsuite_report () \
+ { \
+ result_count $$1 "TOTAL:" $$all "$$brg"; \
+ result_count $$1 "PASS: " $$pass "$$grn"; \
+ result_count $$1 "SKIP: " $$skip "$$blu"; \
+ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \
+ result_count $$1 "FAIL: " $$fail "$$red"; \
+ result_count $$1 "XPASS:" $$xpass "$$red"; \
+ result_count $$1 "ERROR:" $$error "$$mgn"; \
+ }; \
+ { \
+ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \
+ $(am__rst_title); \
+ create_testsuite_report --no-color; \
+ echo; \
+ echo ".. contents:: :depth: 2"; \
+ echo; \
+ for b in $$bases; do echo $$b; done \
+ | $(am__create_global_log); \
+ } >$(TEST_SUITE_LOG).tmp || exit 1; \
+ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \
+ if $$success; then \
+ col="$$grn"; \
+ else \
+ col="$$red"; \
+ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \
+ fi; \
+ echo "$${col}$$br$${std}"; \
+ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \
+ echo "$${col}$$br$${std}"; \
+ create_testsuite_report --maybe-color; \
+ echo "$$col$$br$$std"; \
+ if $$success; then :; else \
+ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \
+ if test -n "$(PACKAGE_BUGREPORT)"; then \
+ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \
+ fi; \
+ echo "$$col$$br$$std"; \
+ fi; \
+ $$success || exit 1
+
+check-TESTS: $(check_PROGRAMS) $(dist_check_SCRIPTS)
+ @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list
+ @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list
+ @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+ @set +e; $(am__set_TESTS_bases); \
+ log_list=`for i in $$bases; do echo $$i.log; done`; \
+ trs_list=`for i in $$bases; do echo $$i.trs; done`; \
+ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \
+ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \
+ exit $$?;
+recheck: all $(check_PROGRAMS) $(dist_check_SCRIPTS)
+ @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+ @set +e; $(am__set_TESTS_bases); \
+ bases=`for i in $$bases; do echo $$i; done \
+ | $(am__list_recheck_tests)` || exit 1; \
+ log_list=`for i in $$bases; do echo $$i.log; done`; \
+ log_list=`echo $$log_list`; \
+ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \
+ am__force_recheck=am--force-recheck \
+ TEST_LOGS="$$log_list"; \
+ exit $$?
+test-parse.log: test-parse$(EXEEXT)
+ @p='test-parse$(EXEEXT)'; \
+ b='test-parse'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-format.log: test-format$(EXEEXT)
+ @p='test-format$(EXEEXT)'; \
+ b='test-format'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-bind.log: test-bind$(EXEEXT)
+ @p='test-bind$(EXEEXT)'; \
+ b='test-bind'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-conncheck.log: test-conncheck$(EXEEXT)
+ @p='test-conncheck$(EXEEXT)'; \
+ b='test-conncheck'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-hmac.log: test-hmac$(EXEEXT)
+ @p='test-hmac$(EXEEXT)'; \
+ b='test-hmac'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+.test.log:
+ @p='$<'; \
+ $(am__set_b); \
+ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+@am__EXEEXT_TRUE@.test$(EXEEXT).log:
+@am__EXEEXT_TRUE@ @p='$<'; \
+@am__EXEEXT_TRUE@ $(am__set_b); \
+@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \
+@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT)
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) \
+ $(dist_check_SCRIPTS)
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-am
+all-am: Makefile
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+ -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS)
+ -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs)
+ -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-checkPROGRAMS clean-generic clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/test-bind.Po
+ -rm -f ./$(DEPDIR)/test-conncheck.Po
+ -rm -f ./$(DEPDIR)/test-format.Po
+ -rm -f ./$(DEPDIR)/test-hmac.Po
+ -rm -f ./$(DEPDIR)/test-parse.Po
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f ./$(DEPDIR)/test-bind.Po
+ -rm -f ./$(DEPDIR)/test-conncheck.Po
+ -rm -f ./$(DEPDIR)/test-format.Po
+ -rm -f ./$(DEPDIR)/test-hmac.Po
+ -rm -f ./$(DEPDIR)/test-parse.Po
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: check-am install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \
+ check-am clean clean-checkPROGRAMS clean-generic clean-libtool \
+ cscopelist-am ctags ctags-am distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ recheck tags tags-am uninstall uninstall-am
+
+.PRECIOUS: Makefile
+
+
+check-valgrind:
+ $(MAKE) TESTS_ENVIRONMENT="USE_VALGRIND=1 " check
+
+.PHONY: check-valgrind
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null
+#! /bin/sh
+
+if test -n "${BUILT_WITH_MESON}"; then
+ STUNC=$1
+ STUND=$2
+else
+ STUNC=../tools/stunbdc
+ STUND=../tools/stund
+fi
+
+cleanup() {
+ rm -f stund?.pid stund?.fail stunc?.log
+}
+
+trap cleanup EXIT
+
+set -xe
+
+# Dummy command line parsing tests
+$STUNC -h
+$STUNC -V
+! $STUNC server port dummy
+
+# Timeout tests
+! $STUNC -4 127.0.0.1 1
+! $STUNC -6 ::1 1
+
+# Allocate a likely unused port number
+PORT=$((32768+$$))
+if test $PORT -le 1024; then
+ PORT=$(($PORT+1024))
+fi
+
+echo "Using local UDP port number $PORT ..."
+
+# Start the STUN test daemon if needed
+cleanup()
+
+for v in 4 6; do
+ (($SHELL -c "echo \$\$ > stund$v.pid ; exec $STUND -$v $PORT") || \
+ touch stund$v.fail) &
+done
+
+# Run the test client
+$STUNC -4 127.0.0.1 $PORT > stunc4.log || test -f stund4.fail
+$STUNC -6 ::1 $PORT > stunc6.log || test -f stund6.fail
+
+# Terminate the test daemon
+for v in 4 6; do kill -INT $(cat stund$v.pid) || true; done
+wait
+
+# Check client results
+if test -f stund4.fail; then exit 77; fi
+grep -e "^Mapped address: 127.0.0.1" stunc4.log || exit 4
+
+if test -f stund6.fail; then exit 77; fi
+grep -e "^Mapped address: ::1" stunc6.log || exit 6
--- /dev/null
+foreach t : ['parse', 'format', 'bind', 'conncheck', 'hmac']
+ test_name = 'test-@0@'.format(t)
+ exe = executable(test_name, test_name + '.c',
+ include_directories: nice_incs,
+ dependencies: [syslibs, crypto_dep],
+ link_with: libstun)
+ test(test_name, exe)
+endforeach
+
+# XXX: This test is broken and unused since 2007, ocrete knows about it
+# If we enable it, we may want to put it in a separate suite that's only run on
+# dist because it takes a long time to run since it tests stun timeouts.
+if false and find_program('sh', required : false).found()
+ test('test-check-bind', find_program('check-bind.sh'),
+ timeout: 600,
+ env: 'BUILT_WITH_MESON=1',
+ args: [stunbdc_exe, stund_exe])
+endif
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2007 Nokia Corporation. All rights reserved.
+ * Contact: Rémi Denis-Courmont
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Rémi Denis-Courmont, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+#include "stun/stunagent.h"
+#include "stun/usages/bind.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef _WIN32
+#include <winsock2.h>
+#include <ws2tcpip.h>
+
+#define MSG_DONTWAIT 0
+
+#define alarm(...)
+#define close closesocket
+#else
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <netdb.h>
+#endif
+
+#undef NDEBUG /* ensure assertions are built-in */
+#include <assert.h>
+
+#ifndef MSG_NOSIGNAL
+#define MSG_NOSIGNAL 0
+#endif
+
+static int listen_dgram (void)
+{
+ struct addrinfo hints, *res;
+ const struct addrinfo *ptr;
+ int val = -1;
+
+ memset (&hints, 0, sizeof (hints));
+ hints.ai_socktype = SOCK_DGRAM;
+
+ if (getaddrinfo (NULL, "0", &hints, &res))
+ return -1;
+
+ for (ptr = res; ptr != NULL; ptr = ptr->ai_next)
+ {
+ int fd = socket (ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
+ if (fd == -1)
+ continue;
+
+ if (bind (fd, ptr->ai_addr, ptr->ai_addrlen))
+ {
+ close (fd);
+ continue;
+ }
+
+ val = fd;
+ break;
+ }
+
+ freeaddrinfo (res);
+ return val;
+}
+
+
+/** Incorrect socket family test */
+static void bad_family (void)
+{
+ struct sockaddr addr;
+ struct sockaddr_storage dummy;
+ int val;
+ socklen_t dummylen = sizeof(dummy);
+
+ memset (&addr, 0, sizeof (addr));
+ addr.sa_family = AF_UNSPEC;
+#ifdef HAVE_SA_LEN
+ addr.sa_len = sizeof (addr);
+#endif
+
+ val = stun_usage_bind_run (&addr, sizeof (addr),
+ &dummy, &dummylen);
+ assert (val != 0);
+}
+
+
+/** Too small socket address test */
+static void small_srv_addr (void)
+{
+ struct sockaddr addr;
+ struct sockaddr_storage dummy;
+ int val;
+ socklen_t dummylen = sizeof(dummy);
+
+ memset (&addr, 0, sizeof (addr));
+ addr.sa_family = AF_INET;
+#ifdef HAVE_SA_LEN
+ addr.sa_len = sizeof (addr);
+#endif
+
+ val = stun_usage_bind_run (&addr, 1,
+ &dummy, &dummylen);
+ assert (val == STUN_USAGE_BIND_RETURN_ERROR);
+}
+
+
+/** Too big socket address test */
+static void big_srv_addr (void)
+{
+ uint8_t buf[sizeof (struct sockaddr_storage) + 16];
+ struct sockaddr_storage dummy;
+ int val;
+ socklen_t dummylen = sizeof(dummy);
+
+
+ memset (buf, 0, sizeof (buf));
+ val = stun_usage_bind_run ((struct sockaddr *)buf, sizeof (buf),
+ &dummy, &dummylen);
+ assert (val == STUN_USAGE_BIND_RETURN_ERROR);
+}
+
+
+/** Timeout test */
+static void timeout (void)
+{
+ struct sockaddr_storage srv, dummy;
+ socklen_t srvlen = sizeof (srv);
+ socklen_t dummylen = sizeof(dummy);
+ int val;
+
+ /* Allocate a local UDP port, so we are 100% sure nobody responds there */
+ int servfd = listen_dgram ();
+ assert (servfd != -1);
+
+ val = getsockname (servfd, (struct sockaddr *)&srv, &srvlen);
+ assert (val == 0);
+
+ val = stun_usage_bind_run ((struct sockaddr *)&srv, srvlen,
+ &dummy, &dummylen);
+ assert (val == STUN_USAGE_BIND_RETURN_TIMEOUT);
+
+ close (servfd);
+}
+
+/** Malformed responses test */
+static void bad_responses (void)
+{
+ struct sockaddr_storage addr;
+ socklen_t addrlen = sizeof (addr);
+ ssize_t val, len;
+ uint8_t buf[STUN_MAX_MESSAGE_SIZE];
+ uint8_t req[STUN_MAX_MESSAGE_SIZE];
+ size_t req_len;
+ StunAgent agent;
+ StunMessage msg;
+ StunMessage req_msg;
+ int servfd, fd;
+
+ uint16_t known_attributes[] = {
+ STUN_ATTRIBUTE_MAPPED_ADDRESS,
+ STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
+ STUN_ATTRIBUTE_PRIORITY,
+ STUN_ATTRIBUTE_USERNAME,
+ STUN_ATTRIBUTE_MESSAGE_INTEGRITY,
+ STUN_ATTRIBUTE_ERROR_CODE, 0};
+
+ stun_agent_init (&agent, known_attributes,
+ STUN_COMPATIBILITY_RFC5389, 0);
+
+ /* Allocate a local UDP port */
+ servfd = listen_dgram ();
+ assert (servfd != -1);
+
+ val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
+ assert (val == 0);
+
+ fd = socket (addr.ss_family, SOCK_DGRAM, 0);
+ assert (fd != -1);
+
+ req_len = stun_usage_bind_create (&agent, &req_msg, req, sizeof(req));
+ assert (req_len > 0);
+
+ val = sendto (fd, req, req_len, MSG_DONTWAIT | MSG_NOSIGNAL,
+ (struct sockaddr *)&addr, addrlen);
+ assert (val >= 0);
+
+ /* Send to/receive from our client instance only */
+ val = getsockname (fd, (struct sockaddr *)&addr, &addrlen);
+ assert (val == 0);
+
+ /* Send request instead of response */
+ val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
+ assert (val == 0);
+ len = recvfrom (servfd, buf, 1000, MSG_DONTWAIT, NULL, 0);
+ assert (len >= 20);
+
+ assert (stun_agent_validate (&agent, &msg, buf, len, NULL, NULL)
+ == STUN_VALIDATION_SUCCESS);
+
+ val = stun_usage_bind_process (&msg, (struct sockaddr *) &addr, &addrlen,
+ (struct sockaddr *) &addr, &addrlen);
+ assert (val == STUN_USAGE_BIND_RETURN_INVALID);
+
+ /* Send response with wrong request type */
+ buf[0] |= 0x03;
+ buf[0] ^= 0x02;
+
+ /* Send error response without ERROR-CODE */
+ buf[1] |= 0x10;
+ val = stun_usage_bind_process (&msg, (struct sockaddr *) &addr, &addrlen,
+ (struct sockaddr *) &addr, &addrlen);
+ assert (val == STUN_USAGE_BIND_RETURN_INVALID);
+
+ close (fd);
+ close (servfd);
+}
+
+/** Various responses test */
+static void responses (void)
+{
+ struct sockaddr_storage addr;
+ socklen_t addrlen = sizeof (addr);
+ ssize_t val;
+ size_t len;
+ int servfd, fd;
+ uint8_t buf[STUN_MAX_MESSAGE_SIZE];
+ uint8_t req[STUN_MAX_MESSAGE_SIZE];
+ size_t req_len;
+ StunAgent agent;
+ StunMessage msg;
+ StunMessage req_msg;
+
+ uint16_t known_attributes[] = {
+ STUN_ATTRIBUTE_MAPPED_ADDRESS,
+ STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
+ STUN_ATTRIBUTE_PRIORITY,
+ STUN_ATTRIBUTE_USERNAME,
+ STUN_ATTRIBUTE_MESSAGE_INTEGRITY,
+ STUN_ATTRIBUTE_ERROR_CODE, 0};
+
+ stun_agent_init (&agent, known_attributes,
+ STUN_COMPATIBILITY_RFC5389, 0);
+
+ /* Allocate a local UDP port for server */
+ servfd = listen_dgram ();
+ assert (servfd != -1);
+
+ val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
+ assert (val == 0);
+
+ /* Allocate a client socket and connect to server */
+ fd = socket (addr.ss_family, SOCK_DGRAM, 0);
+ assert (fd != -1);
+
+ /* Send error response */
+ req_len = stun_usage_bind_create (&agent, &req_msg, req, sizeof(req));
+ assert (req_len > 0);
+
+ val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
+ assert (val == 0);
+
+ val = sendto (fd, req, req_len, MSG_DONTWAIT | MSG_NOSIGNAL,
+ (struct sockaddr *)&addr, addrlen);
+ assert (val >= 0);
+
+ val = recvfrom (servfd, buf, 1000, MSG_DONTWAIT, NULL, 0);
+ assert (val >= 0);
+
+ assert (stun_agent_validate (&agent, &msg, buf, val, NULL, NULL)
+ == STUN_VALIDATION_SUCCESS);
+
+ stun_agent_init_error (&agent, &msg, buf, sizeof (buf),
+ &msg, STUN_ERROR_SERVER_ERROR);
+ len = stun_agent_finish_message (&agent, &msg, NULL, 0);
+ assert (len > 0);
+
+ val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
+ assert (val == 0);
+
+ val = stun_usage_bind_process (&msg, (struct sockaddr *) &addr, &addrlen,
+ (struct sockaddr *) &addr, &addrlen);
+ assert (val == STUN_USAGE_BIND_RETURN_ERROR);
+
+ /* Send response with a no mapped address at all */
+ req_len = stun_usage_bind_create (&agent, &req_msg, req, sizeof(req));
+ assert (req_len > 0);
+
+ val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
+ assert (val == 0);
+
+ val = sendto (fd, req, req_len, MSG_DONTWAIT | MSG_NOSIGNAL,
+ (struct sockaddr *)&addr, addrlen);
+ assert (val >= 0);
+
+ val = recvfrom (servfd, buf, 1000, MSG_DONTWAIT, NULL, 0);
+ assert (val >= 0);
+
+ assert (stun_agent_validate (&agent, &msg, buf, val, NULL, NULL)
+ == STUN_VALIDATION_SUCCESS);
+
+ stun_agent_init_response (&agent, &msg, buf, sizeof (buf), &msg);
+ len = stun_agent_finish_message (&agent, &msg, NULL, 0);
+ assert (len > 0);
+
+ assert (stun_agent_validate (&agent, &msg, buf, len, NULL, NULL)
+ == STUN_VALIDATION_SUCCESS);
+
+ val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
+ assert (val == 0);
+
+ val = stun_usage_bind_process (&msg, (struct sockaddr *) &addr, &addrlen,
+ (struct sockaddr *) &addr, &addrlen);
+ assert (val == STUN_USAGE_BIND_RETURN_ERROR);
+
+ /* Send old-style response */
+ req_len = stun_usage_bind_create (&agent, &req_msg, req, sizeof(req));
+ assert (req_len > 0);
+
+ val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
+ assert (val == 0);
+
+ val = sendto (fd, req, req_len, MSG_DONTWAIT | MSG_NOSIGNAL,
+ (struct sockaddr *)&addr, addrlen);
+ assert (val >= 0);
+
+ val = recvfrom (servfd, buf, 1000, MSG_DONTWAIT, NULL, 0);
+ assert (val >= 0);
+
+ assert (stun_agent_validate (&agent, &msg, buf, val, NULL, NULL)
+ == STUN_VALIDATION_SUCCESS);
+
+ stun_agent_init_response (&agent, &msg, buf, sizeof (buf), &msg);
+ assert (stun_message_append_addr (&msg, STUN_ATTRIBUTE_MAPPED_ADDRESS,
+ (struct sockaddr *) &addr, addrlen) == STUN_MESSAGE_RETURN_SUCCESS);
+ len = stun_agent_finish_message (&agent, &msg, NULL, 0);
+ assert (len > 0);
+
+ assert (stun_agent_validate (&agent, &msg, buf, len, NULL, NULL)
+ == STUN_VALIDATION_SUCCESS);
+
+ val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
+ assert (val == 0);
+
+ val = stun_usage_bind_process (&msg, (struct sockaddr *) &addr, &addrlen,
+ (struct sockaddr *) &addr, &addrlen);
+ assert (val == STUN_USAGE_BIND_RETURN_SUCCESS);
+
+ /* End */
+ close (servfd);
+
+ val = close (fd);
+ assert (val == 0);
+}
+
+static void keepalive (void)
+{
+ struct sockaddr_storage addr = {0};
+ socklen_t addrlen = sizeof (addr);
+ int val, servfd, fd;
+
+ uint8_t buf[STUN_MAX_MESSAGE_SIZE];
+ size_t len;
+ StunAgent agent;
+ StunMessage msg;
+
+ uint16_t known_attributes[] = {
+ STUN_ATTRIBUTE_MAPPED_ADDRESS,
+ STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
+ STUN_ATTRIBUTE_PRIORITY,
+ STUN_ATTRIBUTE_USERNAME,
+ STUN_ATTRIBUTE_MESSAGE_INTEGRITY,
+ STUN_ATTRIBUTE_ERROR_CODE, 0};
+
+ stun_agent_init (&agent, known_attributes,
+ STUN_COMPATIBILITY_RFC5389, 0);
+
+ /* Allocate a local UDP port for server */
+ servfd = listen_dgram ();
+ assert (servfd != -1);
+
+ val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
+ assert (val == 0);
+
+ /* Allocate a client socket and connect to server */
+ fd = socket (addr.ss_family, SOCK_DGRAM, 0);
+ assert (fd != -1);
+
+ /* Keep alive sending smoke test */
+ len = stun_usage_bind_keepalive (&agent, &msg, buf, sizeof(buf));
+ assert (len == 20);
+
+ val = sendto (fd, buf, len, MSG_DONTWAIT | MSG_NOSIGNAL,
+ (struct sockaddr *)&addr, addrlen);
+ assert (val >= 0);
+
+ /* End */
+ close (servfd);
+
+ val = close (fd);
+ assert (val == 0);
+}
+
+
+static void test (void (*func) (void), const char *name)
+{
+ alarm (30);
+
+ printf ("%s test... ", name);
+ func ();
+ puts ("OK");
+}
+
+
+int main (void)
+{
+#ifdef _WIN32
+ WSADATA w;
+ WSAStartup(0x0202, &w);
+#endif
+ test (bad_family, "Bad socket family");
+ test (small_srv_addr, "Too small server address");
+ test (big_srv_addr, "Too big server address");
+ test (bad_responses, "Bad responses");
+ test (responses, "Error responses");
+ test (keepalive, "Keep alives");
+#ifdef HAVE_POLL
+ test (timeout, "Binding discovery timeout");
+#endif
+#ifdef _WIN32
+ WSACleanup();
+#endif
+ return 0;
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2007 Nokia Corporation. All rights reserved.
+ * Contact: Rémi Denis-Courmont
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Rémi Denis-Courmont, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+#include "stun/stunagent.h"
+#include "stun/usages/ice.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef _WIN32
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#define MSG_DONTWAIT 0
+#define MSG_NOSIGNAL 0
+
+#define alarm(...)
+#else
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#endif
+
+#undef NDEBUG /* ensure assertions are built-in */
+#include <assert.h>
+
+
+int main (void)
+{
+ union {
+ struct sockaddr sa;
+ struct sockaddr_storage storage;
+ struct sockaddr_in ip4;
+ } addr;
+ uint8_t req_buf[STUN_MAX_MESSAGE_SIZE];
+ uint8_t resp_buf[STUN_MAX_MESSAGE_SIZE];
+ const uint64_t tie = 0x8000000000000000LL;
+ StunMessageReturn val;
+ StunUsageIceReturn val2;
+ size_t len;
+ size_t rlen;
+ static char username[] = "L:R";
+ static uint8_t ufrag[] = "L", pass[] = "secret";
+ size_t ufrag_len = strlen ((char*) ufrag);
+ size_t pass_len = strlen ((char*) pass);
+ int code;
+ bool control = false;
+ StunAgent agent;
+ StunMessage req;
+ StunMessage resp;
+ StunDefaultValidaterData validater_data[] = {
+ {ufrag, ufrag_len, pass, pass_len},
+ {(uint8_t *) username, strlen (username), pass, pass_len},
+ {NULL, 0, NULL, 0}};
+ StunValidationStatus valid;
+
+ stun_agent_init (&agent, STUN_ALL_KNOWN_ATTRIBUTES,
+ STUN_COMPATIBILITY_RFC5389,
+ STUN_AGENT_USAGE_USE_FINGERPRINT |
+ STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS);
+
+ memset (&addr, 0, sizeof (addr));
+ addr.ip4.sin_family = AF_INET;
+#ifdef HAVE_SA_LEN
+ addr.ip4.sin_len = sizeof (addr);
+#endif
+ addr.ip4.sin_port = htons (12345);
+ addr.ip4.sin_addr.s_addr = htonl (0x7f000001);
+
+ /* Incorrect message class */
+ assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
+ assert (stun_agent_init_response (&agent, &req, req_buf, sizeof (req_buf), &req));
+
+ rlen = stun_agent_finish_message (&agent, &req, NULL, 0);
+ assert (rlen > 0);
+
+ len = sizeof (resp_buf);
+ val2 = stun_usage_ice_conncheck_create_reply (&agent, &req,
+ &resp, resp_buf, &len, &addr.storage,
+ sizeof (addr.ip4), &control, tie, STUN_USAGE_ICE_COMPATIBILITY_RFC5245);
+ assert (val2 == STUN_USAGE_ICE_RETURN_INVALID_REQUEST);
+ assert (len == 0);
+
+ /* Incorrect message method */
+ assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), 0x666));
+ val = stun_message_append_string (&req, STUN_ATTRIBUTE_USERNAME, username);
+ assert (val == STUN_MESSAGE_RETURN_SUCCESS);
+ rlen = stun_agent_finish_message (&agent, &req, pass, pass_len);
+ assert (rlen > 0);
+
+ len = sizeof (resp_buf);
+ val2 = stun_usage_ice_conncheck_create_reply (&agent, &req,
+ &resp, resp_buf, &len, &addr.storage,
+ sizeof (addr.ip4), &control, tie, STUN_USAGE_ICE_COMPATIBILITY_RFC5245);
+ assert (val2 == STUN_USAGE_ICE_RETURN_INVALID_METHOD);
+ assert (len > 0);
+
+ /* Unknown attribute */
+ assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
+ val = stun_message_append_string (&req, 0x666, "The evil unknown attribute!");
+ assert (val == STUN_MESSAGE_RETURN_SUCCESS);
+ val = stun_message_append_string (&req, STUN_ATTRIBUTE_USERNAME, username);
+ assert (val == STUN_MESSAGE_RETURN_SUCCESS);
+ rlen = stun_agent_finish_message (&agent, &req, pass, pass_len);
+ assert (rlen > 0);
+
+ valid = stun_agent_validate (&agent, &req, req_buf, rlen,
+ stun_agent_default_validater, validater_data);
+
+ assert (valid == STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE);
+
+ /* Unauthenticated message */
+ assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
+ rlen = stun_agent_finish_message (&agent, &req, NULL, 0);
+ assert (rlen > 0);
+
+ valid = stun_agent_validate (&agent, &req, req_buf, rlen,
+ stun_agent_default_validater, validater_data);
+
+ assert (valid == STUN_VALIDATION_UNAUTHORIZED_BAD_REQUEST);
+
+ /* No username */
+ assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
+ rlen = stun_agent_finish_message (&agent, &req, pass, pass_len);
+ assert (rlen > 0);
+
+ valid = stun_agent_validate (&agent, &req, req_buf, rlen,
+ stun_agent_default_validater, validater_data);
+
+ assert (valid == STUN_VALIDATION_UNAUTHORIZED_BAD_REQUEST);
+ assert (stun_usage_ice_conncheck_priority (&req) == 0);
+ assert (stun_usage_ice_conncheck_use_candidate (&req) == false);
+
+ /* Good message */
+ assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
+ val = stun_message_append32 (&req, STUN_ATTRIBUTE_PRIORITY, 0x12345678);
+ assert (val == STUN_MESSAGE_RETURN_SUCCESS);
+ val = stun_message_append_flag (&req, STUN_ATTRIBUTE_USE_CANDIDATE);
+ assert (val == STUN_MESSAGE_RETURN_SUCCESS);
+ val = stun_message_append_string (&req, STUN_ATTRIBUTE_USERNAME,
+ (char*) ufrag);
+ assert (val == STUN_MESSAGE_RETURN_SUCCESS);
+ rlen = stun_agent_finish_message (&agent, &req, pass, pass_len);
+ assert (rlen > 0);
+
+ len = sizeof (resp_buf);
+ val2 = stun_usage_ice_conncheck_create_reply (&agent, &req,
+ &resp, resp_buf, &len, &addr.storage,
+ sizeof (addr.ip4), &control, tie, STUN_USAGE_ICE_COMPATIBILITY_RFC5245);
+ assert (val2 == STUN_USAGE_ICE_RETURN_SUCCESS);
+ assert (len > 0);
+ assert (stun_agent_validate (&agent, &resp, resp_buf, len,
+ stun_agent_default_validater, validater_data) == STUN_VALIDATION_SUCCESS);
+ assert (stun_message_get_class (&resp) == STUN_RESPONSE);
+ assert (stun_usage_ice_conncheck_priority (&req) == 0x12345678);
+ assert (stun_usage_ice_conncheck_use_candidate (&req) == true);
+
+ /* Invalid socket address */
+ assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
+ val = stun_message_append_string (&req, STUN_ATTRIBUTE_USERNAME,
+ (char *) ufrag);
+ assert (val == STUN_MESSAGE_RETURN_SUCCESS);
+ rlen = stun_agent_finish_message (&agent, &req, pass, pass_len);
+ assert (rlen > 0);
+
+ addr.ip4.sin_family = AF_UNSPEC;
+ len = sizeof (resp_buf);
+ val2 = stun_usage_ice_conncheck_create_reply (&agent, &req,
+ &resp, resp_buf, &len, &addr.storage,
+ sizeof (addr.ip4), &control, tie, STUN_USAGE_ICE_COMPATIBILITY_RFC5245);
+ assert (val2 == STUN_USAGE_ICE_RETURN_INVALID_ADDRESS);
+ assert (len == 0);
+
+ addr.ip4.sin_family = AF_INET;
+
+ /* Role conflict, controlling + ICE-CONTROLLING, switching controlled */
+ assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
+ val = stun_message_append64 (&req, STUN_ATTRIBUTE_ICE_CONTROLLING, tie + 1);
+ assert (val == STUN_MESSAGE_RETURN_SUCCESS);
+ val = stun_message_append_string (&req, STUN_ATTRIBUTE_USERNAME,
+ (char *) ufrag);
+ assert (val == STUN_MESSAGE_RETURN_SUCCESS);
+ rlen = stun_agent_finish_message (&agent, &req, pass, pass_len);
+ assert (rlen > 0);
+
+ len = sizeof (resp_buf);
+ control = true;
+ val2 = stun_usage_ice_conncheck_create_reply (&agent, &req,
+ &resp, resp_buf, &len, &addr.storage,
+ sizeof (addr.ip4), &control, tie, STUN_USAGE_ICE_COMPATIBILITY_RFC5245);
+ assert (val2 == STUN_USAGE_ICE_RETURN_ROLE_CONFLICT);
+ assert (len > 0);
+ assert (control == false);
+ assert (stun_agent_validate (&agent, &resp, resp_buf, len,
+ stun_agent_default_validater, validater_data) == STUN_VALIDATION_SUCCESS);
+ assert (stun_message_get_class (&resp) == STUN_RESPONSE);
+
+ /* Role conflict, controlled + ICE-CONTROLLED, switching controlling */
+ assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
+ val = stun_message_append64 (&req, STUN_ATTRIBUTE_ICE_CONTROLLED, tie - 1);
+ assert (val == STUN_MESSAGE_RETURN_SUCCESS);
+ val = stun_message_append_string (&req, STUN_ATTRIBUTE_USERNAME,
+ (char *) ufrag);
+ assert (val == STUN_MESSAGE_RETURN_SUCCESS);
+ rlen = stun_agent_finish_message (&agent, &req, pass, pass_len);
+ assert (rlen > 0);
+
+ len = sizeof (resp_buf);
+ control = false;
+ val2 = stun_usage_ice_conncheck_create_reply (&agent, &req,
+ &resp, resp_buf, &len, &addr.storage,
+ sizeof (addr.ip4), &control, tie, STUN_USAGE_ICE_COMPATIBILITY_RFC5245);
+ assert (val2 == STUN_USAGE_ICE_RETURN_ROLE_CONFLICT);
+ assert (len > 0);
+ assert (control == true);
+ assert (stun_agent_validate (&agent, &resp, resp_buf, len,
+ stun_agent_default_validater, validater_data) == STUN_VALIDATION_SUCCESS);
+ assert (stun_message_get_class (&resp) == STUN_RESPONSE);
+
+ /* Role conflict, controlling + ICE-CONTROLLING, staying controlling */
+ assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
+ val = stun_message_append64 (&req, STUN_ATTRIBUTE_ICE_CONTROLLING, tie - 1);
+ assert (val == STUN_MESSAGE_RETURN_SUCCESS);
+ val = stun_message_append_string (&req, STUN_ATTRIBUTE_USERNAME,
+ (char *) ufrag);
+ assert (val == STUN_MESSAGE_RETURN_SUCCESS);
+ rlen = stun_agent_finish_message (&agent, &req, pass, pass_len);
+ assert (rlen > 0);
+
+ len = sizeof (resp_buf);
+ control = true;
+ val2 = stun_usage_ice_conncheck_create_reply (&agent, &req,
+ &resp, resp_buf, &len, &addr.storage,
+ sizeof (addr.ip4), &control, tie, STUN_USAGE_ICE_COMPATIBILITY_RFC5245);
+ assert (val2 == STUN_USAGE_ICE_RETURN_ROLE_CONFLICT);
+ assert (len > 0);
+ assert (control == true);
+ assert (stun_agent_validate (&agent, &resp, resp_buf, len,
+ stun_agent_default_validater, validater_data) == STUN_VALIDATION_SUCCESS);
+ assert (stun_message_get_class (&resp) == STUN_ERROR);
+ stun_message_find_error (&resp, &code);
+ assert (code == STUN_ERROR_ROLE_CONFLICT);
+
+ /* Role conflict, controlled + ICE-CONTROLLED, staying controlling */
+ assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
+ val = stun_message_append64 (&req, STUN_ATTRIBUTE_ICE_CONTROLLED, tie + 1);
+ assert (val == STUN_MESSAGE_RETURN_SUCCESS);
+ val = stun_message_append_string (&req, STUN_ATTRIBUTE_USERNAME,
+ (char *) ufrag);
+ assert (val == STUN_MESSAGE_RETURN_SUCCESS);
+ rlen = stun_agent_finish_message (&agent, &req, pass, pass_len);
+ assert (rlen > 0);
+
+ len = sizeof (resp_buf);
+ control = false;
+ val2 = stun_usage_ice_conncheck_create_reply (&agent, &req,
+ &resp, resp_buf, &len, &addr.storage,
+ sizeof (addr.ip4), &control, tie, STUN_USAGE_ICE_COMPATIBILITY_RFC5245);
+ assert (val2 == STUN_USAGE_ICE_RETURN_ROLE_CONFLICT);
+ assert (len > 0);
+ assert (control == false);
+ assert (stun_agent_validate (&agent, &resp, resp_buf, len,
+ stun_agent_default_validater, validater_data) == STUN_VALIDATION_SUCCESS);
+ assert (stun_message_get_class (&resp) == STUN_ERROR);
+ stun_message_find_error (&resp, &code);
+ assert (code == STUN_ERROR_ROLE_CONFLICT);
+
+ return 0;
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2007 Nokia Corporation. All rights reserved.
+ * Contact: Rémi Denis-Courmont
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Rémi Denis-Courmont, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+
+#include "stun/stunagent.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <assert.h>
+
+#ifdef _WIN32
+#include <winsock2.h>
+#else
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#endif
+
+
+static void fatal (const char *msg, ...)
+{
+ va_list ap;
+ va_start (ap, msg);
+ vfprintf (stderr, msg, ap);
+ va_end (ap);
+ fputc ('\n', stderr);
+ exit (1);
+}
+
+static const uint8_t usr[] = "admin";
+static const uint8_t pwd[] = "s3kr3t";
+
+static bool dynamic_check_validater (StunAgent *agent,
+ StunMessage *message, uint8_t *username, uint16_t username_len,
+ uint8_t **password, size_t *password_len, void *user_data)
+{
+
+ if (username_len != strlen ((char *) usr) ||
+ memcmp (username, usr, strlen ((char *) usr)) != 0)
+ fatal ("vector test : Validater received wrong username!");
+
+ *password = (uint8_t *) pwd;
+ *password_len = strlen ((char *) pwd);
+
+
+ return true;
+}
+static void
+dynamic_check (StunAgent *agent, StunMessage *msg, size_t len)
+{
+ StunMessage msg2;
+
+ if (stun_agent_validate (agent, &msg2, msg->buffer, len, dynamic_check_validater, NULL) != STUN_VALIDATION_SUCCESS)
+ fatal ("Could not validate message");
+
+ printf ("Built message of %u bytes\n", (unsigned)len);
+}
+
+
+static size_t
+finish_check (StunAgent *agent, StunMessage *msg)
+{
+ uint8_t buf[STUN_MAX_MESSAGE_SIZE + 8];
+ size_t len;
+ uint16_t plen;
+ StunMessage msg2 = {0};
+ msg2.agent = msg->agent;
+ msg2.buffer = buf;
+ msg2.buffer_len = sizeof(buf);
+ memcpy (msg2.buffer, msg->buffer, sizeof(buf) > msg->buffer_len ? msg->buffer_len : sizeof(buf));
+
+ len = stun_agent_finish_message (agent, msg, NULL, 0);
+
+ if (len <= 0)
+ fatal ("Cannot finish message");
+ dynamic_check (agent, msg, len);
+
+ if (stun_message_find (&msg2, STUN_ATTRIBUTE_MESSAGE_INTEGRITY, &plen) != NULL)
+ fatal ("Missing HMAC test failed");
+
+ stun_message_append_string (&msg2, STUN_ATTRIBUTE_USERNAME, (char *) usr);
+
+ len = stun_agent_finish_message (agent, &msg2, pwd, strlen ((char *) pwd));
+
+ if (len <= 0)
+ fatal ("Cannot finish message with short-term creds");
+ dynamic_check (agent, &msg2, len);
+
+ return len;
+}
+
+static void
+check_af (const char *name, int family, socklen_t addrlen)
+{
+ struct sockaddr_storage addr;
+ uint8_t buf[100];
+ StunAgent agent;
+ StunMessage msg;
+ uint16_t known_attributes[] = {STUN_ATTRIBUTE_USERNAME, STUN_ATTRIBUTE_MESSAGE_INTEGRITY, STUN_ATTRIBUTE_ERROR_CODE, 0};
+
+ stun_agent_init (&agent, known_attributes,
+ STUN_COMPATIBILITY_RFC5389, STUN_AGENT_USAGE_USE_FINGERPRINT);
+
+ assert (addrlen <= sizeof (addr));
+
+ memset (&addr, 0, sizeof (addr));
+ stun_agent_init_request (&agent, &msg, buf, sizeof(buf), STUN_BINDING);
+
+ if (stun_message_append_addr (&msg, STUN_ATTRIBUTE_MAPPED_ADDRESS,
+ (struct sockaddr *) &addr, addrlen) !=
+ STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS)
+ fatal ("Unknown address family test failed");
+ if (stun_message_append_xor_addr (&msg, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
+ &addr, addrlen) !=
+ STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS)
+ fatal ("Unknown address family xor test failed");
+
+ addr.ss_family = family;
+ if (stun_message_append_addr (&msg, STUN_ATTRIBUTE_MAPPED_ADDRESS,
+ (struct sockaddr *) &addr, addrlen - 1) !=
+ STUN_MESSAGE_RETURN_INVALID)
+ fatal ("Too small %s sockaddr test failed", name);
+
+ if (stun_message_append_xor_addr (&msg, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
+ &addr, addrlen - 1) != STUN_MESSAGE_RETURN_INVALID)
+ fatal ("Too small %s sockaddr xor test failed", name);
+
+ if (stun_message_append_addr (&msg, STUN_ATTRIBUTE_MAPPED_ADDRESS,
+ (struct sockaddr *) &addr, addrlen) != STUN_MESSAGE_RETURN_SUCCESS)
+ fatal ("%s sockaddr test failed", name);
+
+ if (stun_message_append_xor_addr (&msg, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
+ &addr, addrlen) != STUN_MESSAGE_RETURN_SUCCESS)
+ fatal ("%s sockaddr xor test failed", name);
+}
+
+int main (void)
+{
+ uint8_t buf[100];
+ size_t len;
+ union {
+ struct sockaddr_storage storage;
+ struct sockaddr addr;
+ } addr;
+
+ StunAgent agent;
+ StunMessage msg;
+ uint16_t known_attributes[] = {STUN_ATTRIBUTE_USERNAME,
+ STUN_ATTRIBUTE_MESSAGE_INTEGRITY,
+ STUN_ATTRIBUTE_ERROR_CODE,
+ 0};
+
+ stun_agent_init (&agent, known_attributes,
+ STUN_COMPATIBILITY_RFC5389, STUN_AGENT_USAGE_USE_FINGERPRINT);
+
+ /* Request formatting test */
+ stun_agent_init_request (&agent, &msg, buf, sizeof(buf), STUN_BINDING);
+ finish_check (&agent, &msg);
+ if (memcmp (buf, "\x00\x01", 2))
+ fatal ("Request formatting test failed");
+
+ /* Response formatting test */
+ stun_agent_init_response (&agent, &msg, buf, sizeof (buf), &msg);
+ finish_check (&agent, &msg);
+ if (memcmp (buf, "\x01\x01", 2))
+ fatal ("Response formatting test failed");
+
+ /* Error formatting test */
+ stun_agent_init_request (&agent, &msg, buf, sizeof(buf), STUN_BINDING);
+ finish_check (&agent, &msg);
+ if (!stun_agent_init_error (&agent, &msg, buf, sizeof (buf), &msg, 400))
+ fatal ("Error initialization test failed");
+ finish_check (&agent, &msg);
+ if (memcmp (buf, "\x01\x11", 2))
+ fatal ("Error formatting test failed");
+ /* Unknown error formatting test */
+ stun_agent_init_request (&agent, &msg, buf, sizeof(buf), STUN_BINDING);
+ finish_check (&agent, &msg);
+ if (!stun_agent_init_error (&agent, &msg, buf, sizeof (buf), &msg, 666))
+ fatal ("Unknown error initialization test failed");
+ finish_check (&agent, &msg);
+ if (memcmp (buf, "\x01\x11", 2))
+ fatal ("Unknown error formatting test failed");
+
+ /* Overflow tests */
+ stun_agent_init_request (&agent, &msg, buf, sizeof(buf), STUN_BINDING);
+
+ for (len = 0;
+ stun_message_append_flag (&msg, 0xffff) !=
+ STUN_MESSAGE_RETURN_NOT_ENOUGH_SPACE;
+ len += 4)
+ {
+ if (len > 0xffff)
+ fatal ("Overflow protection test failed");
+ }
+
+ if (stun_message_append32 (&msg, 0xffff, 0x12345678) !=
+ STUN_MESSAGE_RETURN_NOT_ENOUGH_SPACE)
+ fatal ("Double-word overflow test failed");
+ if (stun_message_append64 (&msg, 0xffff,
+ 0x123456789abcdef0) != STUN_MESSAGE_RETURN_NOT_ENOUGH_SPACE)
+ fatal ("Quad-word overflow test failed");
+ if (stun_message_append_string (&msg, 0xffff, "foobar") !=
+ STUN_MESSAGE_RETURN_NOT_ENOUGH_SPACE)
+ fatal ("String overflow test failed");
+
+ memset (&addr, 0, sizeof (addr));
+ addr.addr.sa_family = AF_INET;
+#ifdef HAVE_SS_LEN
+ addr.addr.ss_len = sizeof (addr);
+#endif
+ if (stun_message_append_xor_addr (&msg, 0xffff, &addr.storage,
+ sizeof (addr)) != STUN_MESSAGE_RETURN_NOT_ENOUGH_SPACE)
+ fatal ("Address overflow test failed");
+
+ if (stun_agent_finish_message (&agent, &msg, NULL, 0) != 0)
+ fatal ("Fingerprint overflow test failed");
+ if (stun_agent_finish_message (&agent, &msg, pwd, strlen ((char *) pwd)) != 0)
+ fatal ("Message integrity overflow test failed");
+
+ /* Address attributes tests */
+ check_af ("IPv4", AF_INET, sizeof (struct sockaddr_in));
+#ifdef AF_INET6
+ check_af ("IPv6", AF_INET6, sizeof (struct sockaddr_in6));
+#endif
+
+ return 0;
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2007 Nokia Corporation. All rights reserved.
+ * Contact: Rémi Denis-Courmont
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Rémi Denis-Courmont, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include <stun/stunhmac.h>
+
+static void print_bytes (const uint8_t *bytes, int len)
+{
+ int i;
+
+ printf ("0x");
+ for (i = 0; i < len; i++)
+ printf ("%02x", bytes[i]);
+ printf ("\n");
+}
+
+static void test_hmac (const uint8_t *key, const uint8_t *str,
+ const uint8_t *expected) {
+ uint8_t hmac[20];
+
+ /* Arbitrary. */
+ size_t msg_len = 300;
+
+ stun_sha1 (str, strlen ((const char *) str), msg_len, hmac,
+ key, strlen ((const char *) key), TRUE /* padding */);
+
+ printf ("HMAC of '%s' with key '%s' is : ", str, key);
+ print_bytes (hmac, sizeof (hmac));
+ printf ("Expected : ");
+ print_bytes (expected, sizeof (hmac));
+
+ if (memcmp (hmac, expected, sizeof (hmac)))
+ exit (1);
+}
+
+int main (void)
+{
+ const uint8_t hmac1[] = { 0x83, 0x5a, 0x9b, 0x05, 0xea,
+ 0xd7, 0x68, 0x45, 0x48, 0x74,
+ 0x6b, 0xa3, 0x37, 0xe0, 0xa9,
+ 0x3f, 0x4d, 0xb3, 0x9c, 0xa1 };
+
+ test_hmac ((const uint8_t *) "key",
+ (const uint8_t *) "some complicated input string which is over 44 bytes long",
+ hmac1);
+
+ return 0;
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2007 Nokia Corporation. All rights reserved.
+ * Contact: Rémi Denis-Courmont
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Rémi Denis-Courmont, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "stun/stunagent.h"
+#include "stun/stunhmac.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#ifdef _WIN32
+#include <winsock2.h>
+#include <io.h>
+#else
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#endif
+
+
+# define STUN_MAX_STR (763u)
+# define STUN_MAX_CP (127u)
+
+static void fatal (const char *msg, ...)
+{
+ va_list ap;
+ va_start (ap, msg);
+ vfprintf (stderr, msg, ap);
+ va_end (ap);
+ fputc ('\n', stderr);
+ exit (1);
+}
+
+
+static void validate (const uint8_t *msg, unsigned len)
+{
+ unsigned i = 1;
+
+ do
+ {
+ size_t vlen = stun_message_validate_buffer_length (msg, i, TRUE);
+ if ((vlen & 3) || (vlen != ((i >= len) * len)))
+ fatal ("%u/%u short message test failed", i, len);
+ }
+ while (i++ < (len + 4));
+}
+
+
+/* Tests for generic message validation routines */
+static void test_message (void)
+{
+ static const uint8_t extra_garbage[] =
+ {0x15, 0x55, 0x00, 0x00,
+ 0x21, 0x12, 0xA4, 0x42, // cookie
+ 0x76, 0x54, 0x32, 0x10,
+ 0xfe, 0xdc, 0xba, 0x98,
+ 0x76, 0x54, 0x32, 0x10,
+ 0xaa, 0xbb, 0xcc, 0xdd}; //extra garbage
+ static const uint8_t simple_resp[] =
+ {0x15, 0x55, 0x00, 0x00,
+ 0x21, 0x12, 0xA4, 0x42, // cookie
+ 0x76, 0x54, 0x32, 0x10,
+ 0xfe, 0xdc, 0xba, 0x98,
+ 0x76, 0x54, 0x32, 0x10};
+ static const uint8_t old_ind[] =
+ {0x14, 0x55, 0x00, 0x00,
+ 0xfe, 0xdc, 0xba, 0x98, // NO cookie
+ 0x76, 0x54, 0x32, 0x10,
+ 0xfe, 0xdc, 0xba, 0x98,
+ 0x76, 0x54, 0x32, 0x10};
+ static const uint8_t fpr_resp[] =
+ {0x15, 0x55, 0x00, 0x10,
+ 0x21, 0x12, 0xA4, 0x42, // cookie
+ 0x76, 0x54, 0x32, 0x10,
+ 0xfe, 0xdc, 0xba, 0x98,
+ 0x76, 0x54, 0x32, 0x10,
+ 0x00, 0x06, 0x00, 0x04, // dummy USERNAME header
+ 0x41, 0x42, 0x43, 0x44,
+ 0x80, 0x28, 0x00, 0x04, // FINGERPRINT header
+ 0xdc, 0x8d, 0xa7, 0x74}; // CRC32;
+ static const uint8_t bad1[32] =
+ {0x15, 0x55, 0x00, 0x08,
+ 0x21, 0x12, 0xA4, 0x42, // cookie
+ 0x76, 0x54, 0x32, 0x10,
+ 0xfe, 0xdc, 0xba, 0x98,
+ 0x76, 0x54, 0x32, 0x10,
+ 0x00, 0x06, 0x00, 0x05, // too big attribute for message
+ 0x11, 0x22, 0x33, 0x44,
+ 0x55, 0x66, 0x77, 0x88};
+ static const uint8_t bad2[24] =
+ {0x15, 0x55, 0x00, 0x05, // invalid message length
+ 0x21, 0x12, 0xA4, 0x42,
+ 0x76, 0x54, 0x32, 0x10,
+ 0xfe, 0xdc, 0xba, 0x98,
+ 0x76, 0x54, 0x32, 0x10,
+ 0x00, 0x06, 0x00, 0x01};
+ static const uint8_t bad3[27] =
+ {0x15, 0x55, 0x00, 0x08,
+ 0x21, 0x12, 0xA4, 0x42,
+ 0x76, 0x54, 0x32, 0x10,
+ 0xfe, 0xdc, 0xba, 0x98,
+ 0x76, 0x54, 0x32, 0x10,
+ 0x00, 0x06, 0x00, 0x03,
+ 0x11, 0x22, 0x33}; // missing padding
+ static const uint8_t bad_crc[] =
+ {0x15, 0x55, 0x00, 0x08,
+ 0x21, 0x12, 0xA4, 0x42,
+ 0x76, 0x54, 0x32, 0x10,
+ 0xfe, 0xdc, 0xba, 0x98,
+ 0x76, 0x54, 0x32, 0x10,
+ 0x80, 0x28, 0x00, 0x04, // FINGERPRINT header
+ 0x04, 0x91, 0xcd, 0x78}; // CRC32
+ static uint8_t bad_crc_offset[] =
+ {0x15, 0x55, 0x00, 0x10,
+ 0x21, 0x12, 0xA4, 0x42,
+ 0x76, 0x54, 0x32, 0x10,
+ 0xfe, 0xdc, 0xba, 0x98,
+ 0x20, 0x67, 0xc4, 0x09,
+ 0x80, 0x28, 0x00, 0x04, // FINGERPRINT header
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x06, 0x00, 0x04,
+ 0x41, 0x42, 0x43, 0x44};
+
+ static unsigned char req[] =
+ {0x00, 0x01, 0x00, 0x00,
+ 0x8b, 0x45, 0x9b, 0xc3,
+ 0xe7, 0x7a, 0x05, 0xb3,
+ 0xe4, 0xfe, 0x01, 0xf0,
+ 0xaf, 0x83, 0xe1, 0x9e};
+
+ static uint8_t binding_error_resp[] =
+ {0x01, 0x11, 0x00, 0x84,
+ 0x8b, 0x45, 0x9b, 0xc3,
+ 0xe7, 0x7a, 0x05, 0xb3,
+ 0xe4, 0xfe, 0x01, 0xf0,
+ 0xaf, 0x83, 0xe1, 0x9e,
+
+ 0x00, 0x06, 0x00, 0x48, // USERNAME
+ 0x92, 0x6b, 0x2b, 0x3e,
+ 0x6a, 0xa5, 0x43, 0x58,
+ 0xa8, 0x51, 0x25, 0xa6,
+ 0xf7, 0x9c, 0x0a, 0xe7,
+ 0xd8, 0x86, 0xf7, 0x76,
+ 0xf9, 0xcd, 0x8a, 0x2e,
+ 0x45, 0xd7, 0xcb, 0xbb,
+ 0xae, 0xe5, 0x03, 0xc3,
+ 0x3a, 0x32, 0x3a, 0xa9,
+ 0x9e, 0xb7, 0x7b, 0x32,
+ 0xe3, 0xf3, 0xa6, 0xc0,
+ 0xe8, 0x54, 0x4b, 0xef,
+ 0x52, 0xd2, 0xe2, 0xc0,
+ 0x43, 0xc2, 0x4c, 0xbc,
+ 0xaf, 0xd9, 0xf2, 0xfa,
+ 0x48, 0x8b, 0x8c, 0xe6,
+ 0x62, 0x14, 0x64, 0x3a,
+ 0x32, 0x00, 0x00, 0x00,
+
+ 0x00, 0x09, 0x00, 0x1c, // ERROR-CODE
+ 0x00, 0x00, 0x04, 0x1f,
+ 0x49, 0x6e, 0x74, 0x65,
+ 0x67, 0x72, 0x69, 0x74,
+ 0x79, 0x20, 0x43, 0x68,
+ 0x65, 0x63, 0x6b, 0x20,
+ 0x46, 0x61, 0x69, 0x6c,
+ 0x75, 0x72, 0x65, 0x2e,
+
+ 0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY
+ 0xf7, 0x46, 0x81, 0xc4,
+ 0x6f, 0x4c, 0x21, 0x5c,
+ 0xf6, 0x8e, 0xc0, 0x81,
+ 0x0e, 0x20, 0x3f, 0xb1,
+ 0xb1, 0xad, 0xa4, 0x8a};
+
+ StunAgent agent;
+ StunAgent agent2;
+ StunMessage msg;
+ uint16_t known_attributes[] = {STUN_ATTRIBUTE_USERNAME,
+ STUN_ATTRIBUTE_ERROR_CODE,
+ STUN_ATTRIBUTE_MESSAGE_INTEGRITY};
+
+ uint8_t username_v[] = {0x92, 0x6b, 0x2b, 0x3e, 0x6a, 0xa5, 0x43, 0x58,
+ 0xa8, 0x51, 0x25, 0xa6, 0xf7, 0x9c, 0x0a, 0xe7,
+ 0xd8, 0x86, 0xf7, 0x76, 0xf9, 0xcd, 0x8a, 0x2e,
+ 0x45, 0xd7, 0xcb, 0xbb, 0xae, 0xe5, 0x03, 0xc3,
+ 0x3a, 0x32, 0x3a, 0xa9, 0x9e, 0xb7, 0x7b, 0x32,
+ 0xe3, 0xf3, 0xa6, 0xc0, 0xe8, 0x54, 0x4b, 0xef,
+ 0x52, 0xd2, 0xe2, 0xc0, 0x43, 0xc2, 0x4c, 0xbc,
+ 0xaf, 0xd9, 0xf2, 0xfa, 0x48, 0x8b, 0x8c, 0xe6,
+ 0x62, 0x14, 0x64, 0x3a, 0x32, 0x00, 0x00, 0x00};
+ uint8_t password_v[] = {0x77, 0xd9, 0x7a, 0xe9, 0xcf, 0xe0, 0x3e, 0xa2,
+ 0x28, 0xa0, 0x5d, 0xec, 0xcf, 0x36, 0xe8, 0x49};
+
+ StunDefaultValidaterData v = {username_v, 72, password_v, 16};
+
+ stun_agent_init (&agent, known_attributes,
+ STUN_COMPATIBILITY_RFC5389, STUN_AGENT_USAGE_USE_FINGERPRINT);
+ stun_agent_init (&agent2, known_attributes,
+ STUN_COMPATIBILITY_RFC3489, STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS);
+
+
+ stun_agent_validate (&agent2, &msg, req, sizeof(req), NULL, NULL);
+ stun_agent_finish_message (&agent2, &msg, NULL, 0);
+
+ if (stun_agent_validate (&agent2, &msg, binding_error_resp,
+ sizeof(binding_error_resp),
+ stun_agent_default_validater, &v) != STUN_VALIDATION_SUCCESS)
+ fatal ("Binding Error Response failed");
+
+
+ if (stun_message_validate_buffer_length (NULL, 0, TRUE) !=
+ STUN_MESSAGE_BUFFER_INVALID)
+ fatal ("0 bytes test failed");
+ if (stun_message_validate_buffer_length ((uint8_t *)"\xf0", 1, TRUE) >= 0)
+ fatal ("1 byte test failed");
+ if (stun_message_validate_buffer_length (bad1, sizeof (bad1), TRUE) >= 0)
+ fatal ("Badness 1 test failed");
+ if (stun_message_validate_buffer_length (bad2, sizeof (bad2), TRUE) >= 0)
+ fatal ("Badness 2 test failed");
+ if (stun_message_validate_buffer_length (bad3, sizeof (bad3), TRUE) != 0)
+ fatal ("Badness 3 test failed");
+ validate (simple_resp, 20);
+ validate (old_ind, 20);
+ validate (fpr_resp, 36);
+
+ if (stun_agent_validate (&agent, &msg, extra_garbage, sizeof(extra_garbage),
+ NULL, NULL) != STUN_VALIDATION_NOT_STUN)
+ fatal ("Extra garbage test failed");
+ if (stun_agent_validate (&agent, &msg, simple_resp, sizeof(simple_resp),
+ NULL, NULL) != STUN_VALIDATION_BAD_REQUEST)
+ fatal ("Missing CRC test failed");
+ if (stun_agent_validate (&agent, &msg, old_ind, sizeof(old_ind),
+ NULL, NULL) != STUN_VALIDATION_BAD_REQUEST)
+ fatal ("Missing cookie test failed");
+ if (stun_agent_validate (&agent, &msg, bad_crc, sizeof(bad_crc),
+ NULL, NULL) != STUN_VALIDATION_BAD_REQUEST)
+ fatal ("Bad CRC test failed");
+ if (stun_agent_validate (&agent, &msg, bad_crc_offset, sizeof(bad_crc_offset),
+ NULL, NULL) != STUN_VALIDATION_BAD_REQUEST)
+ fatal ("Bad CRC offset test failed");
+ if (stun_agent_validate (&agent, &msg, fpr_resp, sizeof(fpr_resp),
+ NULL, NULL) != STUN_VALIDATION_UNMATCHED_RESPONSE)
+ fatal ("Good CRC test failed");
+
+ if (stun_message_get_class (&msg) != 3)
+ fatal ("Class test failed");
+ if (stun_message_get_method (&msg) != 0x525)
+ fatal ("Method test failed");
+}
+
+
+static bool test_attribute_validater (StunAgent *agent,
+ StunMessage *message, uint8_t *username, uint16_t username_len,
+ uint8_t **password, size_t *password_len, void *user_data)
+{
+ uint8_t *pwd = user_data;
+
+ if (username_len != 4 ||
+ memcmp (username, "ABCD", 4) != 0)
+ return false;
+
+ *password = pwd;
+ *password_len = strlen ((char *) pwd);
+
+ return true;
+}
+
+/* Tests for message attribute parsing */
+static void test_attribute (void)
+{
+ static const uint8_t acme[] =
+ {0x04, 0x55, 0x00, 0x6C, // <-- update message length if needed!!
+ 0x21, 0x12, 0xA4, 0x42, // cookie
+ 0x76, 0x54, 0x32, 0x10,
+ 0xfe, 0xdc, 0xba, 0x98,
+ 0x76, 0x54, 0x32, 0x10,
+
+ /* FF01: empty */
+ 0xff, 0x01, 0x00, 0x00,
+
+ /* FF02: address of unknown family, 32-bits */
+ 0xff, 0x02, 0x00, 0x04,
+ 0x41, 0x42, 0x43, 0x44,
+
+ /* FF03: too short IPv6 address */
+ 0xff, 0x03, 0x00, 0x06,
+ 0x00, 0x02, 0x12, 0x34,
+ 0x20, 0x01, 0x0d, 0xb8,
+
+ /* FF04: valid IPv4 address, 64-bits */
+ 0xff, 0x04, 0x00, 0x08,
+ 0x00, 0x01, 0x12, 0x34,
+ 0xc0, 0x00, 0x02, 0x01,
+
+ /* FF05: too long IPv4 address */
+ 0xff, 0x05, 0x00, 0x0A,
+ 0x00, 0x01, 0x12, 0x34,
+ 0xc0, 0x00, 0x02, 0x01,
+ 0x66, 0x60, 0x00, 0x00,
+
+ /* FF06: valid xor'd IPv6 address, 160-bits */
+ 0xff, 0x06, 0x00, 0x14,
+ 0x00, 0x02, 0x12, 0x34,
+ 0x01, 0x13, 0xa9, 0xfa,
+ 0xa8, 0xf9, 0x8c, 0xff,
+ 0x20, 0x26, 0x74, 0x48,
+ 0x8c, 0x9a, 0xec, 0xfd,
+
+ /* dummy USERNAME header */
+ 0x00, 0x06, 0x00, 0x04,
+ 0x41, 0x42, 0x43, 0x44,
+
+ /* MESSAGE-INTEGRITY attribute */
+ 0x00, 0x08, 0x00, 0x14,
+ 0x0b, 0xc4, 0xb2, 0x0c,
+ 0x94, 0x58, 0xbb, 0x25,
+ 0xa3, 0x22, 0x1a, 0xc8,
+ 0xe1, 0x87, 0x32, 0x36,
+ 0x3a, 0xfc, 0xe2, 0xc3};
+
+ union
+ {
+ struct sockaddr_storage st;
+ struct sockaddr_in6 s6;
+ } addr;
+ socklen_t addrlen;
+ uint32_t dword;
+ uint64_t qword;
+ char str[STUN_MAX_STR];
+
+ StunAgent agent;
+ StunMessage msg;
+ uint16_t known_attributes[] = {STUN_ATTRIBUTE_MESSAGE_INTEGRITY, STUN_ATTRIBUTE_USERNAME, 0};
+
+ printf ("Attribute test message length: %zd\n", sizeof (acme));
+
+ stun_agent_init (&agent, known_attributes,
+ STUN_COMPATIBILITY_RFC5389, STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS);
+
+ if (stun_agent_validate (&agent, &msg, acme, sizeof(acme),
+ NULL, NULL) != STUN_VALIDATION_UNAUTHORIZED)
+ fatal ("Unauthorized validation failed");
+
+ if (stun_agent_validate (&agent, &msg, acme, sizeof(acme),
+ test_attribute_validater, (void *) "bad__guy") != STUN_VALIDATION_UNAUTHORIZED)
+ fatal ("invalid password validation failed");
+
+ if (stun_agent_validate (&agent, &msg, acme, sizeof(acme),
+ test_attribute_validater, (void *) "good_guy") != STUN_VALIDATION_SUCCESS)
+ fatal ("good password validation failed");
+
+ if (stun_message_has_attribute (&msg, 0xff00))
+ fatal ("Absent attribute test failed");
+ if (!stun_message_has_attribute (&msg, 0xff01))
+ fatal ("Present attribute test failed");
+
+ if (stun_message_find_flag (&msg, 0xff00) != STUN_MESSAGE_RETURN_NOT_FOUND)
+ fatal ("Absent flag test failed");
+ if (stun_message_find_flag (&msg, 0xff01) != STUN_MESSAGE_RETURN_SUCCESS)
+ fatal ("Flag test failed");
+ if (stun_message_find_flag (&msg, 0xff02) != STUN_MESSAGE_RETURN_INVALID)
+ fatal ("Too big flag test failed");
+
+ if (stun_message_find32 (&msg, 0xff00, &dword) !=
+ STUN_MESSAGE_RETURN_NOT_FOUND)
+ fatal ("Absent dword test failed");
+ if (stun_message_find32 (&msg, 0xff01, &dword) != STUN_MESSAGE_RETURN_INVALID)
+ fatal ("Bad dword test failed");
+ if (stun_message_find32 (&msg, 0xff02, &dword) != STUN_MESSAGE_RETURN_SUCCESS)
+ fatal ("Double-word test failed");
+
+ if (stun_message_find64 (&msg, 0xff00, &qword) !=
+ STUN_MESSAGE_RETURN_NOT_FOUND)
+ fatal ("Absent qword test failed");
+ if (stun_message_find64 (&msg, 0xff01, &qword) != STUN_MESSAGE_RETURN_INVALID)
+ fatal ("Bad qword test failed");
+ if (stun_message_find64 (&msg, 0xff04, &qword) != STUN_MESSAGE_RETURN_SUCCESS)
+ fatal ("Quad-word test failed");
+
+ if (stun_message_find_string (&msg, 0xff00, str, STUN_MAX_CP) !=
+ STUN_MESSAGE_RETURN_NOT_FOUND)
+ fatal ("Absent string test failed");
+ if ((stun_message_find_string (&msg, 0xff02, str, STUN_MAX_CP) !=
+ STUN_MESSAGE_RETURN_SUCCESS)
+ || strcmp (str, "ABCD"))
+ fatal ("String test failed");
+
+ addrlen = sizeof (addr);
+ if (stun_message_find_addr (&msg, 0xff01, &addr.st, &addrlen) !=
+ STUN_MESSAGE_RETURN_INVALID)
+ fatal ("Too short addres test failed");
+ addrlen = sizeof (addr);
+ if (stun_message_find_addr (&msg, 0xff02, &addr.st, &addrlen) !=
+ STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS)
+ fatal ("Unknown address family test failed");
+ addrlen = sizeof (addr);
+ if (stun_message_find_addr (&msg, 0xff03, &addr.st, &addrlen) !=
+ STUN_MESSAGE_RETURN_INVALID)
+ fatal ("Too short IPv6 address test failed");
+ addrlen = sizeof (addr);
+ if (stun_message_find_addr (&msg, 0xff04, &addr.st, &addrlen) !=
+ STUN_MESSAGE_RETURN_SUCCESS)
+ fatal ("IPv4 address test failed");
+ addrlen = sizeof (addr);
+ if (stun_message_find_addr (&msg, 0xff05, &addr.st, &addrlen) !=
+ STUN_MESSAGE_RETURN_INVALID)
+ fatal ("Too big IPv4 address test failed");
+ addrlen = sizeof (addr);
+ if (stun_message_find_xor_addr (&msg, 0xff06, &addr.st, &addrlen) !=
+ STUN_MESSAGE_RETURN_SUCCESS ||
+ memcmp (&addr.s6.sin6_addr, "\x20\x01\x0d\xb8""\xde\xad\xbe\xef"
+ "\xde\xfa\xce\xd0""\xfa\xce\xde\xed", 16))
+ fatal ("IPv6 address test failed");
+
+}
+
+static const char vector_username[] = "evtj:h6vY";
+static uint8_t vector_password[] = "VOkJxbRl1RmTxUk/WvJxBt";
+
+static bool test_vector_validater (StunAgent *agent,
+ StunMessage *message, uint8_t *username, uint16_t username_len,
+ uint8_t **password, size_t *password_len, void *user_data)
+{
+ intptr_t callable = (intptr_t) user_data;
+
+ if (!callable)
+ fatal ("vector test : Validater should not be called!");
+
+ if (username_len != strlen (vector_username) ||
+ memcmp (username, vector_username, strlen (vector_username)) != 0)
+ fatal ("vector test : Validater received wrong username!");
+
+ *password = vector_password;
+ *password_len = strlen ((char *) vector_password);
+
+
+ return true;
+}
+
+static void test_vectors (void)
+{
+ /* Request message */
+ static unsigned char req[] =
+ {0x00, 0x01, 0x00, 0x44,
+ 0x21, 0x12, 0xa4, 0x42,
+ 0xb7, 0xe7, 0xa7, 0x01,
+ 0xbc, 0x34, 0xd6, 0x86,
+ 0xfa, 0x87, 0xdf, 0xae,
+
+ 0x00, 0x24, 0x00, 0x04, // PRIORITY
+ 0x6e, 0x00, 0x01, 0xff,
+
+ 0x80, 0x29, 0x00, 0x08, // ICE_CONTROLLED
+ 0x93, 0x2f, 0xf9, 0xb1,
+ 0x51, 0x26, 0x3b, 0x36,
+
+ 0x00, 0x06, 0x00, 0x09, // USERNAME
+ 0x65, 0x76, 0x74, 0x6a,
+ 0x3a, 0x68, 0x36, 0x76,
+ 0x59, 0x20, 0x20, 0x20,
+
+ 0x00, 0x08, 0x00, 0x14, // MESSAGE_INTEGRITY
+ 0x62, 0x4e, 0xeb, 0xdc,
+ 0x3c, 0xc9, 0x2d, 0xd8,
+ 0x4b, 0x74, 0xbf, 0x85,
+ 0xd1, 0xc0, 0xf5, 0xde,
+ 0x36, 0x87, 0xbd, 0x33,
+
+ 0x80, 0x28, 0x00, 0x04, // FINGERPRINT
+ 0xad, 0x8a, 0x85, 0xff};
+
+ static const unsigned char req2[] =
+ {0x00, 0x01, 0x00, 0x44,
+ 0x21, 0x12, 0xa4, 0x42,
+ 0xb7, 0xe7, 0xa7, 0x01,
+ 0xbc, 0x34, 0xd6, 0x86,
+ 0xfa, 0x87, 0xdf, 0xae,
+
+ 0x00, 0x24, 0x00, 0x04, // PRIORITY
+ 0x6e, 0x00, 0x01, 0xff,
+
+ 0x80, 0x29, 0x00, 0x08, // ICE_CONTROLLED
+ 0x93, 0x2f, 0xf9, 0xb1,
+ 0x51, 0x26, 0x3b, 0x36,
+
+ 0x00, 0x06, 0x00, 0x09, // USERNAME
+ 0x65, 0x76, 0x74, 0x6a,
+ 0x3a, 0x68, 0x36, 0x76,
+ 0x59, 0x20, 0x20, 0x20,
+
+ 0x00, 0x08, 0x00, 0x14, // MESSAGE_INTEGRITY
+ 0x62, 0x4e, 0xeb, 0xdc,
+ 0x3c, 0xc9, 0x2d, 0xd8,
+ 0x4b, 0x74, 0xbf, 0x85,
+ 0xd1, 0xc0, 0xf5, 0xde,
+ 0x36, 0x87, 0xbd, 0x33,
+
+ 0x80, 0x28, 0x00, 0x04, // FINGERPRINT
+ 0xad, 0x8a, 0x85, 0xff};
+
+ /* Response message */
+ static const unsigned char respv4[] =
+ {0x01, 0x01, 0x00, 0x4c,
+ 0x21, 0x12, 0xa4, 0x42,
+ 0xb7, 0xe7, 0xa7, 0x01,
+ 0xbc, 0x34, 0xd6, 0x86,
+ 0xfa, 0x87, 0xdf, 0xae,
+
+ 0x80, 0x22, 0x00, 0x0b, // SERVER
+ 0x74, 0x65, 0x73, 0x74,
+ 0x20, 0x76, 0x65, 0x63,
+ 0x74, 0x6f, 0x72, 0x20,
+
+ 0x00, 0x20, 0x00, 0x08, // XOR_MAPPED_ADDRESS
+ 0x00, 0x01, 0xa1, 0x47,
+ 0xe1, 0x12, 0xa6, 0x43,
+
+ 0x00, 0x06, 0x00, 0x09, // USERNAME
+ 0x65, 0x76, 0x74, 0x6a,
+ 0x3a, 0x68, 0x36, 0x76,
+ 0x59, 0x20, 0x20, 0x20,
+
+ 0x00, 0x08, 0x00, 0x14, // MESSAGE_INTEGRITY
+ 0x7d, 0xb7, 0xfc, 0x52,
+ 0x70, 0xc6, 0xdb, 0x1f,
+ 0xc3, 0x26, 0x34, 0xbb,
+ 0x4c, 0x64, 0x6e, 0xe7,
+ 0x1d, 0xb3, 0x78, 0x4a,
+
+ 0x80, 0x28, 0x00, 0x04, // FINGERPRINT
+ 0xf0, 0x60, 0x66, 0xa9};
+ static const unsigned char respv6[] =
+ {0x01, 0x01, 0x00, 0x58,
+ 0x21, 0x12, 0xa4, 0x42,
+ 0xb7, 0xe7, 0xa7, 0x01,
+ 0xbc, 0x34, 0xd6, 0x86,
+ 0xfa, 0x87, 0xdf, 0xae,
+
+ 0x80, 0x22, 0x00, 0x0b, // SERVER
+ 0x74, 0x65, 0x73, 0x74,
+ 0x20, 0x76, 0x65, 0x63,
+ 0x74, 0x6f, 0x72, 0x20,
+
+ 0x00, 0x20, 0x00, 0x14, // XOR_MAPPED_ADDRESS
+ 0x00, 0x02, 0xa1, 0x47,
+ 0x01, 0x13, 0xa9, 0xfa,
+ 0xa5, 0xd3, 0xf1, 0x79,
+ 0xbc, 0x25, 0xf4, 0xb5,
+ 0xbe, 0xd2, 0xb9, 0xd9,
+
+ 0x00, 0x06, 0x00, 0x09, // USERNAME
+ 0x65, 0x76, 0x74, 0x6a,
+ 0x3a, 0x68, 0x36, 0x76,
+ 0x59, 0x20, 0x20, 0x20,
+
+ 0x00, 0x08, 0x00, 0x14, // MESSAGE_INTEGRITY
+ 0x21, 0xcb, 0xbd, 0x25,
+ 0x1a, 0x8c, 0x4c, 0x38,
+ 0x8c, 0xc5, 0xcd, 0xb3,
+ 0x27, 0x6a, 0xf5, 0x61,
+ 0xb2, 0x21, 0xc8, 0x2b,
+
+ 0x80, 0x28, 0x00, 0x04, // FINGERPRINT
+ 0xec, 0x27, 0xae, 0xb7};
+ union {
+ struct sockaddr_storage st;
+ struct sockaddr_in ip4;
+ struct sockaddr_in6 ip6;
+ } addr;
+ socklen_t addrlen;
+
+ StunAgent agent;
+ StunMessage msg;
+ StunMessage msg2;
+ uint16_t known_attributes[] = {
+ STUN_ATTRIBUTE_MESSAGE_INTEGRITY,
+ STUN_ATTRIBUTE_USERNAME,
+ STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
+ STUN_ATTRIBUTE_PRIORITY, 0};
+
+ stun_agent_init (&agent, known_attributes,
+ STUN_COMPATIBILITY_RFC5389,
+ STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS |
+ STUN_AGENT_USAGE_USE_FINGERPRINT);
+
+ memset (&addr, 0, sizeof (addr));
+
+ puts ("Checking test vectors...");
+
+ if (stun_agent_validate (&agent, &msg2, req2, sizeof(req2),
+ test_vector_validater, (void *) 1) != STUN_VALIDATION_SUCCESS)
+ fatal ("Request test vector authentication failed");
+
+ if (stun_agent_validate (&agent, &msg, req, sizeof(req),
+ test_vector_validater, (void *) 1) != STUN_VALIDATION_SUCCESS)
+ fatal ("Request test vector authentication failed");
+
+ /* Remove the message-integrity and fingerprint attributes */
+ req[3] = 0x24;
+
+ if (stun_message_length (&msg) != sizeof(req) - 32)
+ fatal ("vector test: removing attributes failed");
+
+ stun_agent_finish_message (&agent, &msg, vector_password,
+ strlen ((char *) vector_password));
+
+ if (stun_message_length (&msg) != stun_message_length (&msg2) ||
+ memcmp (req, req2, sizeof(req)) != 0)
+ fatal ("vector test : req and req2 are different");
+
+ if (stun_agent_validate (&agent, &msg, respv4, sizeof(respv4),
+ test_vector_validater, (void *) 0) != STUN_VALIDATION_SUCCESS)
+ fatal ("Response ipv4 test vector authentication failed");
+
+ if (stun_agent_validate (&agent, &msg, respv4, sizeof(respv4),
+ test_vector_validater, (void *) 0) != STUN_VALIDATION_UNMATCHED_RESPONSE)
+ fatal ("Response ipv4 test vector authentication failed");
+
+ addrlen = sizeof (addr.ip4);
+ if (stun_message_find_xor_addr (&msg, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
+ &addr.st, &addrlen) != STUN_MESSAGE_RETURN_SUCCESS)
+ fatal ("Response test vector IPv4 extraction failed");
+ if (addr.ip4.sin_family != AF_INET)
+ fatal ("Response test vector IPv4 family failed");
+ if (ntohl (addr.ip4.sin_addr.s_addr) != 0xC0000201)
+ fatal ("Response test vector IPv4 address failed");
+ if (ntohs (addr.ip4.sin_port) != 32853)
+ fatal ("Response test vector IPv6 port failed");
+
+ if (stun_agent_validate (&agent, &msg, req, sizeof(req),
+ test_vector_validater, (void *) 1) != STUN_VALIDATION_SUCCESS)
+ fatal ("Request test vector second authentication failed");
+
+ /* Remove the fingerprint attributes */
+ msg.key = NULL;
+ msg.key_len = 0;
+ req[3] = 0x3C;
+
+ if (stun_message_length (&msg) != sizeof(req) - 8)
+ fatal ("vector test: removing attributes failed");
+
+ stun_agent_finish_message (&agent, &msg, NULL, 0);
+
+ if (stun_message_length (&msg) != stun_message_length (&msg2) ||
+ memcmp (req, req2, sizeof(req)) != 0)
+ fatal ("vector test : req and req2 are different");
+
+ if (stun_agent_validate (&agent, &msg, respv6, sizeof(respv6),
+ test_vector_validater, (void *) 1) != STUN_VALIDATION_SUCCESS)
+ fatal ("Response ipv6 test vector authentication failed");
+
+ addrlen = sizeof (addr.ip6);
+ if (stun_message_find_xor_addr (&msg, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
+ &addr.st, &addrlen) != STUN_MESSAGE_RETURN_SUCCESS)
+ fatal ("Response test vector IPv6 extraction failed");
+ if (addr.ip6.sin6_family != AF_INET6)
+ fatal ("Response test vector IPv6 family failed");
+ if (memcmp (addr.ip6.sin6_addr.s6_addr, "\x20\x01\x0d\xb8\x12\x34\x56\x78"
+ "\x00\x11\x22\x33\x44\x55\x66\x77", 16) != 0)
+ fatal ("Response test vector IPv6 address failed");
+ if (ntohs (addr.ip6.sin6_port) != 32853)
+ fatal ("Response test vector IPv6 port failed");
+
+
+ puts ("Done.");
+}
+
+static void test_hash_creds (void)
+{
+ uint8_t md5[16];
+ uint8_t real_md5[] = {
+ 0x84, 0x93, 0xfb, 0xc5,
+ 0x3b, 0xa5, 0x82, 0xfb,
+ 0x4c, 0x04, 0x4c, 0x45,
+ 0x6b, 0xdc, 0x40, 0xeb};
+
+ puts ("Testing long term credentials hash algorithm...");
+
+
+ stun_hash_creds ((uint8_t *) "realm", strlen ("realm"),
+ (uint8_t *) "user", strlen ("user"),
+ (uint8_t *) "pass", strlen ("pass"), md5);
+
+ stun_debug_bytes ("key for user:realm:pass is : ", md5, 16);
+
+ stun_debug_bytes ("RFC key for user:realm:pass is : ", real_md5, 16);
+
+ if(memcmp (md5, real_md5, sizeof(md5)) != 0)
+ fatal ("MD5 hashes are different!");
+
+ puts ("Done!");
+
+}
+
+int main (void)
+{
+ test_message ();
+ test_attribute ();
+ test_vectors ();
+ test_hash_creds ();
+ return 0;
+}
--- /dev/null
+#
+# Makefile.am for the Nice Glib ICE library
+#
+# (C) 2006, 2007 Collabora Ltd.
+# (C) 2006, 2007 Nokia Corporation. All rights reserved.
+#
+# Licensed under MPL 1.1/LGPL 2.1. See file COPYING.
+#
+
+include $(top_srcdir)/common.mk
+AM_CFLAGS = -std=gnu99 $(LIBNICE_CFLAGS)
+AM_CPPFLAGS = -I$(top_srcdir)
+
+bin_PROGRAMS = stunbdc stund
+
+check_PROGRAMS = stund
+
+stund_SOURCES = stund.c stund.h
+stund_LDADD = $(top_builddir)/stun/libstun.la
+
+stunbdc_SOURCES = stunbdc.c
+
+stunbdc_LDADD = $(top_builddir)/stun/libstun.la
+
+
+if WINDOWS
+ AM_CFLAGS += -DWINVER=0x0501 # _WIN32_WINNT_WINXP
+ stunbdc_LDADD += -lws2_32
+endif
+
+EXTRA_DIST = meson.build
--- /dev/null
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+#
+# Makefile.am for the Nice Glib ICE library
+#
+# (C) 2006, 2007 Collabora Ltd.
+# (C) 2006, 2007 Nokia Corporation. All rights reserved.
+#
+# Licensed under MPL 1.1/LGPL 2.1. See file COPYING.
+#
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+bin_PROGRAMS = stunbdc$(EXEEXT) stund$(EXEEXT)
+check_PROGRAMS = stund$(EXEEXT)
+@WINDOWS_TRUE@am__append_1 = -DWINVER=0x0501 # _WIN32_WINNT_WINXP
+@WINDOWS_TRUE@am__append_2 = -lws2_32
+subdir = stun/tools
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/as-compiler-flag.m4 \
+ $(top_srcdir)/m4/ax_check_openssl.m4 \
+ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/introspection.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)"
+PROGRAMS = $(bin_PROGRAMS)
+am_stunbdc_OBJECTS = stunbdc.$(OBJEXT)
+stunbdc_OBJECTS = $(am_stunbdc_OBJECTS)
+am__DEPENDENCIES_1 =
+stunbdc_DEPENDENCIES = $(top_builddir)/stun/libstun.la \
+ $(am__DEPENDENCIES_1)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+am_stund_OBJECTS = stund.$(OBJEXT)
+stund_OBJECTS = $(am_stund_OBJECTS)
+stund_DEPENDENCIES = $(top_builddir)/stun/libstun.la
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/stunbdc.Po ./$(DEPDIR)/stund.Po
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(stunbdc_SOURCES) $(stund_SOURCES)
+DIST_SOURCES = $(stunbdc_SOURCES) $(stund_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/common.mk \
+ $(top_srcdir)/depcomp
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+pkgincludedir = $(includedir)/nice
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCACHE_DISABLE = @CCACHE_DISABLE@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GST010_CFLAGS = @GST010_CFLAGS@
+GST010_LIBS = @GST010_LIBS@
+GST_CFLAGS = @GST_CFLAGS@
+GST_CHECK_CFLAGS = @GST_CHECK_CFLAGS@
+GST_CHECK_LIBS = @GST_CHECK_LIBS@
+GST_LIBS = @GST_LIBS@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@
+GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@
+GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@
+GTKDOC_MKPDF = @GTKDOC_MKPDF@
+GTKDOC_REBASE = @GTKDOC_REBASE@
+GUPNP_CFLAGS = @GUPNP_CFLAGS@
+GUPNP_LIBS = @GUPNP_LIBS@
+GUPNP_PACKAGES = @GUPNP_PACKAGES@
+GUPNP_PACKAGES_PRIVATE = @GUPNP_PACKAGES_PRIVATE@
+GUPNP_PACKAGES_PUBLIC = @GUPNP_PACKAGES_PUBLIC@
+HAVE_GUPNP = @HAVE_GUPNP@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@
+INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@
+INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@
+INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@
+INTROSPECTION_LIBS = @INTROSPECTION_LIBS@
+INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@
+INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
+INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBNICE_CFLAGS = @LIBNICE_CFLAGS@
+LIBNICE_LT_LDFLAGS = @LIBNICE_LT_LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBRT = @LIBRT@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NICE_PACKAGES_PRIVATE = @NICE_PACKAGES_PRIVATE@
+NICE_PACKAGES_PUBLIC = @NICE_PACKAGES_PUBLIC@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_INCLUDES = @OPENSSL_INCLUDES@
+OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+UPNP_ENABLED = @UPNP_ENABLED@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gstplugin010dir = @gstplugin010dir@
+gstplugindir = @gstplugindir@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+CLEANFILES = *.gcno *.gcda
+LOG_DRIVER = $(top_srcdir)/scripts/valgrind-test-driver
+AM_CFLAGS = -std=gnu99 $(LIBNICE_CFLAGS) $(am__append_1)
+AM_CPPFLAGS = -I$(top_srcdir)
+stund_SOURCES = stund.c stund.h
+stund_LDADD = $(top_builddir)/stun/libstun.la
+stunbdc_SOURCES = stunbdc.c
+stunbdc_LDADD = $(top_builddir)/stun/libstun.la $(am__append_2)
+EXTRA_DIST = meson.build
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/common.mk $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu stun/tools/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu stun/tools/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+$(top_srcdir)/common.mk $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
+ fi; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p \
+ || test -f $$p1 \
+ ; then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' \
+ -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' \
+ `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+ @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+
+clean-checkPROGRAMS:
+ @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+
+stunbdc$(EXEEXT): $(stunbdc_OBJECTS) $(stunbdc_DEPENDENCIES) $(EXTRA_stunbdc_DEPENDENCIES)
+ @rm -f stunbdc$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(stunbdc_OBJECTS) $(stunbdc_LDADD) $(LIBS)
+
+stund$(EXEEXT): $(stund_OBJECTS) $(stund_DEPENDENCIES) $(EXTRA_stund_DEPENDENCIES)
+ @rm -f stund$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(stund_OBJECTS) $(stund_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stunbdc.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stund.Po@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
+check: check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+ for dir in "$(DESTDIR)$(bindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \
+ clean-libtool mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/stunbdc.Po
+ -rm -f ./$(DEPDIR)/stund.Po
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-binPROGRAMS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f ./$(DEPDIR)/stunbdc.Po
+ -rm -f ./$(DEPDIR)/stund.Po
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS
+
+.MAKE: check-am install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-binPROGRAMS clean-checkPROGRAMS clean-generic \
+ clean-libtool cscopelist-am ctags ctags-am distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-binPROGRAMS install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags tags-am uninstall uninstall-am uninstall-binPROGRAMS
+
+.PRECIOUS: Makefile
+
+
+check-valgrind:
+ $(MAKE) TESTS_ENVIRONMENT="USE_VALGRIND=1 " check
+
+.PHONY: check-valgrind
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null
+stund_exe = executable('stund', 'stund.c',
+ include_directories: nice_incs,
+ link_with: libstun,
+ install: true)
+
+stunbdc_exe = executable('stunbdc', 'stunbdc.c',
+ include_directories: nice_incs,
+ dependencies: syslibs,
+ link_with: libstun,
+ install: true)
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2007-2009 Nokia Corporation. All rights reserved.
+ * Contact: Rémi Denis-Courmont
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ * Rémi Denis-Courmont, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef _WIN32
+# include <winsock2.h>
+#else
+# include <sys/socket.h>
+# include <netdb.h>
+#endif
+
+#include <sys/types.h>
+#include "stun/stunagent.h"
+#include "stun/usages/bind.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+static int ai_flags = 0;
+
+static void
+printaddr (const char *str, const struct sockaddr *addr, socklen_t addrlen)
+{
+ char hostbuf[NI_MAXHOST], servbuf[NI_MAXSERV];
+
+ int val = getnameinfo (addr, addrlen, hostbuf, sizeof (hostbuf),
+ servbuf, sizeof (servbuf),
+ NI_NUMERICHOST | NI_NUMERICSERV);
+ if (val)
+ printf ("%s: %s\n", str, gai_strerror (val));
+ else
+ printf ("%s: %s port %s\n", str, hostbuf, servbuf);
+}
+
+
+
+static int run (int family, const char *hostname, const char *service)
+{
+ struct addrinfo hints, *res;
+ const struct addrinfo *ptr;
+ int ret = -1;
+
+ memset (&hints, 0, sizeof (hints));
+ hints.ai_family = family;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_flags = ai_flags;
+ if (service == NULL)
+ service = "3478";
+
+ ret = getaddrinfo (hostname, service, &hints, &res);
+ if (ret)
+ {
+ fprintf (stderr, "%s (port %s): %s\n", hostname, service,
+ gai_strerror (ret));
+ return -1;
+ }
+
+ for (ptr = res; ptr != NULL; ptr = ptr->ai_next)
+ {
+ union {
+ struct sockaddr_storage storage;
+ struct sockaddr addr;
+ } addr;
+ socklen_t addrlen = sizeof (addr);
+ StunUsageBindReturn val;
+
+ printaddr ("Server address", ptr->ai_addr, ptr->ai_addrlen);
+
+ val = stun_usage_bind_run (ptr->ai_addr, ptr->ai_addrlen, &addr.storage,
+ &addrlen);
+ if (val)
+ fprintf (stderr, "%d\n", val);
+ else
+ {
+ printaddr ("Mapped address", &addr.addr, addrlen);
+ ret = 0;
+ }
+ }
+
+ freeaddrinfo (res);
+ return ret;
+}
+
+
+int main (int argc, char *argv[])
+{
+ const char *server = NULL, *port = NULL;
+ int family = AF_UNSPEC;
+ int i;
+ int result;
+
+#ifdef _WIN32
+ WSADATA w;
+ WSAStartup (0x0202, &w);
+#endif
+
+ for (i = 1; i < argc; ++i)
+ {
+ const char *arg = argv[i];
+
+ if (arg[0] != '-')
+ break;
+
+ if (strcmp (arg, "--ipv4") == 0 || strcmp (arg, "-4") == 0)
+ {
+ family = AF_INET;
+ }
+ else if (strcmp (arg, "--ipv6") == 0 || strcmp (arg, "-6") == 0)
+ {
+ family = AF_INET6;
+ }
+ else if (strcmp (arg, "--help") == 0 || strcmp (arg, "-h") == 0)
+ {
+ printf ("Usage: %s [-4|-6] <server> [port number]\n"
+ "Performs STUN Binding Discovery\n"
+ "\n"
+ " -4, --ipv4 Force IP version 4\n"
+ " -6, --ipv6 Force IP version 6\n"
+ " -n, --numeric Server in numeric form\n"
+ "\n", argv[0]);
+ return 0;
+ }
+ else if (strcmp (arg, "--numeric") == 0 || strcmp (arg, "-n") == 0)
+ {
+ ai_flags |= AI_NUMERICHOST;
+ }
+ else if (strcmp (arg, "--version") == 0 || strcmp (arg, "-V") == 0)
+ {
+ printf ("stunbcd: STUN Binding Discovery client (%s v%s)\n",
+ PACKAGE, VERSION);
+ return 0;
+ } else {
+ fprintf (stderr, "Unexpected command line argument '%s'", arg);
+ return 2;
+ }
+ }
+
+ if (i < argc)
+ server = argv[i++];
+ if (i < argc)
+ port = argv[i++];
+ if (i < argc)
+ {
+ fprintf (stderr, "%s: extra parameter `%s'\n", argv[0], argv[i]);
+ return 2;
+ }
+
+ result = run (family, server, port) ? 1 : 0;
+
+#ifdef _WIN32
+ WSACleanup();
+#endif
+
+ return result;
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2007-2009 Nokia Corporation. All rights reserved.
+ * Contact: Rémi Denis-Courmont
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ * Rémi Denis-Courmont, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef __sun
+#define _XPG4_2 1
+#endif
+
+#ifndef _WIN32
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <signal.h>
+
+#include <sys/types.h>
+
+
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#else
+# define close(fd) _close(fd)
+#endif
+
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+
+#ifndef SOL_IP
+# define SOL_IP IPPROTO_IP
+#endif
+
+#ifndef SOL_IPV6
+# define SOL_IPV6 IPPROTO_IPV6
+#endif
+
+
+#ifndef IPV6_RECVPKTINFO
+# define IPV6_RECVPKTINFO IPV6_PKTINFO
+#endif
+
+/** Default port for STUN binding discovery */
+#define IPPORT_STUN 3478
+
+#include "stun/stunagent.h"
+#include "stund.h"
+
+static const uint16_t known_attributes[] = {
+ 0
+};
+
+/*
+ * Creates a listening socket
+ */
+int listen_socket (int fam, int type, int proto, unsigned int port)
+{
+ int yes = 1;
+ int fd = socket (fam, type, proto);
+ union {
+ struct sockaddr addr;
+ struct sockaddr_in in;
+ struct sockaddr_in6 in6;
+ struct sockaddr_storage storage;
+ } addr;
+
+ if (fd == -1)
+ {
+ perror ("Error opening IP port");
+ return -1;
+ }
+
+ memset (&addr, 0, sizeof (addr));
+ addr.storage.ss_family = fam;
+#ifdef HAVE_SA_LEN
+ addr.storage.ss_len = sizeof (addr);
+#endif
+
+ switch (fam)
+ {
+ case AF_INET:
+ addr.in.sin_port = htons (port);
+ break;
+
+ case AF_INET6:
+#ifdef IPV6_V6ONLY
+ setsockopt (fd, SOL_IPV6, IPV6_V6ONLY, &yes, sizeof (yes));
+#endif
+ addr.in6.sin6_port = htons (port);
+ break;
+
+ default:
+ assert (0); /* should never be reached */
+ }
+
+ if (bind (fd, &addr.addr, sizeof (struct sockaddr_storage)))
+ {
+ perror ("Error opening IP port");
+ goto error;
+ }
+
+ if ((type == SOCK_DGRAM) || (type == SOCK_RAW))
+ {
+ switch (fam)
+ {
+ case AF_INET:
+#ifdef IP_RECVERR
+ setsockopt (fd, SOL_IP, IP_RECVERR, &yes, sizeof (yes));
+#endif
+ break;
+
+ case AF_INET6:
+#ifdef IPV6_RECVERR
+ setsockopt (fd, SOL_IPV6, IPV6_RECVERR, &yes, sizeof (yes));
+#endif
+ break;
+
+ default:
+ assert (0); /* should never be reached */
+ }
+ }
+ else
+ {
+ if (listen (fd, INT_MAX))
+ {
+ perror ("Error opening IP port");
+ goto error;
+ }
+ }
+
+ return fd;
+
+error:
+ close (fd);
+ return -1;
+}
+
+static int dgram_process (int sock, StunAgent *oldagent, StunAgent *newagent)
+{
+ union {
+ struct sockaddr_storage storage;
+ struct sockaddr addr;
+ } addr;
+ socklen_t addr_len;
+ uint8_t buf[STUN_MAX_MESSAGE_SIZE];
+ size_t buf_len = 0;
+ size_t len = 0;
+ StunMessage request;
+ StunMessage response;
+ StunValidationStatus validation;
+ StunAgent *agent = NULL;
+
+ addr_len = sizeof (struct sockaddr_storage);
+ len = recvfrom (sock, buf, sizeof(buf), 0, &addr.addr, &addr_len);
+ if (len == (size_t)-1)
+ return -1;
+
+ validation = stun_agent_validate (newagent, &request, buf, len, NULL, 0);
+
+ if (validation == STUN_VALIDATION_SUCCESS) {
+ agent = newagent;
+ }
+ else {
+ validation = stun_agent_validate (oldagent, &request, buf, len, NULL, 0);
+ agent = oldagent;
+ }
+
+ /* Unknown attributes */
+ if (validation == STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE)
+ {
+ buf_len = stun_agent_build_unknown_attributes_error (agent, &response, buf,
+ sizeof (buf), &request);
+ goto send_buf;
+ }
+
+ /* Mal-formatted packets */
+ if (validation != STUN_VALIDATION_SUCCESS ||
+ stun_message_get_class (&request) != STUN_REQUEST) {
+ return -1;
+ }
+
+ switch (stun_message_get_method (&request))
+ {
+ case STUN_BINDING:
+ stun_agent_init_response (agent, &response, buf, sizeof (buf), &request);
+ if (stun_message_has_cookie (&request))
+ stun_message_append_xor_addr (&response,
+ STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, &addr.storage, addr_len);
+ else
+ stun_message_append_addr (&response, STUN_ATTRIBUTE_MAPPED_ADDRESS,
+ &addr.addr, addr_len);
+ break;
+
+ case STUN_SHARED_SECRET:
+ case STUN_ALLOCATE:
+ case STUN_SEND:
+ case STUN_CONNECT:
+ case STUN_IND_SEND:
+ case STUN_IND_DATA:
+ case STUN_CREATEPERMISSION:
+ case STUN_CHANNELBIND:
+ default:
+ if (!stun_agent_init_error (agent, &response, buf, sizeof (buf),
+ &request, STUN_ERROR_BAD_REQUEST))
+ return -1;
+ }
+
+ buf_len = stun_agent_finish_message (agent, &response, NULL, 0);
+send_buf:
+ len = sendto (sock, buf, buf_len, 0, &addr.addr, addr_len);
+ return (len < buf_len) ? -1 : 0;
+}
+
+
+static int run (int family, int protocol, unsigned port)
+{
+ StunAgent oldagent;
+ StunAgent newagent;
+ int sock = listen_socket (family, SOCK_DGRAM, protocol, port);
+ if (sock == -1)
+ return -1;
+
+ stun_agent_init (&oldagent, known_attributes,
+ STUN_COMPATIBILITY_RFC3489, 0);
+ stun_agent_init (&newagent, known_attributes,
+ STUN_COMPATIBILITY_RFC5389, STUN_AGENT_USAGE_USE_FINGERPRINT);
+
+ for (;;)
+ dgram_process (sock, &oldagent, &newagent);
+}
+
+
+/* Pretty useless dummy signal handler...
+ * But calling exit() is needed for gcov to work properly. */
+static void exit_handler (int signum)
+{
+ (void)signum;
+ exit (0);
+}
+
+
+int main (int argc, char *argv[])
+{
+ int family = AF_INET;
+ unsigned port = IPPORT_STUN;
+ int i;
+
+ for (i = 1; i < argc; ++i)
+ {
+ const char *arg = argv[i];
+
+ if (strcmp (arg, "-4") == 0)
+ {
+ family = AF_INET;
+ }
+ else if (strcmp (arg, "-6") == 0)
+ {
+ family = AF_INET6;
+ }
+ else if (arg[0] < '0' || arg[0] > '9')
+ {
+ fprintf (stderr, "Unexpected command line argument '%s'", arg);
+ }
+ else
+ {
+ port = atoi (arg);
+ break;
+ }
+ }
+
+ signal (SIGINT, exit_handler);
+ signal (SIGTERM, exit_handler);
+ return run (family, IPPROTO_UDP, port) ? EXIT_FAILURE : EXIT_SUCCESS;
+}
+
+#else
+int main (int argc, char **argv) {
+ return 0;
+}
+#endif
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2007-2009 Nokia Corporation. All rights reserved.
+ * Contact: Rémi Denis-Courmont
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ * Rémi Denis-Courmont, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef NICE_STUN_STUND_H
+# define NICE_STUN_STUND_H 1
+
+int listen_socket (int fam, int type, int proto, unsigned port);
+ssize_t send_safe (int fd, const struct msghdr *msg);
+ssize_t recv_safe (int fd, struct msghdr *msg);
+
+#endif
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2007-2009 Nokia Corporation. All rights reserved.
+ * Contact: Rémi Denis-Courmont
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ * Rémi Denis-Courmont, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef _WIN32
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include "win32_common.h"
+#define close closesocket
+#else
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#endif
+
+
+#ifdef HAVE_POLL
+# include <poll.h>
+#endif
+
+
+#include "bind.h"
+#include "stun/stunagent.h"
+
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <errno.h>
+#include "timer.h"
+
+
+#ifndef SOL_IP
+# define SOL_IP IPPROTO_IP
+#endif
+
+#ifndef SOL_IPV6
+# define SOL_IPV6 IPPROTO_IPV6
+#endif
+
+
+/** Non-blocking mode STUN binding discovery */
+
+size_t stun_usage_bind_create (StunAgent *agent, StunMessage *msg,
+ uint8_t *buffer, size_t buffer_len)
+{
+ stun_agent_init_request (agent, msg, buffer, buffer_len, STUN_BINDING);
+
+ return stun_agent_finish_message (agent, msg, NULL, 0);
+}
+
+StunUsageBindReturn stun_usage_bind_process (StunMessage *msg,
+ struct sockaddr *addr, socklen_t *addrlen,
+ struct sockaddr *alternate_server, socklen_t *alternate_server_len)
+{
+ int code = -1;
+ StunMessageReturn val;
+ union {
+ struct sockaddr *sa;
+ struct sockaddr_storage *sas;
+ } sa;
+
+ sa.sa = addr;
+
+ if (stun_message_get_method (msg) != STUN_BINDING)
+ return STUN_USAGE_BIND_RETURN_INVALID;
+
+ switch (stun_message_get_class (msg))
+ {
+ case STUN_REQUEST:
+ case STUN_INDICATION:
+ return STUN_USAGE_BIND_RETURN_INVALID;
+
+ case STUN_RESPONSE:
+ break;
+
+ case STUN_ERROR:
+ if (stun_message_find_error (msg, &code) != STUN_MESSAGE_RETURN_SUCCESS) {
+ /* missing ERROR-CODE: ignore message */
+ return STUN_USAGE_BIND_RETURN_INVALID;
+ }
+
+ /* NOTE: currently we ignore unauthenticated messages if the context
+ * is authenticated, for security reasons. */
+ stun_debug (" STUN error message received (code: %d)", code);
+
+ /* ALTERNATE-SERVER mechanism */
+ if ((code / 100) == 3) {
+ union {
+ struct sockaddr *sa;
+ struct sockaddr_storage *sas;
+ } alternate_sa;
+
+ alternate_sa.sa = alternate_server;
+ if (alternate_server && alternate_server_len) {
+ if (stun_message_find_addr (msg, STUN_ATTRIBUTE_ALTERNATE_SERVER,
+ alternate_sa.sas,
+ alternate_server_len) != STUN_MESSAGE_RETURN_SUCCESS) {
+ stun_debug (" Unexpectedly missing ALTERNATE-SERVER attribute");
+ return STUN_USAGE_BIND_RETURN_ERROR;
+ }
+ } else {
+ if (!stun_message_has_attribute (msg, STUN_ATTRIBUTE_ALTERNATE_SERVER)) {
+ stun_debug (" Unexpectedly missing ALTERNATE-SERVER attribute");
+ return STUN_USAGE_BIND_RETURN_ERROR;
+ }
+ }
+
+ stun_debug ("Found alternate server");
+ return STUN_USAGE_BIND_RETURN_ALTERNATE_SERVER;
+
+ }
+ return STUN_USAGE_BIND_RETURN_ERROR;
+
+ default:
+ /* Fall through. */
+ break;
+ }
+
+ stun_debug ("Received %u-bytes STUN message", stun_message_length (msg));
+
+ val = stun_message_find_xor_addr (msg,
+ STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, sa.sas,
+ addrlen);
+ if (val != STUN_MESSAGE_RETURN_SUCCESS)
+ {
+ stun_debug (" No XOR-MAPPED-ADDRESS: %d", val);
+ val = stun_message_find_addr (msg,
+ STUN_ATTRIBUTE_MAPPED_ADDRESS, sa.sas,
+ addrlen);
+ if (val != STUN_MESSAGE_RETURN_SUCCESS)
+ {
+ stun_debug (" No MAPPED-ADDRESS: %d", val);
+ return STUN_USAGE_BIND_RETURN_ERROR;
+ }
+ }
+
+ stun_debug (" Mapped address found!");
+ return STUN_USAGE_BIND_RETURN_SUCCESS;
+
+}
+
+
+/** Binding keep-alive (Binding discovery indication!) */
+
+size_t
+stun_usage_bind_keepalive (StunAgent *agent, StunMessage *msg,
+ uint8_t *buf, size_t len)
+{
+
+ stun_agent_init_indication (agent, msg,
+ buf, len, STUN_BINDING);
+ return stun_agent_finish_message (agent, msg, NULL, 0);
+}
+
+
+
+typedef struct stun_trans_s
+{
+
+ int fd;
+ int own_fd;
+ socklen_t dstlen;
+ struct sockaddr_storage dst;
+} StunTransport;
+
+
+typedef enum {
+ STUN_USAGE_TRANS_RETURN_SUCCESS,
+ STUN_USAGE_TRANS_RETURN_ERROR,
+ STUN_USAGE_TRANS_RETURN_RETRY,
+ STUN_USAGE_TRANS_RETURN_INVALID_ADDRESS,
+ STUN_USAGE_TRANS_RETURN_UNSUPPORTED,
+} StunUsageTransReturn;
+
+
+
+
+static StunUsageTransReturn
+stun_trans_init (StunTransport *tr, int fd,
+ const struct sockaddr *srv, socklen_t srvlen)
+{
+ assert (fd != -1);
+
+ if ((size_t) srvlen > sizeof (tr->dst))
+ return STUN_USAGE_TRANS_RETURN_INVALID_ADDRESS;
+
+ tr->own_fd = -1;
+ tr->fd = fd;
+
+ tr->dstlen = srvlen;
+ memcpy (&tr->dst, srv, srvlen);
+
+ return STUN_USAGE_TRANS_RETURN_SUCCESS;
+}
+
+
+/*
+ * Creates and connects a socket. This is useful when a socket is to be used
+ * for multiple consecutive transactions (e.g. TURN).
+ */
+static int stun_socket (int family, int type, int proto)
+{
+#ifdef _WIN32
+ unsigned long set_nonblock=1;
+#endif
+
+ int fd = socket (family, type, proto);
+ if (fd == -1)
+ return -1;
+
+#ifdef FD_CLOEXEC
+ fcntl (fd, F_SETFD, fcntl (fd, F_GETFD) | FD_CLOEXEC);
+#endif
+#ifdef O_NONBLOCK
+ fcntl (fd, F_SETFL, fcntl (fd, F_GETFL) | O_NONBLOCK);
+#elif defined _WIN32
+ ioctlsocket(fd, FIONBIO, &set_nonblock);
+#endif
+
+#ifdef MSG_ERRQUEUE
+ if (type == SOCK_DGRAM)
+ {
+ /* Linux specifics for ICMP errors on non-connected sockets */
+ int yes = 1;
+ switch (family)
+ {
+ case AF_INET:
+ setsockopt (fd, SOL_IP, IP_RECVERR, &yes, sizeof (yes));
+ break;
+ case AF_INET6:
+ setsockopt (fd, SOL_IPV6, IPV6_RECVERR, &yes, sizeof (yes));
+ break;
+ default:
+ /* Nothing to do. */
+ break;
+ }
+ }
+#endif
+
+ return fd;
+}
+
+
+static StunUsageTransReturn
+stun_trans_create (StunTransport *tr, int type, int proto,
+ const struct sockaddr *srv, socklen_t srvlen)
+{
+ StunUsageTransReturn val = STUN_USAGE_TRANS_RETURN_ERROR;
+ int fd;
+
+ if ((size_t) srvlen < sizeof(*srv))
+ return STUN_USAGE_TRANS_RETURN_INVALID_ADDRESS;
+
+ fd = stun_socket (srv->sa_family, type, proto);
+ if (fd == -1)
+ return STUN_USAGE_TRANS_RETURN_ERROR;
+
+ if (type != SOCK_DGRAM) {
+ if (connect (fd, srv, srvlen) &&
+#ifdef _WIN32
+ (WSAGetLastError () != WSAEINPROGRESS)) {
+#else
+ (errno != EINPROGRESS)) {
+#endif
+ goto error;
+ }
+ val = stun_trans_init (tr, fd, NULL, 0);
+ } else {
+ val = stun_trans_init (tr, fd, srv, srvlen);
+ }
+
+ if (val)
+ goto error;
+
+ tr->own_fd = tr->fd;
+ return STUN_USAGE_TRANS_RETURN_SUCCESS;
+
+error:
+ close (fd);
+ return val;
+}
+
+
+static void stun_trans_deinit (StunTransport *tr)
+{
+ int saved = errno;
+
+ assert (tr->fd != -1);
+
+ if (tr->own_fd != -1)
+ close (tr->own_fd);
+
+ tr->own_fd = -1;
+ tr->fd = -1;
+
+ errno = saved;
+}
+
+
+#ifndef MSG_DONTWAIT
+# define MSG_DONTWAIT 0
+#endif
+#ifndef MSG_NOSIGNAL
+# define MSG_NOSIGNAL 0
+#endif
+
+
+static int stun_err_dequeue (int fd)
+{
+#ifdef MSG_ERRQUEUE
+ struct msghdr hdr;
+ int saved_errno = errno, ret;
+
+ memset (&hdr, 0, sizeof (hdr));
+ ret = (recvmsg (fd, &hdr, MSG_ERRQUEUE) >= 0);
+ errno = saved_errno;
+ return ret;
+#else
+ (void) fd;
+ return 0;
+#endif
+}
+
+
+static ssize_t
+stun_trans_sendto (StunTransport *tr, const uint8_t *buf, size_t len,
+ const struct sockaddr *dst, socklen_t dstlen)
+{
+ static const int flags = MSG_DONTWAIT | MSG_NOSIGNAL;
+ ssize_t val;
+
+ do
+ {
+ if (dstlen > 0)
+ val = sendto (tr->fd, (void *)buf, len, flags, dst, dstlen);
+ else
+ val = send (tr->fd, (void *)buf, len, flags);
+ }
+ while ((val == -1) && stun_err_dequeue (tr->fd));
+
+ return val;
+}
+
+
+static ssize_t
+stun_trans_recvfrom (StunTransport *tr, uint8_t *buf, size_t maxlen,
+ struct sockaddr_storage * dst,
+ socklen_t * dstlen)
+{
+ static const int flags = MSG_DONTWAIT | MSG_NOSIGNAL;
+ ssize_t val;
+
+ if (dstlen != NULL)
+ val = recvfrom (tr->fd, (void *)buf, maxlen, flags, (struct sockaddr *) dst,
+ dstlen);
+ else
+ val = recv (tr->fd, (void *)buf, maxlen, flags);
+
+ if (val == -1)
+ stun_err_dequeue (tr->fd);
+
+ return val;
+}
+
+
+static ssize_t
+stun_trans_send (StunTransport *tr, const uint8_t *buf, size_t len)
+{
+ struct sockaddr *conv;
+
+ conv = (struct sockaddr *) &tr->dst;
+
+ return stun_trans_sendto (tr, buf, len, conv, tr->dstlen);
+}
+
+static ssize_t
+stun_trans_recv (StunTransport *tr, uint8_t *buf, size_t maxlen)
+{
+ return stun_trans_recvfrom (tr, buf, maxlen, NULL, NULL);
+}
+
+
+#ifdef HAVE_POLL
+static int stun_trans_fd (const StunTransport *tr)
+{
+ assert (tr != NULL);
+ return tr->fd;
+}
+#endif
+
+
+/*
+ * Waits for a response or timeout to occur.
+ *
+ * @return ETIMEDOUT if the transaction has timed out, or 0 if an incoming
+ * message needs to be processed.
+ */
+static StunUsageTransReturn
+stun_trans_poll (StunTransport *tr, unsigned int delay)
+{
+#ifdef HAVE_POLL
+ struct pollfd ufd;
+
+ memset (&ufd, 0, sizeof (ufd));
+ ufd.fd = stun_trans_fd (tr);
+
+ ufd.events |= POLLIN;
+
+ if (poll (&ufd, 1, delay) <= 0) {
+ return STUN_USAGE_TRANS_RETURN_RETRY;
+ }
+
+ return STUN_USAGE_TRANS_RETURN_SUCCESS;
+#else
+ (void)tr;
+ return STUN_USAGE_TRANS_RETURN_UNSUPPORTED;
+#endif
+}
+
+
+
+/** Blocking mode STUN binding discovery */
+StunUsageBindReturn stun_usage_bind_run (const struct sockaddr *srv,
+ socklen_t srvlen, struct sockaddr_storage *addr, socklen_t *addrlen)
+{
+ StunTimer timer;
+ StunTransport trans;
+ StunAgent agent;
+ StunMessage req;
+ uint8_t req_buf[STUN_MAX_MESSAGE_SIZE];
+ StunMessage msg;
+ uint8_t buf[STUN_MAX_MESSAGE_SIZE];
+ StunValidationStatus valid;
+ size_t len;
+ StunUsageTransReturn ret;
+ int val;
+ struct sockaddr_storage alternate_server = { AF_UNSPEC } ;
+ socklen_t alternate_server_len = sizeof (alternate_server);
+ StunUsageBindReturn bind_ret;
+
+ trans.fd = -1;
+
+ stun_agent_init (&agent, STUN_ALL_KNOWN_ATTRIBUTES,
+ STUN_COMPATIBILITY_RFC3489, 0);
+
+ len = stun_usage_bind_create (&agent, &req, req_buf, sizeof(req_buf));
+
+ ret = stun_trans_create (&trans, SOCK_DGRAM, 0, srv, srvlen);
+ if (ret != STUN_USAGE_TRANS_RETURN_SUCCESS) {
+ stun_debug ("STUN transaction failed: couldn't create transport.");
+ bind_ret = STUN_USAGE_BIND_RETURN_ERROR;
+ goto done;
+ }
+
+ val = stun_trans_send (&trans, req_buf, len);
+ if (val < -1) {
+ stun_debug ("STUN transaction failed: couldn't send request.");
+ bind_ret = STUN_USAGE_BIND_RETURN_ERROR;
+ goto done;
+ }
+
+ stun_timer_start (&timer, STUN_TIMER_DEFAULT_TIMEOUT,
+ STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS);
+ stun_debug ("STUN transaction started (timeout %dms).",
+ stun_timer_remainder (&timer));
+
+ do
+ {
+ for (;;) {
+ unsigned delay = stun_timer_remainder (&timer);
+ ret = stun_trans_poll (&trans, delay);
+ if (ret == STUN_USAGE_TRANS_RETURN_RETRY) {
+ switch (stun_timer_refresh (&timer)) {
+ case STUN_USAGE_TIMER_RETURN_TIMEOUT:
+ stun_debug ("STUN transaction failed: time out.");
+ bind_ret = STUN_USAGE_BIND_RETURN_TIMEOUT; // fatal error!
+ goto done;
+ case STUN_USAGE_TIMER_RETURN_RETRANSMIT:
+ stun_debug ("STUN transaction retransmitted (timeout %dms).",
+ stun_timer_remainder (&timer));
+ val = stun_trans_send (&trans, req_buf, len);
+ if (val < -1) {
+ stun_debug ("STUN transaction failed: couldn't resend request.");
+ bind_ret = STUN_USAGE_BIND_RETURN_ERROR;
+ goto done;
+ }
+ continue;
+ case STUN_USAGE_TIMER_RETURN_SUCCESS:
+ default:
+ /* Fall through. */
+ break;
+ }
+ }
+ val = stun_trans_recv (&trans, buf, sizeof (buf));
+ if (val >= 0) {
+ break;
+ }
+ }
+
+ valid = stun_agent_validate (&agent, &msg, buf, val, NULL, NULL);
+ if (valid == STUN_VALIDATION_UNKNOWN_ATTRIBUTE)
+ {
+ bind_ret = STUN_USAGE_BIND_RETURN_ERROR;
+ goto done;
+ }
+
+ if (valid != STUN_VALIDATION_SUCCESS) {
+ ret = STUN_USAGE_TRANS_RETURN_RETRY;
+ } else {
+ bind_ret = stun_usage_bind_process (&msg, (struct sockaddr *) addr,
+ addrlen, (struct sockaddr *) &alternate_server, &alternate_server_len);
+ if (bind_ret == STUN_USAGE_BIND_RETURN_ALTERNATE_SERVER) {
+ stun_trans_deinit (&trans);
+
+ assert (alternate_server.ss_family != AF_UNSPEC);
+
+ ret = stun_trans_create (&trans, SOCK_DGRAM, 0,
+ (struct sockaddr *) &alternate_server, alternate_server_len);
+
+ if (ret != STUN_USAGE_TRANS_RETURN_SUCCESS) {
+ bind_ret = STUN_USAGE_BIND_RETURN_ERROR;
+ goto done;
+ }
+
+ val = stun_trans_send (&trans, req_buf, len);
+ if (val < -1)
+ {
+ bind_ret = STUN_USAGE_BIND_RETURN_ERROR;
+ goto done;
+ }
+
+ stun_timer_start (&timer, STUN_TIMER_DEFAULT_TIMEOUT,
+ STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS);
+ ret = STUN_USAGE_TRANS_RETURN_RETRY;
+ } else if (bind_ret == STUN_USAGE_BIND_RETURN_INVALID) {
+ ret = STUN_USAGE_TRANS_RETURN_RETRY;
+ } else {
+ break;
+ }
+ }
+ }
+ while (ret == STUN_USAGE_TRANS_RETURN_RETRY);
+
+done:
+ if (trans.fd != -1)
+ stun_trans_deinit (&trans);
+
+ return bind_ret;
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2007-2009 Nokia Corporation. All rights reserved.
+ * Contact: Rémi Denis-Courmont
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ * Rémi Denis-Courmont, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef STUN_BIND_H
+# define STUN_BIND_H 1
+
+/**
+ * SECTION:bind
+ * @short_description: STUN Binding Usage
+ * @include: stun/usages/bind.h
+ * @stability: Stable
+ *
+ * The STUN Binding usage allows for easily creating and parsing STUN Binding
+ * requests and responses. It offers both an asynchronous and a synchronous API
+ * that uses the STUN timer usage.
+ */
+
+
+#ifdef _WIN32
+# include "../win32_common.h"
+#else
+# include <stdbool.h>
+# include <stdint.h>
+#endif
+
+# include "stun/stunagent.h"
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+/**
+ * StunUsageBindReturn:
+ * @STUN_USAGE_BIND_RETURN_SUCCESS: The binding usage succeeded
+ * @STUN_USAGE_BIND_RETURN_ERROR: There was an unknown error in the bind usage
+ * @STUN_USAGE_BIND_RETURN_INVALID: The message is invalid and should be ignored
+ * @STUN_USAGE_BIND_RETURN_ALTERNATE_SERVER: The binding request has an
+ * ALTERNATE-SERVER attribute
+ * @STUN_USAGE_BIND_RETURN_TIMEOUT: The binding was unsuccessful because it has
+ * timed out.
+ *
+ * Return value of stun_usage_bind_process() and stun_usage_bind_run() which
+ * allows you to see what status the function call returned.
+ */
+typedef enum {
+ STUN_USAGE_BIND_RETURN_SUCCESS,
+ STUN_USAGE_BIND_RETURN_ERROR,
+ STUN_USAGE_BIND_RETURN_INVALID,
+ STUN_USAGE_BIND_RETURN_ALTERNATE_SERVER,
+ STUN_USAGE_BIND_RETURN_TIMEOUT,
+} StunUsageBindReturn;
+
+
+/**
+ * stun_usage_bind_create:
+ * @agent: The #StunAgent to use to create the binding request
+ * @msg: The #StunMessage to build
+ * @buffer: The buffer to use for creating the #StunMessage
+ * @buffer_len: The size of the @buffer
+ *
+ * Create a new STUN binding request to use with a STUN server.
+ * Returns: The length of the built message.
+ */
+size_t stun_usage_bind_create (StunAgent *agent, StunMessage *msg,
+ uint8_t *buffer, size_t buffer_len);
+
+/**
+ * stun_usage_bind_process:
+ * @msg: The #StunMessage to process
+ * @addr: A pointer to a #sockaddr structure to fill with the mapped address
+ * that the STUN server gives us
+ * @addrlen: The length of @add. rMust be set to the size of the @addr socket
+ * address and will be set to the actual length of the socket address.
+ * @alternate_server: A pointer to a #sockaddr structure to fill with the
+ * address of an alternate server to which we should send our new STUN
+ * binding request, in case the currently used STUN server is requesting the use
+ * of an alternate server. This argument will only be filled if the return value
+ * of the function is #STUN_USAGE_BIND_RETURN_ALTERNATE_SERVER
+ * @alternate_server_len: The length of @alternate_server. Must be set to
+ * the size of the @alternate_server socket address and will be set to the
+ * actual length of the socket address.
+ *
+ * Process a STUN binding response and extracts the mapped address from the STUN
+ * message. Also checks for the ALTERNATE-SERVER attribute.
+ * Returns: A #StunUsageBindReturn value.
+ * Note that #STUN_USAGE_BIND_RETURN_TIMEOUT cannot be returned by this function
+ */
+StunUsageBindReturn stun_usage_bind_process (StunMessage *msg,
+ struct sockaddr *addr, socklen_t *addrlen,
+ struct sockaddr *alternate_server, socklen_t *alternate_server_len);
+
+/**
+ * stun_usage_bind_keepalive:
+ * @agent: The #StunAgent to use to build the message
+ * @msg: The #StunMessage to build
+ * @buf: The buffer to use for creating the #StunMessage
+ * @len: The size of the @buf
+ *
+ * Creates a STUN binding indication that can be used for a keepalive.
+ * Since this is an indication message, no STUN response will be generated
+ * and it can only be used as a keepalive message.
+ * Returns: The length of the message to send
+ */
+size_t stun_usage_bind_keepalive (StunAgent *agent, StunMessage *msg,
+ uint8_t *buf, size_t len);
+
+/**
+ * stun_usage_bind_run:
+ * @srv: A pointer to the #sockaddr structure representing the STUN server's
+ * address
+ * @srvlen: The length of @srv
+ * @addr: A pointer to a #sockaddr structure to fill with the mapped address
+ * that the STUN server gives us
+ * @addrlen: The length of @addr
+ *
+ * This is a convenience function that will do a synchronous Binding request to
+ * a server and wait for its answer. It will create the socket transports and
+ * use the #StunTimer usage to send the request and handle the response.
+ * Returns: A #StunUsageBindReturn.
+ * Possible return values are #STUN_USAGE_BIND_RETURN_SUCCESS,
+ * #STUN_USAGE_BIND_RETURN_ERROR and #STUN_USAGE_BIND_RETURN_TIMEOUT
+ */
+StunUsageBindReturn stun_usage_bind_run (const struct sockaddr *srv,
+ socklen_t srvlen, struct sockaddr_storage *addr, socklen_t *addrlen);
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2007-2009 Nokia Corporation. All rights reserved.
+ * Contact: Rémi Denis-Courmont
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ * Rémi Denis-Courmont, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+
+#ifdef _WIN32
+#include <winsock2.h>
+#else
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#endif
+
+
+#include "stunagent.h"
+
+/** ICE connectivity checks **/
+#include "ice.h"
+
+
+size_t
+stun_usage_ice_conncheck_create (StunAgent *agent, StunMessage *msg,
+ uint8_t *buffer, size_t buffer_len,
+ const uint8_t *username, const size_t username_len,
+ const uint8_t *password, const size_t password_len,
+ bool cand_use, bool controlling, uint32_t priority,
+ uint64_t tie, const char *candidate_identifier,
+ StunUsageIceCompatibility compatibility)
+{
+ StunMessageReturn val;
+
+ stun_agent_init_request (agent, msg, buffer, buffer_len, STUN_BINDING);
+
+ if (compatibility == STUN_USAGE_ICE_COMPATIBILITY_RFC5245 ||
+ compatibility == STUN_USAGE_ICE_COMPATIBILITY_MSICE2) {
+ if (cand_use)
+ {
+ val = stun_message_append_flag (msg, STUN_ATTRIBUTE_USE_CANDIDATE);
+ if (val != STUN_MESSAGE_RETURN_SUCCESS)
+ return 0;
+ }
+
+ val = stun_message_append32 (msg, STUN_ATTRIBUTE_PRIORITY, priority);
+ if (val != STUN_MESSAGE_RETURN_SUCCESS)
+ return 0;
+
+ if (controlling)
+ val = stun_message_append64 (msg, STUN_ATTRIBUTE_ICE_CONTROLLING, tie);
+ else
+ val = stun_message_append64 (msg, STUN_ATTRIBUTE_ICE_CONTROLLED, tie);
+ if (val != STUN_MESSAGE_RETURN_SUCCESS)
+ return 0;
+ }
+
+ if (username && username_len > 0) {
+ val = stun_message_append_bytes (msg, STUN_ATTRIBUTE_USERNAME,
+ username, username_len);
+ if (val != STUN_MESSAGE_RETURN_SUCCESS)
+ return 0;
+ }
+
+ if (compatibility == STUN_USAGE_ICE_COMPATIBILITY_MSICE2 &&
+ candidate_identifier) {
+ size_t identifier_len = strlen(candidate_identifier);
+ size_t attribute_len = identifier_len;
+ int modulo4 = identifier_len % 4;
+ uint8_t* buf;
+
+ if (modulo4)
+ attribute_len += 4 - modulo4;
+
+ // Avoid a coverify false positive
+ assert (attribute_len >= identifier_len);
+ buf = malloc(attribute_len);
+ memset(buf, 0, attribute_len);
+ memcpy(buf, candidate_identifier, identifier_len);
+
+ val = stun_message_append_bytes (msg, STUN_ATTRIBUTE_CANDIDATE_IDENTIFIER,
+ buf, attribute_len);
+
+ free(buf);
+
+ if (val != STUN_MESSAGE_RETURN_SUCCESS)
+ return 0;
+
+ val = stun_message_append32 (msg,
+ STUN_ATTRIBUTE_MS_IMPLEMENTATION_VERSION, 2);
+
+ if (val != STUN_MESSAGE_RETURN_SUCCESS)
+ return 0;
+ }
+
+ return stun_agent_finish_message (agent, msg, password, password_len);
+
+}
+
+
+StunUsageIceReturn stun_usage_ice_conncheck_process (StunMessage *msg,
+ struct sockaddr_storage *addr, socklen_t *addrlen,
+ StunUsageIceCompatibility compatibility)
+{
+ int code = -1;
+ StunMessageReturn val;
+
+ if (stun_message_get_method (msg) != STUN_BINDING)
+ return STUN_USAGE_ICE_RETURN_INVALID;
+
+ switch (stun_message_get_class (msg))
+ {
+ case STUN_REQUEST:
+ case STUN_INDICATION:
+ return STUN_USAGE_ICE_RETURN_INVALID;
+
+ case STUN_RESPONSE:
+ break;
+
+ case STUN_ERROR:
+ default:
+ if (stun_message_find_error (msg, &code) != STUN_MESSAGE_RETURN_SUCCESS) {
+ /* missing ERROR-CODE: ignore message */
+ return STUN_USAGE_ICE_RETURN_INVALID;
+ }
+
+ if (code == STUN_ERROR_ROLE_CONFLICT)
+ return STUN_USAGE_ICE_RETURN_ROLE_CONFLICT;
+
+ /* NOTE: currently we ignore unauthenticated messages if the context
+ * is authenticated, for security reasons. */
+ stun_debug (" STUN error message received (code: %d)", code);
+
+ return STUN_USAGE_ICE_RETURN_ERROR;
+ }
+
+ stun_debug ("Received %u-bytes STUN message", stun_message_length (msg));
+
+ if (compatibility == STUN_USAGE_ICE_COMPATIBILITY_MSN) {
+ union {
+ StunTransactionId u8;
+ uint32_t u32[STUN_MESSAGE_TRANS_ID_LEN / 4];
+ } transid;
+ uint32_t magic_cookie;
+ stun_message_id (msg, transid.u8);
+ magic_cookie = *(transid.u32);
+
+ val = stun_message_find_xor_addr_full (msg,
+ STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, addr, addrlen, htonl (magic_cookie));
+ } else {
+ val = stun_message_find_xor_addr (msg,
+ STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, addr, addrlen);
+ }
+ if (val != STUN_MESSAGE_RETURN_SUCCESS)
+ {
+ stun_debug (" No XOR-MAPPED-ADDRESS: %d", val);
+ val = stun_message_find_addr (msg,
+ STUN_ATTRIBUTE_MAPPED_ADDRESS, addr, addrlen);
+ if (val != STUN_MESSAGE_RETURN_SUCCESS)
+ {
+ stun_debug (" No MAPPED-ADDRESS: %d", val);
+ return STUN_USAGE_ICE_RETURN_NO_MAPPED_ADDRESS;
+ }
+ }
+
+ stun_debug ("Mapped address found!");
+ return STUN_USAGE_ICE_RETURN_SUCCESS;
+}
+
+static int
+stun_bind_error (StunAgent *agent, StunMessage *msg,
+ uint8_t *buf, size_t *plen, const StunMessage *req,
+ StunError code)
+{
+ size_t len = *plen;
+ int val;
+
+ *plen = 0;
+ stun_debug ("STUN Error Reply (buffer size: %u)...", (unsigned)len);
+
+ val = stun_agent_init_error (agent, msg, buf, len, req, code);
+ if (!val)
+ return val;
+
+ len = stun_agent_finish_message (agent, msg, NULL, 0);
+ if (len == 0)
+ return 0;
+
+ *plen = len;
+ stun_debug (" Error response (%u) of %u bytes", (unsigned)code,
+ (unsigned)*plen);
+ return 1;
+}
+
+StunUsageIceReturn
+stun_usage_ice_conncheck_create_reply (StunAgent *agent, StunMessage *req,
+ StunMessage *msg, uint8_t *buf, size_t *plen,
+ const struct sockaddr_storage *src, socklen_t srclen,
+ bool *control, uint64_t tie,
+ StunUsageIceCompatibility compatibility)
+{
+ const char *username = NULL;
+ uint16_t username_len;
+ size_t len = *plen;
+ uint64_t q;
+ StunMessageReturn val = STUN_MESSAGE_RETURN_SUCCESS;
+ StunUsageIceReturn ret = STUN_USAGE_ICE_RETURN_SUCCESS;
+
+
+#define err( code ) \
+ stun_bind_error (agent, msg, buf, &len, req, code); \
+ *plen = len
+
+ *plen = 0;
+ stun_debug ("STUN Reply (buffer size = %u)...", (unsigned)len);
+
+ if (stun_message_get_class (req) != STUN_REQUEST)
+ {
+ stun_debug (" Unhandled non-request (class %u) message.",
+ stun_message_get_class (req));
+ return STUN_USAGE_ICE_RETURN_INVALID_REQUEST;
+ }
+
+ if (stun_message_get_method (req) != STUN_BINDING)
+ {
+ stun_debug (" Bad request (method %u) message.",
+ stun_message_get_method (req));
+ err (STUN_ERROR_BAD_REQUEST);
+ return STUN_USAGE_ICE_RETURN_INVALID_METHOD;
+ }
+
+ /* Role conflict handling */
+ assert (control != NULL);
+ if (stun_message_find64 (req, *control ? STUN_ATTRIBUTE_ICE_CONTROLLING
+ : STUN_ATTRIBUTE_ICE_CONTROLLED, &q) == STUN_MESSAGE_RETURN_SUCCESS)
+ {
+ /* we have the ice-controlling/controlled attribute,
+ * and there's a role conflict
+ */
+ stun_debug ("STUN Role Conflict detected:");
+
+ /* According to ICE RFC 5245, section 7.2.1.1, we consider the four
+ * possible cases when a role conflict is detected: two cases are
+ * resolved by switching role locally, and the two other cases are
+ * handled by responding with a STUN error.
+ */
+ if ((tie < q && *control) || (tie >= q && !*control))
+ {
+ stun_debug (" switching role from \"controll%s\" to \"controll%s\"",
+ *control ? "ing" : "ed", *control ? "ed" : "ing");
+ *control = !*control;
+ ret = STUN_USAGE_ICE_RETURN_ROLE_CONFLICT;
+ }
+ else
+ {
+ stun_debug (" staying \"controll%s\" (sending error)",
+ *control ? "ing" : "ed");
+ err (STUN_ERROR_ROLE_CONFLICT);
+ return STUN_USAGE_ICE_RETURN_ROLE_CONFLICT;
+ }
+ } else {
+ if (stun_message_find64 (req, *control ? STUN_ATTRIBUTE_ICE_CONTROLLED
+ : STUN_ATTRIBUTE_ICE_CONTROLLING, &q) != STUN_MESSAGE_RETURN_SUCCESS)
+ {
+ /* we don't have the expected ice-controlling/controlled
+ * attribute
+ */
+ if (compatibility == STUN_USAGE_ICE_COMPATIBILITY_RFC5245 ||
+ compatibility == STUN_USAGE_ICE_COMPATIBILITY_MSICE2)
+ {
+ stun_debug ("STUN Role not specified by peer!");
+ }
+ }
+ }
+
+ if (stun_agent_init_response (agent, msg, buf, len, req) == FALSE) {
+ stun_debug ("Unable to create response");
+ goto failure;
+ }
+ if (compatibility == STUN_USAGE_ICE_COMPATIBILITY_MSN) {
+ union {
+ StunTransactionId transid;
+ uint32_t magic_cookie;
+ } conv;
+
+ stun_message_id (msg, conv.transid);
+
+ val = stun_message_append_xor_addr_full (msg, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
+ src, srclen, htonl (conv.magic_cookie));
+ } else if (stun_message_has_cookie (msg) &&
+ compatibility != STUN_USAGE_ICE_COMPATIBILITY_GOOGLE) {
+ val = stun_message_append_xor_addr (msg, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
+ src, srclen);
+ } else {
+ val = stun_message_append_addr (msg, STUN_ATTRIBUTE_MAPPED_ADDRESS,
+ (struct sockaddr *) src, srclen);
+ }
+
+ if (val != STUN_MESSAGE_RETURN_SUCCESS) {
+ stun_debug (" Mapped address problem: %d", val);
+ goto failure;
+ }
+
+ username = (const char *)stun_message_find (req,
+ STUN_ATTRIBUTE_USERNAME, &username_len);
+ if (username) {
+ val = stun_message_append_bytes (msg, STUN_ATTRIBUTE_USERNAME,
+ username, username_len);
+ }
+
+ if (val != STUN_MESSAGE_RETURN_SUCCESS) {
+ stun_debug ("Error appending username: %d", val);
+ goto failure;
+ }
+
+ if (compatibility == STUN_USAGE_ICE_COMPATIBILITY_MSICE2) {
+ val = stun_message_append32 (msg,
+ STUN_ATTRIBUTE_MS_IMPLEMENTATION_VERSION, 2);
+
+ if (val != STUN_MESSAGE_RETURN_SUCCESS) {
+ stun_debug ("Error appending implementation version: %d", val);
+ goto failure;
+ }
+ }
+
+ /* the stun agent will automatically use the password of the request */
+ len = stun_agent_finish_message (agent, msg, NULL, 0);
+ if (len == 0)
+ goto failure;
+
+ *plen = len;
+ stun_debug (" All done (response size: %u)", (unsigned)len);
+ return ret;
+
+failure:
+ assert (*plen == 0);
+ stun_debug (" Fatal error formatting Response: %d", val);
+
+ switch (val)
+ {
+ case STUN_MESSAGE_RETURN_NOT_ENOUGH_SPACE:
+ return STUN_USAGE_ICE_RETURN_MEMORY_ERROR;
+ case STUN_MESSAGE_RETURN_INVALID:
+ case STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS:
+ return STUN_USAGE_ICE_RETURN_INVALID_ADDRESS;
+ case STUN_MESSAGE_RETURN_SUCCESS:
+ assert (0); /* shouldn’t be reached */
+ case STUN_MESSAGE_RETURN_NOT_FOUND:
+ default:
+ return STUN_USAGE_ICE_RETURN_ERROR;
+ }
+}
+#undef err
+
+
+uint32_t stun_usage_ice_conncheck_priority (const StunMessage *msg)
+{
+ uint32_t value;
+
+ if (stun_message_find32 (msg, STUN_ATTRIBUTE_PRIORITY, &value)
+ != STUN_MESSAGE_RETURN_SUCCESS)
+ return 0;
+ return value;
+}
+
+
+bool stun_usage_ice_conncheck_use_candidate (const StunMessage *msg)
+{
+ return (stun_message_find_flag (msg,
+ STUN_ATTRIBUTE_USE_CANDIDATE) == STUN_MESSAGE_RETURN_SUCCESS);
+}
+
--- /dev/null
+
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2007-2009 Nokia Corporation. All rights reserved.
+ * Contact: Rémi Denis-Courmont
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ * Rémi Denis-Courmont, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef STUN_CONNCHECK_H
+# define STUN_CONNCHECK_H 1
+
+/**
+ * SECTION:ice
+ * @short_description: STUN ICE Usage
+ * @include: stun/usages/ice.h
+ * @stability: Stable
+ *
+ * The STUN ICE usage allows for easily creating and parsing STUN Binding
+ * requests and responses used for ICE connectivity checks. The API allows you
+ * to create a connectivity check message, parse a response or create a reply
+ * to an incoming connectivity check request.
+ */
+
+# include "stun/stunagent.h"
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+/**
+ * StunUsageIceCompatibility:
+ * @STUN_USAGE_ICE_COMPATIBILITY_RFC5245: The ICE compatibility with RFC 5245
+ * @STUN_USAGE_ICE_COMPATIBILITY_GOOGLE: The ICE compatibility with Google's
+ * implementation of ICE
+ * @STUN_USAGE_ICE_COMPATIBILITY_MSN: The ICE compatibility with MSN's
+ * implementation of ICE
+ * @STUN_USAGE_ICE_COMPATIBILITY_MSICE2: The ICE compatibility with [MS-ICE2]
+ * specification
+ * @STUN_USAGE_ICE_COMPATIBILITY_DRAFT19: The ICE compatibility with draft 19
+ * @STUN_USAGE_ICE_COMPATIBILITY_WLM2009: An alias
+ * for @STUN_USAGE_ICE_COMPATIBILITY_MSICE2
+ *
+ * This enum defines which compatibility modes this ICE usage can use
+ *
+ * <warning>@STUN_USAGE_ICE_COMPATIBILITY_DRAFT19 and
+ * @STUN_USAGE_ICE_COMPATIBILITY_WLM2009 are deprecated and should not be used
+ * in newly-written code. They are kept for compatibility reasons and represent
+ * the same compatibilities as @STUN_USAGE_ICE_COMPATIBILITY_RFC5245 and
+ * @STUN_USAGE_ICE_COMPATIBILITY_MSICE2 respectively.</warning>
+ */
+typedef enum {
+ STUN_USAGE_ICE_COMPATIBILITY_RFC5245,
+ STUN_USAGE_ICE_COMPATIBILITY_GOOGLE,
+ STUN_USAGE_ICE_COMPATIBILITY_MSN,
+ STUN_USAGE_ICE_COMPATIBILITY_MSICE2,
+ STUN_USAGE_ICE_COMPATIBILITY_DRAFT19 = STUN_USAGE_ICE_COMPATIBILITY_RFC5245,
+ STUN_USAGE_ICE_COMPATIBILITY_WLM2009 = STUN_USAGE_ICE_COMPATIBILITY_MSICE2,
+} StunUsageIceCompatibility;
+
+
+/**
+ * StunUsageIceReturn:
+ * @STUN_USAGE_ICE_RETURN_SUCCESS: The function succeeded
+ * @STUN_USAGE_ICE_RETURN_ERROR: There was an unspecified error
+ * @STUN_USAGE_ICE_RETURN_INVALID: The message is invalid for processing
+ * @STUN_USAGE_ICE_RETURN_ROLE_CONFLICT: A role conflict was detected
+ * @STUN_USAGE_ICE_RETURN_INVALID_REQUEST: The message is an not a request
+ * @STUN_USAGE_ICE_RETURN_INVALID_METHOD: The method of the request is invalid
+ * @STUN_USAGE_ICE_RETURN_MEMORY_ERROR: The buffer size is too small to hold
+ * the STUN reply
+ * @STUN_USAGE_ICE_RETURN_INVALID_ADDRESS: The mapped address argument has
+ * an invalid address family
+ * @STUN_USAGE_ICE_RETURN_NO_MAPPED_ADDRESS: The response is valid but no
+ * MAPPED-ADDRESS or XOR-MAPPED-ADDRESS attribute was found
+ *
+ * Return value of stun_usage_ice_conncheck_process() and
+ * stun_usage_ice_conncheck_create_reply() which allows you to see what
+ * status the function call returned.
+ */
+typedef enum {
+ STUN_USAGE_ICE_RETURN_SUCCESS,
+ STUN_USAGE_ICE_RETURN_ERROR,
+ STUN_USAGE_ICE_RETURN_INVALID,
+ STUN_USAGE_ICE_RETURN_ROLE_CONFLICT,
+ STUN_USAGE_ICE_RETURN_INVALID_REQUEST,
+ STUN_USAGE_ICE_RETURN_INVALID_METHOD,
+ STUN_USAGE_ICE_RETURN_MEMORY_ERROR,
+ STUN_USAGE_ICE_RETURN_INVALID_ADDRESS,
+ STUN_USAGE_ICE_RETURN_NO_MAPPED_ADDRESS,
+} StunUsageIceReturn;
+
+
+/**
+ * stun_usage_ice_conncheck_create:
+ * @agent: The #StunAgent to use to build the request
+ * @msg: The #StunMessage to build
+ * @buffer: The buffer to use for creating the #StunMessage
+ * @buffer_len: The size of the @buffer
+ * @username: The username to use in the request
+ * @username_len: The length of @username
+ * @password: The key to use for building the MESSAGE-INTEGRITY
+ * @password_len: The length of @password
+ * @cand_use: Set to %TRUE to append the USE-CANDIDATE flag to the request
+ * @controlling: Set to %TRUE if you are the controlling agent or set to
+ * %FALSE if you are the controlled agent.
+ * @priority: The value of the PRIORITY attribute
+ * @tie: The value of the tie-breaker to put in the ICE-CONTROLLED or
+ * ICE-CONTROLLING attribute
+ * @candidate_identifier: The foundation value to put in the
+ * CANDIDATE-IDENTIFIER attribute
+ * @compatibility: The compatibility mode to use for building the conncheck
+ * request
+ *
+ * Builds an ICE connectivity check STUN message.
+ * If the compatibility is not #STUN_USAGE_ICE_COMPATIBILITY_RFC5245, the
+ * @cand_use, @controlling, @priority and @tie arguments are not used.
+ * If the compatibility is not #STUN_USAGE_ICE_COMPATIBILITY_MSICE2, the
+ * @candidate_identifier argument is not used.
+ * Returns: The length of the message built.
+ */
+size_t
+stun_usage_ice_conncheck_create (StunAgent *agent, StunMessage *msg,
+ uint8_t *buffer, size_t buffer_len,
+ const uint8_t *username, const size_t username_len,
+ const uint8_t *password, const size_t password_len,
+ bool cand_use, bool controlling, uint32_t priority,
+ uint64_t tie, const char *candidate_identifier,
+ StunUsageIceCompatibility compatibility);
+
+
+/**
+ * stun_usage_ice_conncheck_process:
+ * @msg: The #StunMessage to process
+ * @addr: A pointer to a #sockaddr structure to fill with the mapped address
+ * that the STUN connectivity check response contains
+ * @addrlen: The length of @addr
+ * @compatibility: The compatibility mode to use for processing the conncheck
+ * response
+ *
+ * Process an ICE connectivity check STUN message and retrieve the
+ * mapped address from the message
+ * <para> See also stun_usage_ice_conncheck_priority() and
+ * stun_usage_ice_conncheck_use_candidate() </para>
+ * Returns: A #StunUsageIceReturn value
+ */
+StunUsageIceReturn stun_usage_ice_conncheck_process (StunMessage *msg,
+ struct sockaddr_storage *addr, socklen_t *addrlen,
+ StunUsageIceCompatibility compatibility);
+
+/**
+ * stun_usage_ice_conncheck_create_reply:
+ * @agent: The #StunAgent to use to build the response
+ * @req: The original STUN request to reply to
+ * @msg: The #StunMessage to build
+ * @buf: The buffer to use for creating the #StunMessage
+ * @plen: A pointer containing the size of the @buffer on input.
+ * Will contain the length of the message built on output.
+ * @src: A pointer to a #sockaddr structure containing the source address from
+ * which the request was received. Will be used as the mapped address in the
+ * response
+ * @srclen: The length of @addr
+ * @control: Set to %TRUE if you are the controlling agent or set to
+ * %FALSE if you are the controlled agent.
+ * @tie: The value of the tie-breaker to put in the ICE-CONTROLLED or
+ * ICE-CONTROLLING attribute
+ * @compatibility: The compatibility mode to use for building the conncheck
+ * response
+ *
+ * Tries to parse a STUN connectivity check request and builds a
+ * response accordingly.
+ <note>
+ <para>
+ In case of error, the @msg is filled with the appropriate error response
+ to be sent and the value of @plen is set to the size of that message.
+ If @plen has a size of 0, then no error response should be sent.
+ </para>
+ </note>
+ * Returns: A #StunUsageIceReturn value
+ */
+StunUsageIceReturn
+stun_usage_ice_conncheck_create_reply (StunAgent *agent, StunMessage *req,
+ StunMessage *msg, uint8_t *buf, size_t *plen,
+ const struct sockaddr_storage *src, socklen_t srclen,
+ bool *control, uint64_t tie,
+ StunUsageIceCompatibility compatibility);
+
+/**
+ * stun_usage_ice_conncheck_priority:
+ * @msg: The #StunMessage to parse
+ *
+ * Extracts the priority from a STUN message.
+ * Returns: host byte order priority, or 0 if not specified.
+ */
+uint32_t stun_usage_ice_conncheck_priority (const StunMessage *msg);
+
+/**
+ * stun_usage_ice_conncheck_use_candidate:
+ * @msg: The #StunMessage to parse
+ *
+ * Extracts the USE-CANDIDATE attribute flag from a STUN message.
+ * Returns: %TRUE if the flag is set, %FALSE if not.
+ */
+bool stun_usage_ice_conncheck_use_candidate (const StunMessage *msg);
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2007-2009 Nokia Corporation. All rights reserved.
+ * Contact: Rémi Denis-Courmont
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ * Rémi Denis-Courmont, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#else
+#include <unistd.h>
+#endif
+
+#include "timer.h"
+
+#include <stdlib.h> /* div() */
+
+/*
+ * Clock used throughout the STUN code.
+ * STUN requires a monotonic 1kHz clock to operate properly.
+ */
+static void stun_gettime (struct timeval *now)
+{
+#ifdef _WIN32
+ FILETIME ft;
+ unsigned long long *time64 = (unsigned long long *) &ft;
+
+ GetSystemTimeAsFileTime (&ft);
+
+ /* Convert from 100s of nanoseconds since 1601-01-01
+ * to Unix epoch. Yes, this is Y2038 unsafe.
+ */
+ *time64 -= (unsigned long long) 116444736000000000;
+ *time64 /= 10;
+
+ now->tv_sec = (long)(*time64 / 1000000);
+ now->tv_usec = *time64 % 1000000;
+#else
+#if defined (_POSIX_MONOTONIC_CLOCK) && (_POSIX_MONOTONIC_CLOCK >= 0)
+ struct timespec spec;
+ if (!clock_gettime (CLOCK_MONOTONIC, &spec)) {
+ now->tv_sec = spec.tv_sec;
+ now->tv_usec = spec.tv_nsec / 1000;
+ } else
+#endif
+ { // fallback to wall clock
+ gettimeofday (now, NULL);
+ }
+#endif
+}
+
+
+static void add_delay (struct timeval *ts, unsigned delay)
+{
+ /* Delay is in ms. */
+ ts->tv_sec += delay / 1000;
+ ts->tv_usec += (delay % 1000) * 1000;
+
+ while (ts->tv_usec > 1000000)
+ {
+ ts->tv_usec -= 1000000;
+ ts->tv_sec++;
+ }
+}
+
+
+void stun_timer_start (StunTimer *timer, unsigned int initial_timeout,
+ unsigned int max_retransmissions)
+{
+ stun_gettime (&timer->deadline);
+ timer->retransmissions = 1;
+ timer->delay = initial_timeout;
+ timer->max_retransmissions = max_retransmissions;
+ add_delay (&timer->deadline, timer->delay);
+}
+
+
+void stun_timer_start_reliable (StunTimer *timer, unsigned int initial_timeout)
+{
+ stun_timer_start (timer, initial_timeout, 0);
+}
+
+
+
+unsigned stun_timer_remainder (const StunTimer *timer)
+{
+ unsigned delay;
+ struct timeval now;
+
+ stun_gettime (&now);
+ if (now.tv_sec > timer->deadline.tv_sec)
+ return 0;
+
+ delay = timer->deadline.tv_sec - now.tv_sec;
+ if ((delay == 0) && (now.tv_usec >= timer->deadline.tv_usec))
+ return 0;
+
+ delay *= 1000;
+ delay += ((signed)(timer->deadline.tv_usec - now.tv_usec)) / 1000;
+ return delay;
+}
+
+
+StunUsageTimerReturn stun_timer_refresh (StunTimer *timer)
+{
+ unsigned delay = stun_timer_remainder (timer);
+ if (delay == 0)
+ {
+ if (timer->retransmissions >= timer->max_retransmissions)
+ return STUN_USAGE_TIMER_RETURN_TIMEOUT;
+
+ if (timer->retransmissions == timer->max_retransmissions - 1)
+ timer->delay = timer->delay / 2;
+ else
+ timer->delay = timer->delay * 2;
+ add_delay (&timer->deadline, timer->delay);
+ timer->retransmissions++;
+ return STUN_USAGE_TIMER_RETURN_RETRANSMIT;
+ }
+
+ return STUN_USAGE_TIMER_RETURN_SUCCESS;
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2007-2009 Nokia Corporation. All rights reserved.
+ * Contact: Rémi Denis-Courmont
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ * Rémi Denis-Courmont, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef STUN_TIMER_H
+# define STUN_TIMER_H 1
+
+/**
+ * SECTION:timer
+ * @short_description: STUN timer Usage
+ * @include: stun/usages/timer.h
+ * @stability: Stable
+ *
+ * The STUN timer usage is a set of helpful utility functions that allows you
+ * to easily track when a STUN message should be retransmitted or considered
+ * as timed out.
+ *
+ *
+ <example>
+ <title>Simple example on how to use the timer usage</title>
+ <programlisting>
+ StunTimer timer;
+ unsigned remainder;
+ StunUsageTimerReturn ret;
+
+ // Build the message, etc..
+ ...
+
+ // Send the message and start the timer
+ send(socket, request, sizeof(request));
+ stun_timer_start(&timer, STUN_TIMER_DEFAULT_TIMEOUT,
+ STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS);
+
+ // Loop until we get the response
+ for (;;) {
+ remainder = stun_timer_remainder(&timer);
+
+ // Poll the socket until data is received or the timer expires
+ if (poll (&pollfd, 1, delay) <= 0) {
+ // Time out and no response was received
+ ret = stun_timer_refresh (&timer);
+ if (ret == STUN_USAGE_TIMER_RETURN_TIMEOUT) {
+ // Transaction timed out
+ break;
+ } else if (ret == STUN_USAGE_TIMER_RETURN_RETRANSMIT) {
+ // A retransmission is necessary
+ send(socket, request, sizeof(request));
+ continue;
+ } else if (ret == STUN_USAGE_TIMER_RETURN_SUCCESS) {
+ // The refresh succeeded and nothing has to be done, continue polling
+ continue;
+ }
+ } else {
+ // We received a response, read it
+ recv(socket, response, sizeof(response));
+ break;
+ }
+ }
+
+ // Check if the transaction timed out or not
+ if (ret == STUN_USAGE_TIMER_RETURN_TIMEOUT) {
+ // do whatever needs to be done in that case
+ } else {
+ // Parse the response
+ }
+
+ </programlisting>
+ </example>
+ */
+
+#ifdef _WIN32
+#include <winsock2.h>
+#else
+# include <sys/types.h>
+# include <sys/time.h>
+# include <time.h>
+#endif
+
+
+/**
+ * StunTimer:
+ *
+ * An opaque structure representing a STUN transaction retransmission timer
+ */
+typedef struct stun_timer_s StunTimer;
+
+struct stun_timer_s {
+ struct timeval deadline;
+ unsigned delay;
+ unsigned retransmissions;
+ unsigned max_retransmissions;
+};
+
+
+/**
+ * STUN_TIMER_DEFAULT_TIMEOUT:
+ *
+ * The default intial timeout to use for the timer
+ * RFC recommendds 500, but it's ridiculous, 50ms is known to work in most
+ * cases as it is also what is used by SIP style VoIP when sending A-Law and
+ * mu-Law audio, so 200ms should be hyper safe. With an initial timeout
+ * of 200ms, a default of 7 transmissions, the last timeout will be
+ * 16 * 200ms, and we expect to receive a response from the stun server
+ * before (1 + 2 + 4 + 8 + 16 + 32 + 16) * 200ms = 15200 ms after the initial
+ * stun request has been sent.
+ */
+#define STUN_TIMER_DEFAULT_TIMEOUT 200
+
+/**
+ * STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS:
+ *
+ * The default maximum retransmissions allowed before a timer decides to timeout
+ */
+#define STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS 7
+
+/**
+ * STUN_TIMER_DEFAULT_RELIABLE_TIMEOUT:
+ *
+ * The default intial timeout to use for a reliable timer
+ */
+#define STUN_TIMER_DEFAULT_RELIABLE_TIMEOUT 7900
+
+/**
+ * StunUsageTimerReturn:
+ * @STUN_USAGE_TIMER_RETURN_SUCCESS: The timer was refreshed successfully
+ * and there is nothing to be done
+ * @STUN_USAGE_TIMER_RETURN_RETRANSMIT: The timer expired and the message
+ * should be retransmitted now.
+ * @STUN_USAGE_TIMER_RETURN_TIMEOUT: The timer expired as well as all the
+ * retransmissions, the transaction timed out
+ *
+ * Return value of stun_usage_timer_refresh() which provides you with status
+ * information on the timer.
+ */
+typedef enum {
+ STUN_USAGE_TIMER_RETURN_SUCCESS,
+ STUN_USAGE_TIMER_RETURN_RETRANSMIT,
+ STUN_USAGE_TIMER_RETURN_TIMEOUT
+} StunUsageTimerReturn;
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+
+/**
+ * stun_timer_start:
+ * @timer: The #StunTimer to start
+ * @initial_timeout: The initial timeout to use before the first retransmission
+ * @max_retransmissions: The maximum number of transmissions before the
+ * #StunTimer times out
+ *
+ * Starts a STUN transaction retransmission timer.
+ * This should be called as soon as you send the message for the first time on
+ * a UDP socket.
+ * The timeout before the next retransmission is set to @initial_timeout, then
+ * each time a packet is retransmited, that timeout will be doubled, until the
+ * @max_retransmissions retransmissions limit is reached.
+ * <para>
+ * To determine the total timeout value, one can use the following equation :
+ <programlisting>
+ total_timeout = initial_timeout * (2^(max_retransmissions + 1) - 1);
+ </programlisting>
+ * </para>
+ *
+ * See also: #STUN_TIMER_DEFAULT_TIMEOUT
+ *
+ * See also: #STUN_TIMER_DEFAULT_MAX_RETRANSMISSIONS
+ */
+void stun_timer_start (StunTimer *timer, unsigned int initial_timeout,
+ unsigned int max_retransmissions);
+
+/**
+ * stun_timer_start_reliable:
+ * @timer: The #StunTimer to start
+ * @initial_timeout: The initial timeout to use before the first retransmission
+ *
+ * Starts a STUN transaction retransmission timer for a reliable transport.
+ * This should be called as soon as you send the message for the first time on
+ * a TCP socket
+ */
+void stun_timer_start_reliable (StunTimer *timer, unsigned int initial_timeout);
+
+/**
+ * stun_timer_refresh:
+ * @timer: The #StunTimer to refresh
+ *
+ * Updates a STUN transaction retransmission timer.
+ * Returns: A #StunUsageTimerReturn telling you what to do next
+ */
+StunUsageTimerReturn stun_timer_refresh (StunTimer *timer);
+
+/**
+ * stun_timer_remainder:
+ * @timer: The #StunTimer to query
+ *
+ * Query the timer on the time left before the next refresh should be done
+ * Returns: The time remaining for the timer to expire in milliseconds
+ */
+unsigned stun_timer_remainder (const StunTimer *timer);
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif /* !STUN_TIMER_H */
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2007-2009 Nokia Corporation. All rights reserved.
+ * Contact: Rémi Denis-Courmont
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ * Rémi Denis-Courmont, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef _WIN32
+#include <winsock2.h>
+#else
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif
+
+#include "stun/stunagent.h"
+#include "turn.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+
+
+
+#define REQUESTED_PROPS_E 0x80000000
+#define REQUESTED_PROPS_R 0x40000000
+#define REQUESTED_PROPS_P 0x20000000
+
+
+#define STUN_ATTRIBUTE_MSN_MAPPED_ADDRESS 0x8000
+
+
+#define TURN_REQUESTED_TRANSPORT_UDP 0x11000000
+
+/** Non-blocking mode STUN TURN usage */
+
+size_t stun_usage_turn_create (StunAgent *agent, StunMessage *msg,
+ uint8_t *buffer, size_t buffer_len,
+ StunMessage *previous_response,
+ StunUsageTurnRequestPorts request_props,
+ int32_t bandwidth, int32_t lifetime,
+ uint8_t *username, size_t username_len,
+ uint8_t *password, size_t password_len,
+ StunUsageTurnCompatibility compatibility)
+{
+ stun_agent_init_request (agent, msg, buffer, buffer_len, STUN_ALLOCATE);
+
+ if (compatibility == STUN_USAGE_TURN_COMPATIBILITY_DRAFT9 ||
+ compatibility == STUN_USAGE_TURN_COMPATIBILITY_RFC5766) {
+ if (stun_message_append32 (msg, STUN_ATTRIBUTE_REQUESTED_TRANSPORT,
+ TURN_REQUESTED_TRANSPORT_UDP) != STUN_MESSAGE_RETURN_SUCCESS)
+ return 0;
+ if (bandwidth >= 0) {
+ if (stun_message_append32 (msg, STUN_ATTRIBUTE_BANDWIDTH, bandwidth) !=
+ STUN_MESSAGE_RETURN_SUCCESS)
+ return 0;
+ }
+ } else {
+ if (stun_message_append32 (msg, STUN_ATTRIBUTE_MAGIC_COOKIE,
+ TURN_MAGIC_COOKIE) != STUN_MESSAGE_RETURN_SUCCESS)
+ return 0;
+ }
+
+ if (compatibility == STUN_USAGE_TURN_COMPATIBILITY_OC2007) {
+ stun_message_append32(msg, STUN_ATTRIBUTE_MS_VERSION, 1);
+ }
+
+ if (lifetime >= 0) {
+ if (stun_message_append32 (msg, STUN_ATTRIBUTE_LIFETIME, lifetime) !=
+ STUN_MESSAGE_RETURN_SUCCESS)
+ return 0;
+ }
+
+ if ((compatibility == STUN_USAGE_TURN_COMPATIBILITY_DRAFT9 ||
+ compatibility == STUN_USAGE_TURN_COMPATIBILITY_RFC5766) &&
+ request_props != STUN_USAGE_TURN_REQUEST_PORT_NORMAL) {
+ uint32_t req = 0;
+
+
+ if (request_props & STUN_USAGE_TURN_REQUEST_PORT_EVEN_AND_RESERVE) {
+ req |= REQUESTED_PROPS_R;
+ req |= REQUESTED_PROPS_E;
+ } else if (request_props & STUN_USAGE_TURN_REQUEST_PORT_EVEN) {
+ req |= REQUESTED_PROPS_E;
+ }
+
+ if (stun_message_append32 (msg, STUN_ATTRIBUTE_REQUESTED_PORT_PROPS,
+ req) != STUN_MESSAGE_RETURN_SUCCESS)
+ return 0;
+ }
+
+ if (previous_response) {
+ uint8_t *realm;
+ uint8_t *nonce;
+ uint64_t reservation;
+ uint16_t len;
+
+ realm = (uint8_t *) stun_message_find (previous_response,
+ STUN_ATTRIBUTE_REALM, &len);
+ if (realm != NULL) {
+ if (stun_message_append_bytes (msg, STUN_ATTRIBUTE_REALM, realm, len) !=
+ STUN_MESSAGE_RETURN_SUCCESS)
+ return 0;
+ }
+ nonce = (uint8_t *) stun_message_find (previous_response,
+ STUN_ATTRIBUTE_NONCE, &len);
+ if (nonce != NULL) {
+ if (stun_message_append_bytes (msg, STUN_ATTRIBUTE_NONCE, nonce, len) !=
+ STUN_MESSAGE_RETURN_SUCCESS)
+ return 0;
+ }
+ if (stun_message_find64 (previous_response,
+ STUN_ATTRIBUTE_RESERVATION_TOKEN,
+ &reservation) == STUN_MESSAGE_RETURN_SUCCESS) {
+ if (stun_message_append64 (msg, STUN_ATTRIBUTE_RESERVATION_TOKEN,
+ reservation) != STUN_MESSAGE_RETURN_SUCCESS)
+ return 0;
+ }
+ }
+
+ if (username != NULL && username_len > 0 &&
+ (agent->usage_flags & STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS ||
+ previous_response)) {
+ if (stun_message_append_bytes (msg, STUN_ATTRIBUTE_USERNAME,
+ username, username_len) != STUN_MESSAGE_RETURN_SUCCESS)
+ return 0;
+ }
+
+ return stun_agent_finish_message (agent, msg, password, password_len);
+}
+
+size_t stun_usage_turn_create_refresh (StunAgent *agent, StunMessage *msg,
+ uint8_t *buffer, size_t buffer_len,
+ StunMessage *previous_response, int32_t lifetime,
+ uint8_t *username, size_t username_len,
+ uint8_t *password, size_t password_len,
+ StunUsageTurnCompatibility compatibility)
+{
+
+ if (compatibility != STUN_USAGE_TURN_COMPATIBILITY_DRAFT9 &&
+ compatibility != STUN_USAGE_TURN_COMPATIBILITY_RFC5766) {
+ return stun_usage_turn_create (agent, msg, buffer, buffer_len,
+ previous_response, STUN_USAGE_TURN_REQUEST_PORT_NORMAL, 0, lifetime,
+ username, username_len, password, password_len, compatibility);
+ }
+
+ stun_agent_init_request (agent, msg, buffer, buffer_len, STUN_REFRESH);
+ if (lifetime >= 0) {
+ if (stun_message_append32 (msg, STUN_ATTRIBUTE_LIFETIME, lifetime) !=
+ STUN_MESSAGE_RETURN_SUCCESS)
+ return 0;
+ }
+
+ if (previous_response) {
+ uint8_t *realm;
+ uint8_t *nonce;
+ uint16_t len;
+
+ realm = (uint8_t *) stun_message_find (previous_response,
+ STUN_ATTRIBUTE_REALM, &len);
+ if (realm != NULL) {
+ if (stun_message_append_bytes (msg, STUN_ATTRIBUTE_REALM, realm, len) !=
+ STUN_MESSAGE_RETURN_SUCCESS)
+ return 0;
+ }
+ nonce = (uint8_t *) stun_message_find (previous_response,
+ STUN_ATTRIBUTE_NONCE, &len);
+ if (nonce != NULL) {
+ if (stun_message_append_bytes (msg, STUN_ATTRIBUTE_NONCE, nonce, len) !=
+ STUN_MESSAGE_RETURN_SUCCESS)
+ return 0;
+ }
+ }
+
+
+ if (username != NULL && username_len > 0 &&
+ (agent->usage_flags & STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS ||
+ previous_response)) {
+ if (stun_message_append_bytes (msg, STUN_ATTRIBUTE_USERNAME,
+ username, username_len) != STUN_MESSAGE_RETURN_SUCCESS)
+ return 0;
+ }
+
+
+ return stun_agent_finish_message (agent, msg, password, password_len);
+}
+
+size_t stun_usage_turn_create_permission (StunAgent *agent, StunMessage *msg,
+ uint8_t *buffer, size_t buffer_len,
+ uint8_t *username, size_t username_len,
+ uint8_t *password, size_t password_len,
+ uint8_t *realm, size_t realm_len,
+ uint8_t *nonce, size_t nonce_len,
+ struct sockaddr_storage *peer,
+ StunUsageTurnCompatibility compatibility)
+{
+ if (!peer)
+ return 0;
+
+ stun_agent_init_request (agent, msg, buffer, buffer_len,
+ STUN_CREATEPERMISSION);
+
+ /* PEER address */
+ if (stun_message_append_xor_addr (msg, STUN_ATTRIBUTE_XOR_PEER_ADDRESS,
+ peer, sizeof(*peer)) != STUN_MESSAGE_RETURN_SUCCESS) {
+ return 0;
+ }
+
+ /* nonce */
+ if (nonce != NULL) {
+ if (stun_message_append_bytes (msg, STUN_ATTRIBUTE_NONCE,
+ nonce, nonce_len) != STUN_MESSAGE_RETURN_SUCCESS)
+ return 0;
+ }
+
+ /* realm */
+ if (realm != NULL) {
+ if (stun_message_append_bytes (msg, STUN_ATTRIBUTE_REALM,
+ realm, realm_len) != STUN_MESSAGE_RETURN_SUCCESS)
+ return 0;
+ }
+
+ /* username */
+ if (username != NULL &&
+ (agent->usage_flags & STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS ||
+ (nonce != NULL && realm != NULL))) {
+ if (stun_message_append_bytes (msg, STUN_ATTRIBUTE_USERNAME,
+ username, username_len) != STUN_MESSAGE_RETURN_SUCCESS)
+ return 0;
+ }
+
+ return stun_agent_finish_message (agent, msg, password, password_len);
+}
+
+
+StunUsageTurnReturn stun_usage_turn_process (StunMessage *msg,
+ struct sockaddr_storage *relay_addr, socklen_t *relay_addrlen,
+ struct sockaddr_storage *addr, socklen_t *addrlen,
+ struct sockaddr_storage *alternate_server, socklen_t *alternate_server_len,
+ uint32_t *bandwidth, uint32_t *lifetime,
+ StunUsageTurnCompatibility compatibility)
+{
+ int val, code = -1;
+ StunUsageTurnReturn ret = STUN_USAGE_TURN_RETURN_RELAY_SUCCESS;
+
+ if (stun_message_get_method (msg) != STUN_ALLOCATE)
+ return STUN_USAGE_TURN_RETURN_INVALID;
+
+ switch (stun_message_get_class (msg))
+ {
+ case STUN_REQUEST:
+ case STUN_INDICATION:
+ return STUN_USAGE_TURN_RETURN_INVALID;
+
+ case STUN_RESPONSE:
+ break;
+
+ case STUN_ERROR:
+ if (stun_message_find_error (msg, &code) != STUN_MESSAGE_RETURN_SUCCESS) {
+ /* missing ERROR-CODE: ignore message */
+ return STUN_USAGE_TURN_RETURN_INVALID;
+ }
+
+ /* NOTE: currently we ignore unauthenticated messages if the context
+ * is authenticated, for security reasons. */
+ stun_debug (" STUN error message received (code: %d)", code);
+
+ /* ALTERNATE-SERVER mechanism */
+ if (compatibility == STUN_USAGE_TURN_COMPATIBILITY_OC2007 &&
+ alternate_server && alternate_server_len &&
+ stun_message_find_addr (msg, STUN_ATTRIBUTE_MS_ALTERNATE_SERVER,
+ alternate_server,
+ alternate_server_len) == STUN_MESSAGE_RETURN_SUCCESS) {
+ stun_debug ("Found alternate server");
+ /* The ALTERNATE_SERVER will always be returned by the MS turn server.
+ * We need to check if the ALTERNATE_SERVER is the same as the current
+ * server to decide whether we need to switch servers or not.
+ */
+ }
+ if ((code / 100) == 3) {
+ if (alternate_server && alternate_server_len) {
+ if (stun_message_find_addr (msg, STUN_ATTRIBUTE_ALTERNATE_SERVER,
+ alternate_server, alternate_server_len) !=
+ STUN_MESSAGE_RETURN_SUCCESS) {
+ stun_debug (" Unexpectedly missing ALTERNATE-SERVER attribute");
+ return STUN_USAGE_TURN_RETURN_ERROR;
+ }
+ } else {
+ if (!stun_message_has_attribute (msg,
+ STUN_ATTRIBUTE_ALTERNATE_SERVER)) {
+ stun_debug (" Unexpectedly missing ALTERNATE-SERVER attribute");
+ return STUN_USAGE_TURN_RETURN_ERROR;
+ }
+ }
+
+ stun_debug ("Found alternate server");
+ return STUN_USAGE_TURN_RETURN_ALTERNATE_SERVER;
+
+ }
+ return STUN_USAGE_TURN_RETURN_ERROR;
+
+ default:
+ /* Fall through. */
+ break;
+ }
+
+ stun_debug ("Received %u-bytes STUN message", stun_message_length (msg));
+
+ if (compatibility == STUN_USAGE_TURN_COMPATIBILITY_DRAFT9 ||
+ compatibility == STUN_USAGE_TURN_COMPATIBILITY_RFC5766) {
+ val = stun_message_find_xor_addr (msg,
+ STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, addr, addrlen);
+
+ if (val == STUN_MESSAGE_RETURN_SUCCESS)
+ ret = STUN_USAGE_TURN_RETURN_MAPPED_SUCCESS;
+ val = stun_message_find_xor_addr (msg,
+ STUN_ATTRIBUTE_RELAY_ADDRESS, relay_addr, relay_addrlen);
+ if (val != STUN_MESSAGE_RETURN_SUCCESS) {
+ stun_debug (" No RELAYED-ADDRESS: %d", val);
+ return STUN_USAGE_TURN_RETURN_ERROR;
+ }
+ } else if (compatibility == STUN_USAGE_TURN_COMPATIBILITY_GOOGLE) {
+ val = stun_message_find_addr (msg,
+ STUN_ATTRIBUTE_MAPPED_ADDRESS, relay_addr, relay_addrlen);
+ if (val != STUN_MESSAGE_RETURN_SUCCESS) {
+ stun_debug (" No MAPPED-ADDRESS: %d", val);
+ return STUN_USAGE_TURN_RETURN_ERROR;
+ }
+ } else if (compatibility == STUN_USAGE_TURN_COMPATIBILITY_MSN) {
+ val = stun_message_find_addr (msg,
+ STUN_ATTRIBUTE_MSN_MAPPED_ADDRESS, addr, addrlen);
+
+ if (val == STUN_MESSAGE_RETURN_SUCCESS)
+ ret = STUN_USAGE_TURN_RETURN_MAPPED_SUCCESS;
+
+ val = stun_message_find_addr (msg,
+ STUN_ATTRIBUTE_MAPPED_ADDRESS, relay_addr, relay_addrlen);
+ if (val != STUN_MESSAGE_RETURN_SUCCESS) {
+ stun_debug (" No MAPPED-ADDRESS: %d", val);
+ return STUN_USAGE_TURN_RETURN_ERROR;
+ }
+ } else if (compatibility == STUN_USAGE_TURN_COMPATIBILITY_OC2007) {
+ union {
+ StunTransactionId id;
+ uint32_t u32[4];
+ } transid;
+ uint32_t magic_cookie;
+
+ stun_message_id (msg, transid.id);
+ magic_cookie = transid.u32[0];
+
+ val = stun_message_find_xor_addr_full (msg,
+ STUN_ATTRIBUTE_MS_XOR_MAPPED_ADDRESS, addr, addrlen,
+ htonl (magic_cookie));
+
+ if (val == STUN_MESSAGE_RETURN_SUCCESS)
+ ret = STUN_USAGE_TURN_RETURN_MAPPED_SUCCESS;
+
+ val = stun_message_find_addr (msg,
+ STUN_ATTRIBUTE_MAPPED_ADDRESS, relay_addr, relay_addrlen);
+ if (val != STUN_MESSAGE_RETURN_SUCCESS) {
+ stun_debug (" No MAPPED-ADDRESS: %d", val);
+ return STUN_USAGE_TURN_RETURN_ERROR;
+ }
+ }
+
+ stun_message_find32 (msg, STUN_ATTRIBUTE_LIFETIME, lifetime);
+ stun_message_find32 (msg, STUN_ATTRIBUTE_BANDWIDTH, bandwidth);
+
+ stun_debug (" Mapped address found!");
+ return ret;
+
+}
+
+
+
+StunUsageTurnReturn stun_usage_turn_refresh_process (StunMessage *msg,
+ uint32_t *lifetime, StunUsageTurnCompatibility compatibility)
+{
+ int code = -1;
+ StunUsageTurnReturn ret = STUN_USAGE_TURN_RETURN_RELAY_SUCCESS;
+
+ if (compatibility == STUN_USAGE_TURN_COMPATIBILITY_DRAFT9 ||
+ compatibility == STUN_USAGE_TURN_COMPATIBILITY_RFC5766) {
+ if (stun_message_get_method (msg) != STUN_REFRESH)
+ return STUN_USAGE_TURN_RETURN_INVALID;
+ } else {
+ if (stun_message_get_method (msg) != STUN_ALLOCATE)
+ return STUN_USAGE_TURN_RETURN_INVALID;
+ }
+
+ switch (stun_message_get_class (msg))
+ {
+ case STUN_REQUEST:
+ case STUN_INDICATION:
+ return STUN_USAGE_TURN_RETURN_INVALID;
+
+ case STUN_RESPONSE:
+ break;
+
+ case STUN_ERROR:
+ if (stun_message_find_error (msg, &code) != STUN_MESSAGE_RETURN_SUCCESS) {
+ /* missing ERROR-CODE: ignore message */
+ return STUN_USAGE_TURN_RETURN_INVALID;
+ }
+
+ return STUN_USAGE_TURN_RETURN_ERROR;
+
+ default:
+ /* Fall through. */
+ break;
+ }
+
+ stun_message_find32 (msg, STUN_ATTRIBUTE_LIFETIME, lifetime);
+
+ stun_debug ("TURN Refresh successful!");
+ return ret;
+
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2007-2009 Nokia Corporation. All rights reserved.
+ * Contact: Rémi Denis-Courmont
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ * Rémi Denis-Courmont, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef STUN_TURN_H
+# define STUN_TURN_H 1
+
+/**
+ * SECTION:turn
+ * @short_description: TURN Allocation Usage
+ * @include: stun/usages/turn.h
+ * @stability: Stable
+ *
+ * The STUN TURN usage allows for easily creating and parsing STUN Allocate
+ * requests and responses used for TURN. The API allows you to create a new
+ * allocation or refresh an existing one as well as to parse a response to
+ * an allocate or refresh request.
+ */
+
+
+#ifdef _WIN32
+# include "../win32_common.h"
+#else
+# include <stdbool.h>
+# include <stdint.h>
+#endif
+
+#ifdef _WIN32
+#include <winsock2.h>
+#else
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif
+
+# include "stun/stunagent.h"
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+/**
+ * StunUsageTurnRequestPorts:
+ * @STUN_USAGE_TURN_REQUEST_PORT_NORMAL: Request a normal port
+ * @STUN_USAGE_TURN_REQUEST_PORT_EVEN: Request an even port
+ * @STUN_USAGE_TURN_REQUEST_PORT_EVEN_AND_RESERVE: Request an even port and
+ * reserve the next higher port
+ *
+ * This enum is used to specify which port configuration you want when creating
+ * a new Allocation
+ */
+typedef enum {
+ STUN_USAGE_TURN_REQUEST_PORT_NORMAL = 0,
+ STUN_USAGE_TURN_REQUEST_PORT_EVEN = 1,
+ STUN_USAGE_TURN_REQUEST_PORT_EVEN_AND_RESERVE = 2
+} StunUsageTurnRequestPorts;
+
+/**
+ * StunUsageTurnCompatibility:
+ * @STUN_USAGE_TURN_COMPATIBILITY_DRAFT9: Use the specification compatible with
+ * TURN Draft 09
+ * @STUN_USAGE_TURN_COMPATIBILITY_GOOGLE: Use the specification compatible with
+ * Google Talk's relay server
+ * @STUN_USAGE_TURN_COMPATIBILITY_MSN: Use the specification compatible with
+ * MSN TURN servers
+ * @STUN_USAGE_TURN_COMPATIBILITY_OC2007: Use the specification compatible with
+ * Microsoft Office Communicator 2007
+ * @STUN_USAGE_TURN_COMPATIBILITY_RFC5766: Use the specification compatible with
+ * RFC 5766 (the final, canonical TURN standard)
+ *
+ * Specifies which TURN specification compatibility to use
+ */
+typedef enum {
+ STUN_USAGE_TURN_COMPATIBILITY_DRAFT9,
+ STUN_USAGE_TURN_COMPATIBILITY_GOOGLE,
+ STUN_USAGE_TURN_COMPATIBILITY_MSN,
+ STUN_USAGE_TURN_COMPATIBILITY_OC2007,
+ STUN_USAGE_TURN_COMPATIBILITY_RFC5766,
+} StunUsageTurnCompatibility;
+
+/**
+ * StunUsageTurnReturn:
+ * @STUN_USAGE_TURN_RETURN_RELAY_SUCCESS: The response was successful and a relay
+ * address is provided
+ * @STUN_USAGE_TURN_RETURN_MAPPED_SUCCESS: The response was successful and a
+ * relay address as well as a mapped address are provided
+ * @STUN_USAGE_TURN_RETURN_ERROR: The response resulted in an error
+ * @STUN_USAGE_TURN_RETURN_INVALID: The response is not a valid response
+ * @STUN_USAGE_TURN_RETURN_ALTERNATE_SERVER: The server requests the message
+ * to be sent to an alternate server
+ *
+ * Return value of stun_usage_turn_process() and
+ * stun_usage_turn_refresh_process() which allows you to see what status the
+ * function call returned.
+ */
+typedef enum {
+ STUN_USAGE_TURN_RETURN_RELAY_SUCCESS,
+ STUN_USAGE_TURN_RETURN_MAPPED_SUCCESS,
+ STUN_USAGE_TURN_RETURN_ERROR,
+ STUN_USAGE_TURN_RETURN_INVALID,
+ STUN_USAGE_TURN_RETURN_ALTERNATE_SERVER,
+} StunUsageTurnReturn;
+
+
+/**
+ * stun_usage_turn_create:
+ * @agent: The #StunAgent to use to build the request
+ * @msg: The #StunMessage to build
+ * @buffer: The buffer to use for creating the #StunMessage
+ * @buffer_len: The size of the @buffer
+ * @previous_response: If this is the first request you are sending, set this
+ * argument to NULL, if it's a subsequent request you are building, then set this
+ * argument to the response you have received. This argument is used for building
+ * long term credentials (using the REALM and NONCE attributes) as well as for
+ * getting the RESERVATION-TOKEN attribute when you previously requested an
+ * allocation which reserved two ports
+ * @request_ports: Specify how you want to request the allocated port(s).
+ * This is only used if the compatibility is set to
+ * #STUN_USAGE_TURN_COMPATIBILITY_DRAFT9
+ * <para>See #StunUsageTurnRequestPorts </para>
+ * @bandwidth: The bandwidth to request from the server for the allocation. If
+ * this value is negative, then no BANDWIDTH attribute is added to the request.
+ * This is only used if the compatibility is set to
+ * #STUN_USAGE_TURN_COMPATIBILITY_DRAFT9
+ * @lifetime: The lifetime of the allocation to request from the server. If
+ * this value is negative, then no LIFETIME attribute is added to the request.
+ * This is only used if the compatibility is set to
+ * #STUN_USAGE_TURN_COMPATIBILITY_DRAFT9
+ * @username: The username to use in the request
+ * @username_len: The length of @username
+ * @password: The key to use for building the MESSAGE-INTEGRITY
+ * @password_len: The length of @password
+ * @compatibility: The compatibility mode to use for building the Allocation
+ * request
+ *
+ * Create a new TURN Allocation request
+ * Returns: The length of the message to send
+ */
+size_t stun_usage_turn_create (StunAgent *agent, StunMessage *msg,
+ uint8_t *buffer, size_t buffer_len,
+ StunMessage *previous_response,
+ StunUsageTurnRequestPorts request_ports,
+ int32_t bandwidth, int32_t lifetime,
+ uint8_t *username, size_t username_len,
+ uint8_t *password, size_t password_len,
+ StunUsageTurnCompatibility compatibility);
+
+/**
+ * stun_usage_turn_create_refresh:
+ * @agent: The #StunAgent to use to build the request
+ * @msg: The #StunMessage to build
+ * @buffer: The buffer to use for creating the #StunMessage
+ * @buffer_len: The size of the @buffer
+ * @previous_response: If this is the first request you are sending, set this
+ * argument to NULL, if it's a subsequent request you are building, then set this
+ * argument to the response you have received. This argument is used for building
+ * long term credentials (using the REALM and NONCE attributes)
+ * @lifetime: The lifetime of the allocation to request from the server. If
+ * this value is negative, then no LIFETIME attribute is added to the request.
+ * This is only used if the compatibility is set to
+ * #STUN_USAGE_TURN_COMPATIBILITY_DRAFT9
+ * @username: The username to use in the request
+ * @username_len: The length of @username
+ * @password: The key to use for building the MESSAGE-INTEGRITY
+ * @password_len: The length of @password
+ * @compatibility: The compatibility mode to use for building the Allocation
+ * request
+ *
+ * Create a new TURN Refresh request
+ * Returns: The length of the message to send
+ */
+size_t stun_usage_turn_create_refresh (StunAgent *agent, StunMessage *msg,
+ uint8_t *buffer, size_t buffer_len,
+ StunMessage *previous_response, int32_t lifetime,
+ uint8_t *username, size_t username_len,
+ uint8_t *password, size_t password_len,
+ StunUsageTurnCompatibility compatibility);
+
+/**
+ * stun_usage_turn_create_permission:
+ * @agent: The #StunAgent to use to build the request
+ * @msg: The #StunMessage to build
+ * @buffer: The buffer to use for creating the #StunMessage
+ * @buffer_len: The size of the @buffer
+ * @username: The username to use in the request
+ * @username_len: The length of @username
+ * @password: The key to use for building the MESSAGE-INTEGRITY
+ * @password_len: The length of @password
+ * @realm: The realm identifier to use in the request
+ * @realm_len: The length of @realm
+ * @nonce: Unique and securely random nonce to use in the request
+ * @nonce_len: The length of @nonce
+ * @peer: Server-reflexive host address to request permission for
+ * @compatibility: The compatibility mode to use for building the
+ * CreatePermission request
+ *
+ * Create a new TURN CreatePermission request
+ *
+ * Returns: The length of the message to send
+ */
+size_t stun_usage_turn_create_permission (StunAgent *agent, StunMessage *msg,
+ uint8_t *buffer, size_t buffer_len,
+ uint8_t *username, size_t username_len,
+ uint8_t *password, size_t password_len,
+ uint8_t *realm, size_t realm_len,
+ uint8_t *nonce, size_t nonce_len,
+ struct sockaddr_storage *peer,
+ StunUsageTurnCompatibility compatibility);
+
+/**
+ * stun_usage_turn_process:
+ * @msg: The message containing the response
+ * @relay_addr: A pointer to a #sockaddr structure to fill with the relay address
+ * that the TURN server allocated for us
+ * @relay_addrlen: The length of @relay_addr
+ * @addr: A pointer to a #sockaddr structure to fill with the mapped address
+ * that the STUN response contains.
+ * This argument will only be filled if the return value
+ * of the function is #STUN_USAGE_TURN_RETURN_MAPPED_SUCCESS
+ * @addrlen: The length of @addr
+ * @alternate_server: A pointer to a #sockaddr structure to fill with the
+ * address of an alternate server to which we should send our new STUN
+ * Allocate request, in case the currently used TURN server is requesting the use
+ * of an alternate server. This argument will only be filled if the return value
+ * of the function is #STUN_USAGE_TURN_RETURN_ALTERNATE_SERVER
+ * In the case of @STUN_USAGE_TURN_COMPATIBILITY_OC2007 compatibility, the
+ * @alternate_server could be filled at any time, and should only be considered
+ * if the request was sent to a different server than the address returned
+ * in the @alternate_server field
+ * @alternate_server_len: The length of @alternate_server
+ * @bandwidth: A pointer to fill with the bandwidth the TURN server allocated us
+ * @lifetime: A pointer to fill with the lifetime of the allocation
+ * @compatibility: The compatibility mode to use for processing the Allocation
+ * response
+ *
+ * Process a TURN Allocate response and extract the necessary information from
+ * the message
+ * Returns: A #StunUsageTurnReturn value
+ */
+StunUsageTurnReturn stun_usage_turn_process (StunMessage *msg,
+ struct sockaddr_storage *relay_addr, socklen_t *relay_addrlen,
+ struct sockaddr_storage *addr, socklen_t *addrlen,
+ struct sockaddr_storage *alternate_server, socklen_t *alternate_server_len,
+ uint32_t *bandwidth, uint32_t *lifetime,
+ StunUsageTurnCompatibility compatibility);
+
+/**
+ * stun_usage_turn_refresh_process:
+ * @msg: The message containing the response
+ * @lifetime: A pointer to fill with the lifetime of the allocation
+ * @compatibility: The compatibility mode to use for processing the Refresh
+ * response
+ *
+ * Process a TURN Refresh response and extract the necessary information from
+ * the message
+ * Returns: A #StunUsageTurnReturn value. A #STUN_USAGE_TURN_RETURN_RELAY_SUCCESS
+ * means the Refresh was successful, but no relay address is given (kept the same
+ * as for the original allocation)
+ */
+StunUsageTurnReturn stun_usage_turn_refresh_process (StunMessage *msg,
+ uint32_t *lifetime, StunUsageTurnCompatibility compatibility);
+
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2007-2009 Nokia Corporation. All rights reserved.
+ * Contact: Rémi Denis-Courmont
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ * Olivier Crete, Collabora Ltd.
+ * Kai Vehmanen, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "utils.h"
+
+size_t stun_padding (size_t l)
+{
+ return (4 - (l & 3)) & 3;
+}
+
+size_t stun_align (size_t l)
+{
+ return (l + 3) & ~3;
+}
+
+
+uint16_t stun_getw (const uint8_t *ptr)
+{
+ return ((ptr)[0] << 8) | ptr[1];
+}
+
+
+void *stun_setw (uint8_t *ptr, uint16_t value)
+{
+ *ptr++ = value >> 8;
+ *ptr++ = value & 0xff;
+ return ptr;
+}
+
+
+void stun_set_type (uint8_t *h, StunClass c, StunMethod m)
+{
+/* assert (c < 4); */
+/* assert (m < (1 << 12)); */
+
+ h[0] = (c >> 1) | ((m >> 6) & 0x3e);
+ h[1] = ((c << 4) & 0x10) | ((m << 1) & 0xe0) | (m & 0x0f);
+
+/* assert (stun_getw (h) < (1 << 14)); */
+/* assert (stun_get_class (h) == c); */
+/* assert (stun_get_method (h) == m); */
+}
+
+
+StunMessageReturn stun_xor_address (const StunMessage *msg,
+ struct sockaddr_storage *addr, socklen_t addrlen,
+ uint32_t magic_cookie)
+{
+ union {
+ struct sockaddr_storage *addr;
+ struct sockaddr_in *in;
+ struct sockaddr_in6 *in6;
+ } addr_ptr;
+
+ addr_ptr.addr = addr;
+
+ switch (addr->ss_family)
+ {
+ case AF_INET:
+ {
+ struct sockaddr_in *ip4 = addr_ptr.in;
+ if ((size_t) addrlen < sizeof (*ip4))
+ return STUN_MESSAGE_RETURN_INVALID;
+
+ ip4->sin_port ^= htons (magic_cookie >> 16);
+ ip4->sin_addr.s_addr ^= htonl (magic_cookie);
+ return STUN_MESSAGE_RETURN_SUCCESS;
+ }
+
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *ip6 = addr_ptr.in6;
+ unsigned short i;
+
+ if ((size_t) addrlen < sizeof (*ip6))
+ return STUN_MESSAGE_RETURN_INVALID;
+
+ ip6->sin6_port ^= htons (magic_cookie >> 16);
+ for (i = 0; i < 16; i++)
+ ip6->sin6_addr.s6_addr[i] ^= msg->buffer[4 + i];
+ return STUN_MESSAGE_RETURN_SUCCESS;
+ }
+
+ default:
+ return STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS;
+ }
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2008-2009 Nokia Corporation. All rights reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifndef STUN_UTILS_H
+# define STUN_UTILS_H 1
+
+/*
+ * @file utils.h
+ * @brief STUN client generic utility functions
+ */
+
+#include "stunmessage.h"
+
+#ifdef _WIN32
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#endif
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+size_t stun_padding (size_t l);
+
+size_t stun_align (size_t l);
+
+uint16_t stun_getw (const uint8_t *ptr);
+
+void *stun_setw (uint8_t *ptr, uint16_t value);
+
+void stun_set_type (uint8_t *h, StunClass c, StunMethod m);
+
+StunMessageReturn stun_xor_address (const StunMessage *msg,
+ struct sockaddr_storage *addr, socklen_t addrlen,
+ uint32_t magic_cookie);
+
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif /* STUN_UTILS_H */
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2008-2009 Collabora Ltd.
+ * Contact: Youness Alaoui
+ * (C) 2008-2009 Nokia Corporation. All rights reserved.
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ * Danny Smith
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+/* ISO C9x 7.18 Integer types <stdint.h>
+ * Based on ISO/IEC SC22/WG14 9899 Committee draft (SC22 N2794)
+ *
+ * THIS SOFTWARE IS NOT COPYRIGHTED
+ *
+ * Contributor: Danny Smith <danny_r_smith_2001@yahoo.co.nz>
+ *
+ * This source code is offered for use in the public domain. You may
+ * use, modify or distribute it freely.
+ *
+ * This code is distributed in the hope that it will be useful but
+ * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
+ * DISCLAIMED. This includes but is not limited to warranties of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Date: 2000-12-02
+ */
+
+
+#ifndef _WIN32_COMMON_H
+#define _WIN32_COMMON_H
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+/* On MSVC, ssize_t is SSIZE_T */
+#ifdef _MSC_VER
+#include <BaseTsd.h>
+#define ssize_t SSIZE_T
+#endif
+
+/* Windows v10.0.16232 SDK defines MSG_ERRQUEUE, but doesn't support it with
+ * recvmsg, and also uses a different msghdr struct */
+#undef MSG_ERRQUEUE
+
+#endif /* _WIN32_COMMON_H */
--- /dev/null
+#! /bin/sh
+# test-driver - basic testsuite driver script.
+
+scriptversion=2018-03-07.03; # UTC
+
+# Copyright (C) 2011-2018 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+# Make unconditional expansion of undefined variables an error. This
+# helps a lot in preventing typo-related bugs.
+set -u
+
+usage_error ()
+{
+ echo "$0: $*" >&2
+ print_usage >&2
+ exit 2
+}
+
+print_usage ()
+{
+ cat <<END
+Usage:
+ test-driver --test-name=NAME --log-file=PATH --trs-file=PATH
+ [--expect-failure={yes|no}] [--color-tests={yes|no}]
+ [--enable-hard-errors={yes|no}] [--]
+ TEST-SCRIPT [TEST-SCRIPT-ARGUMENTS]
+The '--test-name', '--log-file' and '--trs-file' options are mandatory.
+END
+}
+
+test_name= # Used for reporting.
+log_file= # Where to save the output of the test script.
+trs_file= # Where to save the metadata of the test run.
+expect_failure=no
+color_tests=no
+enable_hard_errors=yes
+while test $# -gt 0; do
+ case $1 in
+ --help) print_usage; exit $?;;
+ --version) echo "test-driver $scriptversion"; exit $?;;
+ --test-name) test_name=$2; shift;;
+ --log-file) log_file=$2; shift;;
+ --trs-file) trs_file=$2; shift;;
+ --color-tests) color_tests=$2; shift;;
+ --expect-failure) expect_failure=$2; shift;;
+ --enable-hard-errors) enable_hard_errors=$2; shift;;
+ --) shift; break;;
+ -*) usage_error "invalid option: '$1'";;
+ *) break;;
+ esac
+ shift
+done
+
+missing_opts=
+test x"$test_name" = x && missing_opts="$missing_opts --test-name"
+test x"$log_file" = x && missing_opts="$missing_opts --log-file"
+test x"$trs_file" = x && missing_opts="$missing_opts --trs-file"
+if test x"$missing_opts" != x; then
+ usage_error "the following mandatory options are missing:$missing_opts"
+fi
+
+if test $# -eq 0; then
+ usage_error "missing argument"
+fi
+
+if test $color_tests = yes; then
+ # Keep this in sync with 'lib/am/check.am:$(am__tty_colors)'.
+ red='\e[0;31m' # Red.
+ grn='\e[0;32m' # Green.
+ lgn='\e[1;32m' # Light green.
+ blu='\e[1;34m' # Blue.
+ mgn='\e[0;35m' # Magenta.
+ std='\e[m' # No color.
+else
+ red= grn= lgn= blu= mgn= std=
+fi
+
+do_exit='rm -f $log_file $trs_file; (exit $st); exit $st'
+trap "st=129; $do_exit" 1
+trap "st=130; $do_exit" 2
+trap "st=141; $do_exit" 13
+trap "st=143; $do_exit" 15
+
+# Test script is run here.
+"$@" >$log_file 2>&1
+estatus=$?
+
+if test $enable_hard_errors = no && test $estatus -eq 99; then
+ tweaked_estatus=1
+else
+ tweaked_estatus=$estatus
+fi
+
+case $tweaked_estatus:$expect_failure in
+ 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;;
+ 0:*) col=$grn res=PASS recheck=no gcopy=no;;
+ 77:*) col=$blu res=SKIP recheck=no gcopy=yes;;
+ 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;;
+ *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;;
+ *:*) col=$red res=FAIL recheck=yes gcopy=yes;;
+esac
+
+# Report the test outcome and exit status in the logs, so that one can
+# know whether the test passed or failed simply by looking at the '.log'
+# file, without the need of also peaking into the corresponding '.trs'
+# file (automake bug#11814).
+echo "$res $test_name (exit status: $estatus)" >>$log_file
+
+# Report outcome to console.
+echo "${col}${res}${std}: $test_name"
+
+# Register the test result, and other relevant metadata.
+echo ":test-result: $res" > $trs_file
+echo ":global-test-result: $res" >> $trs_file
+echo ":recheck: $recheck" >> $trs_file
+echo ":copy-in-global-log: $gcopy" >> $trs_file
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC0"
+# time-stamp-end: "; # UTC"
+# End:
--- /dev/null
+#
+# Makefile.am for the Nice Glib ICE library
+#
+# (C) 2006, 2007 Collabora Ltd.
+# (C) 2006, 2007 Nokia Corporation. All rights reserved.
+#
+# Licensed under MPL 1.1/LGPL 2.1. See file COPYING.
+
+include $(top_srcdir)/common.mk
+
+TESTS_ENVIRONMENT=\
+ GST_PLUGIN_PATH=${GST_PLUGIN_PATH}:$(top_builddir)/gst
+
+AM_CFLAGS = \
+ $(LIBNICE_CFLAGS) \
+ $(GLIB_CFLAGS) \
+ $(GUPNP_CFLAGS) \
+ -I $(top_srcdir) \
+ -I $(top_srcdir)/agent \
+ -I $(top_srcdir)/random \
+ -I $(top_srcdir)/socket \
+ -I $(top_srcdir)/stun
+AM_CPPFLAGS = -DG_LOG_DOMAIN=\"libnice-tests\"
+
+AM_TESTS_ENVIRONMENT = \
+ G_MESSAGES_DEBUG=all \
+ NICE_DEBUG=all
+
+COMMON_LDADD = $(top_builddir)/agent/libagent.la $(top_builddir)/socket/libsocket.la $(GLIB_LIBS) $(GUPNP_LIBS)
+
+check_PROGRAMS = \
+ test-pseudotcp \
+ test-pseudotcp-fin \
+ test-pseudotcp-fuzzy \
+ test-bsd \
+ test \
+ test-address \
+ test-add-remove-stream \
+ test-build-io-stream \
+ test-io-stream-thread \
+ test-io-stream-closing-write \
+ test-io-stream-closing-read \
+ test-io-stream-cancelling \
+ test-io-stream-pollable \
+ test-send-recv \
+ test-socket-is-based-on \
+ test-udp-turn-fragmentation \
+ test-priority \
+ test-fullmode \
+ test-different-number-streams \
+ test-restart \
+ test-fallback \
+ test-thread \
+ test-trickle \
+ test-new-trickle \
+ test-tcp \
+ test-icetcp \
+ test-credentials \
+ test-turn \
+ test-drop-invalid \
+ test-nomination
+
+dist_check_SCRIPTS = \
+ check-test-fullmode-with-stun.sh \
+ test-pseudotcp-random.sh
+
+if HAVE_GST_CHECK
+check_PROGRAMS += test-gstreamer
+endif
+
+TESTS = $(check_PROGRAMS) $(dist_check_SCRIPTS)
+
+noinst_HEADERS = test-io-stream-common.h
+
+test_pseudotcp_LDADD = $(COMMON_LDADD)
+
+test_pseudotcp_fin_LDADD = $(COMMON_LDADD)
+
+test_pseudotcp_fuzzy_LDADD = $(COMMON_LDADD) -lm
+
+test_bsd_LDADD = $(COMMON_LDADD)
+
+test_LDADD = $(COMMON_LDADD)
+
+test_thread_LDADD = $(COMMON_LDADD)
+
+test_address_LDADD = $(COMMON_LDADD)
+
+test_add_remove_stream_LDADD = $(COMMON_LDADD)
+
+test_build_io_stream_LDADD = $(COMMON_LDADD)
+
+test_io_stream_thread_SOURCES = test-io-stream-thread.c test-io-stream-common.c
+test_io_stream_thread_LDADD = $(COMMON_LDADD)
+
+test_io_stream_closing_write_SOURCES = test-io-stream-closing-write.c test-io-stream-common.c
+test_io_stream_closing_write_LDADD = $(COMMON_LDADD)
+
+test_io_stream_closing_read_SOURCES = test-io-stream-closing-read.c test-io-stream-common.c
+test_io_stream_closing_read_LDADD = $(COMMON_LDADD)
+
+test_io_stream_cancelling_SOURCES = test-io-stream-cancelling.c test-io-stream-common.c
+test_io_stream_cancelling_LDADD = $(COMMON_LDADD)
+
+test_io_stream_pollable_SOURCES = test-io-stream-pollable.c test-io-stream-common.c
+test_io_stream_pollable_LDADD = $(COMMON_LDADD)
+
+test_send_recv_SOURCES = test-send-recv.c test-io-stream-common.c
+test_send_recv_LDADD = $(COMMON_LDADD)
+
+test_socket_is_based_on_LDADD = $(COMMON_LDADD)
+
+test_udp_turn_fragmentation_LDADD = $(COMMON_LDADD)
+
+test_priority_LDADD = $(COMMON_LDADD)
+
+test_fullmode_LDADD = $(COMMON_LDADD)
+
+test_different_number_streams_LDADD = $(COMMON_LDADD)
+
+test_restart_LDADD = $(COMMON_LDADD)
+
+test_fallback_LDADD = $(COMMON_LDADD)
+
+test_trickle_LDADD = $(COMMON_LDADD)
+
+test_new_trickle_LDADD = $(COMMON_LDADD)
+
+test_tcp_LDADD = $(COMMON_LDADD)
+
+test_icetcp_LDADD = $(COMMON_LDADD)
+
+test_credentials_LDADD = $(COMMON_LDADD)
+
+test_turn_LDADD = $(COMMON_LDADD)
+
+test_drop_invalid_LDADD = $(COMMON_LDADD)
+
+test_nomination_LDADD = $(COMMON_LDADD)
+
+test_gstreamer_CFLAGS = $(AM_CFLAGS) $(GST_CHECK_CFLAGS)
+test_gstreamer_LDADD = -lnice -L$(top_builddir)/nice/.libs $(GLIB_LIBS) $(GUPNP_LIBS) $(GST_CHECK_LIBS) $(GST_LIBS)
+
+all-local:
+ chmod a+x $(srcdir)/check-test-fullmode-with-stun.sh
+ chmod a+x $(srcdir)/test-pseudotcp-random.sh
+
+EXTRA_DIST = \
+ libnice.supp \
+ meson.build
--- /dev/null
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+#
+# Makefile.am for the Nice Glib ICE library
+#
+# (C) 2006, 2007 Collabora Ltd.
+# (C) 2006, 2007 Nokia Corporation. All rights reserved.
+#
+# Licensed under MPL 1.1/LGPL 2.1. See file COPYING.
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+check_PROGRAMS = test-pseudotcp$(EXEEXT) test-pseudotcp-fin$(EXEEXT) \
+ test-pseudotcp-fuzzy$(EXEEXT) test-bsd$(EXEEXT) test$(EXEEXT) \
+ test-address$(EXEEXT) test-add-remove-stream$(EXEEXT) \
+ test-build-io-stream$(EXEEXT) test-io-stream-thread$(EXEEXT) \
+ test-io-stream-closing-write$(EXEEXT) \
+ test-io-stream-closing-read$(EXEEXT) \
+ test-io-stream-cancelling$(EXEEXT) \
+ test-io-stream-pollable$(EXEEXT) test-send-recv$(EXEEXT) \
+ test-socket-is-based-on$(EXEEXT) \
+ test-udp-turn-fragmentation$(EXEEXT) test-priority$(EXEEXT) \
+ test-fullmode$(EXEEXT) test-different-number-streams$(EXEEXT) \
+ test-restart$(EXEEXT) test-fallback$(EXEEXT) \
+ test-thread$(EXEEXT) test-trickle$(EXEEXT) \
+ test-new-trickle$(EXEEXT) test-tcp$(EXEEXT) \
+ test-icetcp$(EXEEXT) test-credentials$(EXEEXT) \
+ test-turn$(EXEEXT) test-drop-invalid$(EXEEXT) \
+ test-nomination$(EXEEXT) $(am__EXEEXT_1)
+@HAVE_GST_CHECK_TRUE@am__append_1 = test-gstreamer
+subdir = tests
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/as-compiler-flag.m4 \
+ $(top_srcdir)/m4/ax_check_openssl.m4 \
+ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/introspection.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(dist_check_SCRIPTS) \
+ $(noinst_HEADERS) $(am__DIST_COMMON)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+@HAVE_GST_CHECK_TRUE@am__EXEEXT_1 = test-gstreamer$(EXEEXT)
+test_SOURCES = test.c
+test_OBJECTS = test.$(OBJEXT)
+am__DEPENDENCIES_1 =
+am__DEPENDENCIES_2 = $(top_builddir)/agent/libagent.la \
+ $(top_builddir)/socket/libsocket.la $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+test_DEPENDENCIES = $(am__DEPENDENCIES_2)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+test_add_remove_stream_SOURCES = test-add-remove-stream.c
+test_add_remove_stream_OBJECTS = test-add-remove-stream.$(OBJEXT)
+test_add_remove_stream_DEPENDENCIES = $(am__DEPENDENCIES_2)
+test_address_SOURCES = test-address.c
+test_address_OBJECTS = test-address.$(OBJEXT)
+test_address_DEPENDENCIES = $(am__DEPENDENCIES_2)
+test_bsd_SOURCES = test-bsd.c
+test_bsd_OBJECTS = test-bsd.$(OBJEXT)
+test_bsd_DEPENDENCIES = $(am__DEPENDENCIES_2)
+test_build_io_stream_SOURCES = test-build-io-stream.c
+test_build_io_stream_OBJECTS = test-build-io-stream.$(OBJEXT)
+test_build_io_stream_DEPENDENCIES = $(am__DEPENDENCIES_2)
+test_credentials_SOURCES = test-credentials.c
+test_credentials_OBJECTS = test-credentials.$(OBJEXT)
+test_credentials_DEPENDENCIES = $(am__DEPENDENCIES_2)
+test_different_number_streams_SOURCES = \
+ test-different-number-streams.c
+test_different_number_streams_OBJECTS = \
+ test-different-number-streams.$(OBJEXT)
+test_different_number_streams_DEPENDENCIES = $(am__DEPENDENCIES_2)
+test_drop_invalid_SOURCES = test-drop-invalid.c
+test_drop_invalid_OBJECTS = test-drop-invalid.$(OBJEXT)
+test_drop_invalid_DEPENDENCIES = $(am__DEPENDENCIES_2)
+test_fallback_SOURCES = test-fallback.c
+test_fallback_OBJECTS = test-fallback.$(OBJEXT)
+test_fallback_DEPENDENCIES = $(am__DEPENDENCIES_2)
+test_fullmode_SOURCES = test-fullmode.c
+test_fullmode_OBJECTS = test-fullmode.$(OBJEXT)
+test_fullmode_DEPENDENCIES = $(am__DEPENDENCIES_2)
+test_gstreamer_SOURCES = test-gstreamer.c
+test_gstreamer_OBJECTS = test_gstreamer-test-gstreamer.$(OBJEXT)
+test_gstreamer_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+test_gstreamer_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(test_gstreamer_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o \
+ $@
+test_icetcp_SOURCES = test-icetcp.c
+test_icetcp_OBJECTS = test-icetcp.$(OBJEXT)
+test_icetcp_DEPENDENCIES = $(am__DEPENDENCIES_2)
+am_test_io_stream_cancelling_OBJECTS = \
+ test-io-stream-cancelling.$(OBJEXT) \
+ test-io-stream-common.$(OBJEXT)
+test_io_stream_cancelling_OBJECTS = \
+ $(am_test_io_stream_cancelling_OBJECTS)
+test_io_stream_cancelling_DEPENDENCIES = $(am__DEPENDENCIES_2)
+am_test_io_stream_closing_read_OBJECTS = \
+ test-io-stream-closing-read.$(OBJEXT) \
+ test-io-stream-common.$(OBJEXT)
+test_io_stream_closing_read_OBJECTS = \
+ $(am_test_io_stream_closing_read_OBJECTS)
+test_io_stream_closing_read_DEPENDENCIES = $(am__DEPENDENCIES_2)
+am_test_io_stream_closing_write_OBJECTS = \
+ test-io-stream-closing-write.$(OBJEXT) \
+ test-io-stream-common.$(OBJEXT)
+test_io_stream_closing_write_OBJECTS = \
+ $(am_test_io_stream_closing_write_OBJECTS)
+test_io_stream_closing_write_DEPENDENCIES = $(am__DEPENDENCIES_2)
+am_test_io_stream_pollable_OBJECTS = \
+ test-io-stream-pollable.$(OBJEXT) \
+ test-io-stream-common.$(OBJEXT)
+test_io_stream_pollable_OBJECTS = \
+ $(am_test_io_stream_pollable_OBJECTS)
+test_io_stream_pollable_DEPENDENCIES = $(am__DEPENDENCIES_2)
+am_test_io_stream_thread_OBJECTS = test-io-stream-thread.$(OBJEXT) \
+ test-io-stream-common.$(OBJEXT)
+test_io_stream_thread_OBJECTS = $(am_test_io_stream_thread_OBJECTS)
+test_io_stream_thread_DEPENDENCIES = $(am__DEPENDENCIES_2)
+test_new_trickle_SOURCES = test-new-trickle.c
+test_new_trickle_OBJECTS = test-new-trickle.$(OBJEXT)
+test_new_trickle_DEPENDENCIES = $(am__DEPENDENCIES_2)
+test_nomination_SOURCES = test-nomination.c
+test_nomination_OBJECTS = test-nomination.$(OBJEXT)
+test_nomination_DEPENDENCIES = $(am__DEPENDENCIES_2)
+test_priority_SOURCES = test-priority.c
+test_priority_OBJECTS = test-priority.$(OBJEXT)
+test_priority_DEPENDENCIES = $(am__DEPENDENCIES_2)
+test_pseudotcp_SOURCES = test-pseudotcp.c
+test_pseudotcp_OBJECTS = test-pseudotcp.$(OBJEXT)
+test_pseudotcp_DEPENDENCIES = $(am__DEPENDENCIES_2)
+test_pseudotcp_fin_SOURCES = test-pseudotcp-fin.c
+test_pseudotcp_fin_OBJECTS = test-pseudotcp-fin.$(OBJEXT)
+test_pseudotcp_fin_DEPENDENCIES = $(am__DEPENDENCIES_2)
+test_pseudotcp_fuzzy_SOURCES = test-pseudotcp-fuzzy.c
+test_pseudotcp_fuzzy_OBJECTS = test-pseudotcp-fuzzy.$(OBJEXT)
+test_pseudotcp_fuzzy_DEPENDENCIES = $(am__DEPENDENCIES_2)
+test_restart_SOURCES = test-restart.c
+test_restart_OBJECTS = test-restart.$(OBJEXT)
+test_restart_DEPENDENCIES = $(am__DEPENDENCIES_2)
+am_test_send_recv_OBJECTS = test-send-recv.$(OBJEXT) \
+ test-io-stream-common.$(OBJEXT)
+test_send_recv_OBJECTS = $(am_test_send_recv_OBJECTS)
+test_send_recv_DEPENDENCIES = $(am__DEPENDENCIES_2)
+test_socket_is_based_on_SOURCES = test-socket-is-based-on.c
+test_socket_is_based_on_OBJECTS = test-socket-is-based-on.$(OBJEXT)
+test_socket_is_based_on_DEPENDENCIES = $(am__DEPENDENCIES_2)
+test_tcp_SOURCES = test-tcp.c
+test_tcp_OBJECTS = test-tcp.$(OBJEXT)
+test_tcp_DEPENDENCIES = $(am__DEPENDENCIES_2)
+test_thread_SOURCES = test-thread.c
+test_thread_OBJECTS = test-thread.$(OBJEXT)
+test_thread_DEPENDENCIES = $(am__DEPENDENCIES_2)
+test_trickle_SOURCES = test-trickle.c
+test_trickle_OBJECTS = test-trickle.$(OBJEXT)
+test_trickle_DEPENDENCIES = $(am__DEPENDENCIES_2)
+test_turn_SOURCES = test-turn.c
+test_turn_OBJECTS = test-turn.$(OBJEXT)
+test_turn_DEPENDENCIES = $(am__DEPENDENCIES_2)
+test_udp_turn_fragmentation_SOURCES = test-udp-turn-fragmentation.c
+test_udp_turn_fragmentation_OBJECTS = \
+ test-udp-turn-fragmentation.$(OBJEXT)
+test_udp_turn_fragmentation_DEPENDENCIES = $(am__DEPENDENCIES_2)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/test-add-remove-stream.Po \
+ ./$(DEPDIR)/test-address.Po ./$(DEPDIR)/test-bsd.Po \
+ ./$(DEPDIR)/test-build-io-stream.Po \
+ ./$(DEPDIR)/test-credentials.Po \
+ ./$(DEPDIR)/test-different-number-streams.Po \
+ ./$(DEPDIR)/test-drop-invalid.Po ./$(DEPDIR)/test-fallback.Po \
+ ./$(DEPDIR)/test-fullmode.Po ./$(DEPDIR)/test-icetcp.Po \
+ ./$(DEPDIR)/test-io-stream-cancelling.Po \
+ ./$(DEPDIR)/test-io-stream-closing-read.Po \
+ ./$(DEPDIR)/test-io-stream-closing-write.Po \
+ ./$(DEPDIR)/test-io-stream-common.Po \
+ ./$(DEPDIR)/test-io-stream-pollable.Po \
+ ./$(DEPDIR)/test-io-stream-thread.Po \
+ ./$(DEPDIR)/test-new-trickle.Po ./$(DEPDIR)/test-nomination.Po \
+ ./$(DEPDIR)/test-priority.Po ./$(DEPDIR)/test-pseudotcp-fin.Po \
+ ./$(DEPDIR)/test-pseudotcp-fuzzy.Po \
+ ./$(DEPDIR)/test-pseudotcp.Po ./$(DEPDIR)/test-restart.Po \
+ ./$(DEPDIR)/test-send-recv.Po \
+ ./$(DEPDIR)/test-socket-is-based-on.Po ./$(DEPDIR)/test-tcp.Po \
+ ./$(DEPDIR)/test-thread.Po ./$(DEPDIR)/test-trickle.Po \
+ ./$(DEPDIR)/test-turn.Po \
+ ./$(DEPDIR)/test-udp-turn-fragmentation.Po ./$(DEPDIR)/test.Po \
+ ./$(DEPDIR)/test_gstreamer-test-gstreamer.Po
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = test.c test-add-remove-stream.c test-address.c test-bsd.c \
+ test-build-io-stream.c test-credentials.c \
+ test-different-number-streams.c test-drop-invalid.c \
+ test-fallback.c test-fullmode.c test-gstreamer.c test-icetcp.c \
+ $(test_io_stream_cancelling_SOURCES) \
+ $(test_io_stream_closing_read_SOURCES) \
+ $(test_io_stream_closing_write_SOURCES) \
+ $(test_io_stream_pollable_SOURCES) \
+ $(test_io_stream_thread_SOURCES) test-new-trickle.c \
+ test-nomination.c test-priority.c test-pseudotcp.c \
+ test-pseudotcp-fin.c test-pseudotcp-fuzzy.c test-restart.c \
+ $(test_send_recv_SOURCES) test-socket-is-based-on.c test-tcp.c \
+ test-thread.c test-trickle.c test-turn.c \
+ test-udp-turn-fragmentation.c
+DIST_SOURCES = test.c test-add-remove-stream.c test-address.c \
+ test-bsd.c test-build-io-stream.c test-credentials.c \
+ test-different-number-streams.c test-drop-invalid.c \
+ test-fallback.c test-fullmode.c test-gstreamer.c test-icetcp.c \
+ $(test_io_stream_cancelling_SOURCES) \
+ $(test_io_stream_closing_read_SOURCES) \
+ $(test_io_stream_closing_write_SOURCES) \
+ $(test_io_stream_pollable_SOURCES) \
+ $(test_io_stream_thread_SOURCES) test-new-trickle.c \
+ test-nomination.c test-priority.c test-pseudotcp.c \
+ test-pseudotcp-fin.c test-pseudotcp-fuzzy.c test-restart.c \
+ $(test_send_recv_SOURCES) test-socket-is-based-on.c test-tcp.c \
+ test-thread.c test-trickle.c test-turn.c \
+ test-udp-turn-fragmentation.c
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+HEADERS = $(noinst_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__tty_colors_dummy = \
+ mgn= red= grn= lgn= blu= brg= std=; \
+ am__color_tests=no
+am__tty_colors = { \
+ $(am__tty_colors_dummy); \
+ if test "X$(AM_COLOR_TESTS)" = Xno; then \
+ am__color_tests=no; \
+ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
+ am__color_tests=yes; \
+ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
+ am__color_tests=yes; \
+ fi; \
+ if test $$am__color_tests = yes; then \
+ red='\e[0;31m'; \
+ grn='\e[0;32m'; \
+ lgn='\e[1;32m'; \
+ blu='\e[1;34m'; \
+ mgn='\e[0;35m'; \
+ brg='\e[1m'; \
+ std='\e[m'; \
+ fi; \
+}
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__recheck_rx = ^[ ]*:recheck:[ ]*
+am__global_test_result_rx = ^[ ]*:global-test-result:[ ]*
+am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]*
+# A command that, given a newline-separated list of test names on the
+# standard input, print the name of the tests that are to be re-run
+# upon "make recheck".
+am__list_recheck_tests = $(AWK) '{ \
+ recheck = 1; \
+ while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+ { \
+ if (rc < 0) \
+ { \
+ if ((getline line2 < ($$0 ".log")) < 0) \
+ recheck = 0; \
+ break; \
+ } \
+ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \
+ { \
+ recheck = 0; \
+ break; \
+ } \
+ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \
+ { \
+ break; \
+ } \
+ }; \
+ if (recheck) \
+ print $$0; \
+ close ($$0 ".trs"); \
+ close ($$0 ".log"); \
+}'
+# A command that, given a newline-separated list of test names on the
+# standard input, create the global log from their .trs and .log files.
+am__create_global_log = $(AWK) ' \
+function fatal(msg) \
+{ \
+ print "fatal: making $@: " msg | "cat >&2"; \
+ exit 1; \
+} \
+function rst_section(header) \
+{ \
+ print header; \
+ len = length(header); \
+ for (i = 1; i <= len; i = i + 1) \
+ printf "="; \
+ printf "\n\n"; \
+} \
+{ \
+ copy_in_global_log = 1; \
+ global_test_result = "RUN"; \
+ while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+ { \
+ if (rc < 0) \
+ fatal("failed to read from " $$0 ".trs"); \
+ if (line ~ /$(am__global_test_result_rx)/) \
+ { \
+ sub("$(am__global_test_result_rx)", "", line); \
+ sub("[ ]*$$", "", line); \
+ global_test_result = line; \
+ } \
+ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \
+ copy_in_global_log = 0; \
+ }; \
+ if (copy_in_global_log) \
+ { \
+ rst_section(global_test_result ": " $$0); \
+ while ((rc = (getline line < ($$0 ".log"))) != 0) \
+ { \
+ if (rc < 0) \
+ fatal("failed to read from " $$0 ".log"); \
+ print line; \
+ }; \
+ printf "\n"; \
+ }; \
+ close ($$0 ".trs"); \
+ close ($$0 ".log"); \
+}'
+# Restructured Text title.
+am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; }
+# Solaris 10 'make', and several other traditional 'make' implementations,
+# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it
+# by disabling -e (using the XSI extension "set +e") if it's set.
+am__sh_e_setup = case $$- in *e*) set +e;; esac
+# Default flags passed to test drivers.
+am__common_driver_flags = \
+ --color-tests "$$am__color_tests" \
+ --enable-hard-errors "$$am__enable_hard_errors" \
+ --expect-failure "$$am__expect_failure"
+# To be inserted before the command running the test. Creates the
+# directory for the log if needed. Stores in $dir the directory
+# containing $f, in $tst the test, in $log the log. Executes the
+# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and
+# passes TESTS_ENVIRONMENT. Set up options for the wrapper that
+# will run the test scripts (or their associated LOG_COMPILER, if
+# thy have one).
+am__check_pre = \
+$(am__sh_e_setup); \
+$(am__vpath_adj_setup) $(am__vpath_adj) \
+$(am__tty_colors); \
+srcdir=$(srcdir); export srcdir; \
+case "$@" in \
+ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \
+ *) am__odir=.;; \
+esac; \
+test "x$$am__odir" = x"." || test -d "$$am__odir" \
+ || $(MKDIR_P) "$$am__odir" || exit $$?; \
+if test -f "./$$f"; then dir=./; \
+elif test -f "$$f"; then dir=; \
+else dir="$(srcdir)/"; fi; \
+tst=$$dir$$f; log='$@'; \
+if test -n '$(DISABLE_HARD_ERRORS)'; then \
+ am__enable_hard_errors=no; \
+else \
+ am__enable_hard_errors=yes; \
+fi; \
+case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \
+ am__expect_failure=yes;; \
+ *) \
+ am__expect_failure=no;; \
+esac; \
+$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT)
+# A shell command to get the names of the tests scripts with any registered
+# extension removed (i.e., equivalently, the names of the test logs, with
+# the '.log' extension removed). The result is saved in the shell variable
+# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly,
+# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)",
+# since that might cause problem with VPATH rewrites for suffix-less tests.
+# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'.
+am__set_TESTS_bases = \
+ bases='$(TEST_LOGS)'; \
+ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \
+ bases=`echo $$bases`
+RECHECK_LOGS = $(TEST_LOGS)
+AM_RECURSIVE_TARGETS = check recheck
+TEST_SUITE_LOG = test-suite.log
+TEST_EXTENSIONS = @EXEEXT@ .test
+LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS)
+am__set_b = \
+ case '$@' in \
+ */*) \
+ case '$*' in \
+ */*) b='$*';; \
+ *) b=`echo '$@' | sed 's/\.log$$//'`; \
+ esac;; \
+ *) \
+ b='$*';; \
+ esac
+am__test_logs1 = $(TESTS:=.log)
+am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log)
+TEST_LOGS = $(am__test_logs2:.test.log=.log)
+TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver
+TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \
+ $(TEST_LOG_FLAGS)
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/common.mk \
+ $(top_srcdir)/depcomp $(top_srcdir)/test-driver
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+pkgincludedir = $(includedir)/nice
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCACHE_DISABLE = @CCACHE_DISABLE@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GST010_CFLAGS = @GST010_CFLAGS@
+GST010_LIBS = @GST010_LIBS@
+GST_CFLAGS = @GST_CFLAGS@
+GST_CHECK_CFLAGS = @GST_CHECK_CFLAGS@
+GST_CHECK_LIBS = @GST_CHECK_LIBS@
+GST_LIBS = @GST_LIBS@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@
+GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@
+GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@
+GTKDOC_MKPDF = @GTKDOC_MKPDF@
+GTKDOC_REBASE = @GTKDOC_REBASE@
+GUPNP_CFLAGS = @GUPNP_CFLAGS@
+GUPNP_LIBS = @GUPNP_LIBS@
+GUPNP_PACKAGES = @GUPNP_PACKAGES@
+GUPNP_PACKAGES_PRIVATE = @GUPNP_PACKAGES_PRIVATE@
+GUPNP_PACKAGES_PUBLIC = @GUPNP_PACKAGES_PUBLIC@
+HAVE_GUPNP = @HAVE_GUPNP@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@
+INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@
+INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@
+INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@
+INTROSPECTION_LIBS = @INTROSPECTION_LIBS@
+INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@
+INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
+INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBNICE_CFLAGS = @LIBNICE_CFLAGS@
+LIBNICE_LT_LDFLAGS = @LIBNICE_LT_LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBRT = @LIBRT@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NICE_PACKAGES_PRIVATE = @NICE_PACKAGES_PRIVATE@
+NICE_PACKAGES_PUBLIC = @NICE_PACKAGES_PUBLIC@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_INCLUDES = @OPENSSL_INCLUDES@
+OPENSSL_LDFLAGS = @OPENSSL_LDFLAGS@
+OPENSSL_LIBS = @OPENSSL_LIBS@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+UPNP_ENABLED = @UPNP_ENABLED@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gstplugin010dir = @gstplugin010dir@
+gstplugindir = @gstplugindir@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+CLEANFILES = *.gcno *.gcda
+LOG_DRIVER = $(top_srcdir)/scripts/valgrind-test-driver
+TESTS_ENVIRONMENT = \
+ GST_PLUGIN_PATH=${GST_PLUGIN_PATH}:$(top_builddir)/gst
+
+AM_CFLAGS = \
+ $(LIBNICE_CFLAGS) \
+ $(GLIB_CFLAGS) \
+ $(GUPNP_CFLAGS) \
+ -I $(top_srcdir) \
+ -I $(top_srcdir)/agent \
+ -I $(top_srcdir)/random \
+ -I $(top_srcdir)/socket \
+ -I $(top_srcdir)/stun
+
+AM_CPPFLAGS = -DG_LOG_DOMAIN=\"libnice-tests\"
+AM_TESTS_ENVIRONMENT = \
+ G_MESSAGES_DEBUG=all \
+ NICE_DEBUG=all
+
+COMMON_LDADD = $(top_builddir)/agent/libagent.la $(top_builddir)/socket/libsocket.la $(GLIB_LIBS) $(GUPNP_LIBS)
+dist_check_SCRIPTS = \
+ check-test-fullmode-with-stun.sh \
+ test-pseudotcp-random.sh
+
+TESTS = $(check_PROGRAMS) $(dist_check_SCRIPTS)
+noinst_HEADERS = test-io-stream-common.h
+test_pseudotcp_LDADD = $(COMMON_LDADD)
+test_pseudotcp_fin_LDADD = $(COMMON_LDADD)
+test_pseudotcp_fuzzy_LDADD = $(COMMON_LDADD) -lm
+test_bsd_LDADD = $(COMMON_LDADD)
+test_LDADD = $(COMMON_LDADD)
+test_thread_LDADD = $(COMMON_LDADD)
+test_address_LDADD = $(COMMON_LDADD)
+test_add_remove_stream_LDADD = $(COMMON_LDADD)
+test_build_io_stream_LDADD = $(COMMON_LDADD)
+test_io_stream_thread_SOURCES = test-io-stream-thread.c test-io-stream-common.c
+test_io_stream_thread_LDADD = $(COMMON_LDADD)
+test_io_stream_closing_write_SOURCES = test-io-stream-closing-write.c test-io-stream-common.c
+test_io_stream_closing_write_LDADD = $(COMMON_LDADD)
+test_io_stream_closing_read_SOURCES = test-io-stream-closing-read.c test-io-stream-common.c
+test_io_stream_closing_read_LDADD = $(COMMON_LDADD)
+test_io_stream_cancelling_SOURCES = test-io-stream-cancelling.c test-io-stream-common.c
+test_io_stream_cancelling_LDADD = $(COMMON_LDADD)
+test_io_stream_pollable_SOURCES = test-io-stream-pollable.c test-io-stream-common.c
+test_io_stream_pollable_LDADD = $(COMMON_LDADD)
+test_send_recv_SOURCES = test-send-recv.c test-io-stream-common.c
+test_send_recv_LDADD = $(COMMON_LDADD)
+test_socket_is_based_on_LDADD = $(COMMON_LDADD)
+test_udp_turn_fragmentation_LDADD = $(COMMON_LDADD)
+test_priority_LDADD = $(COMMON_LDADD)
+test_fullmode_LDADD = $(COMMON_LDADD)
+test_different_number_streams_LDADD = $(COMMON_LDADD)
+test_restart_LDADD = $(COMMON_LDADD)
+test_fallback_LDADD = $(COMMON_LDADD)
+test_trickle_LDADD = $(COMMON_LDADD)
+test_new_trickle_LDADD = $(COMMON_LDADD)
+test_tcp_LDADD = $(COMMON_LDADD)
+test_icetcp_LDADD = $(COMMON_LDADD)
+test_credentials_LDADD = $(COMMON_LDADD)
+test_turn_LDADD = $(COMMON_LDADD)
+test_drop_invalid_LDADD = $(COMMON_LDADD)
+test_nomination_LDADD = $(COMMON_LDADD)
+test_gstreamer_CFLAGS = $(AM_CFLAGS) $(GST_CHECK_CFLAGS)
+test_gstreamer_LDADD = -lnice -L$(top_builddir)/nice/.libs $(GLIB_LIBS) $(GUPNP_LIBS) $(GST_CHECK_LIBS) $(GST_LIBS)
+EXTRA_DIST = \
+ libnice.supp \
+ meson.build
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/common.mk $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tests/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu tests/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+$(top_srcdir)/common.mk $(am__empty):
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-checkPROGRAMS:
+ @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+
+test$(EXEEXT): $(test_OBJECTS) $(test_DEPENDENCIES) $(EXTRA_test_DEPENDENCIES)
+ @rm -f test$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_OBJECTS) $(test_LDADD) $(LIBS)
+
+test-add-remove-stream$(EXEEXT): $(test_add_remove_stream_OBJECTS) $(test_add_remove_stream_DEPENDENCIES) $(EXTRA_test_add_remove_stream_DEPENDENCIES)
+ @rm -f test-add-remove-stream$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_add_remove_stream_OBJECTS) $(test_add_remove_stream_LDADD) $(LIBS)
+
+test-address$(EXEEXT): $(test_address_OBJECTS) $(test_address_DEPENDENCIES) $(EXTRA_test_address_DEPENDENCIES)
+ @rm -f test-address$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_address_OBJECTS) $(test_address_LDADD) $(LIBS)
+
+test-bsd$(EXEEXT): $(test_bsd_OBJECTS) $(test_bsd_DEPENDENCIES) $(EXTRA_test_bsd_DEPENDENCIES)
+ @rm -f test-bsd$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_bsd_OBJECTS) $(test_bsd_LDADD) $(LIBS)
+
+test-build-io-stream$(EXEEXT): $(test_build_io_stream_OBJECTS) $(test_build_io_stream_DEPENDENCIES) $(EXTRA_test_build_io_stream_DEPENDENCIES)
+ @rm -f test-build-io-stream$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_build_io_stream_OBJECTS) $(test_build_io_stream_LDADD) $(LIBS)
+
+test-credentials$(EXEEXT): $(test_credentials_OBJECTS) $(test_credentials_DEPENDENCIES) $(EXTRA_test_credentials_DEPENDENCIES)
+ @rm -f test-credentials$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_credentials_OBJECTS) $(test_credentials_LDADD) $(LIBS)
+
+test-different-number-streams$(EXEEXT): $(test_different_number_streams_OBJECTS) $(test_different_number_streams_DEPENDENCIES) $(EXTRA_test_different_number_streams_DEPENDENCIES)
+ @rm -f test-different-number-streams$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_different_number_streams_OBJECTS) $(test_different_number_streams_LDADD) $(LIBS)
+
+test-drop-invalid$(EXEEXT): $(test_drop_invalid_OBJECTS) $(test_drop_invalid_DEPENDENCIES) $(EXTRA_test_drop_invalid_DEPENDENCIES)
+ @rm -f test-drop-invalid$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_drop_invalid_OBJECTS) $(test_drop_invalid_LDADD) $(LIBS)
+
+test-fallback$(EXEEXT): $(test_fallback_OBJECTS) $(test_fallback_DEPENDENCIES) $(EXTRA_test_fallback_DEPENDENCIES)
+ @rm -f test-fallback$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_fallback_OBJECTS) $(test_fallback_LDADD) $(LIBS)
+
+test-fullmode$(EXEEXT): $(test_fullmode_OBJECTS) $(test_fullmode_DEPENDENCIES) $(EXTRA_test_fullmode_DEPENDENCIES)
+ @rm -f test-fullmode$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_fullmode_OBJECTS) $(test_fullmode_LDADD) $(LIBS)
+
+test-gstreamer$(EXEEXT): $(test_gstreamer_OBJECTS) $(test_gstreamer_DEPENDENCIES) $(EXTRA_test_gstreamer_DEPENDENCIES)
+ @rm -f test-gstreamer$(EXEEXT)
+ $(AM_V_CCLD)$(test_gstreamer_LINK) $(test_gstreamer_OBJECTS) $(test_gstreamer_LDADD) $(LIBS)
+
+test-icetcp$(EXEEXT): $(test_icetcp_OBJECTS) $(test_icetcp_DEPENDENCIES) $(EXTRA_test_icetcp_DEPENDENCIES)
+ @rm -f test-icetcp$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_icetcp_OBJECTS) $(test_icetcp_LDADD) $(LIBS)
+
+test-io-stream-cancelling$(EXEEXT): $(test_io_stream_cancelling_OBJECTS) $(test_io_stream_cancelling_DEPENDENCIES) $(EXTRA_test_io_stream_cancelling_DEPENDENCIES)
+ @rm -f test-io-stream-cancelling$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_io_stream_cancelling_OBJECTS) $(test_io_stream_cancelling_LDADD) $(LIBS)
+
+test-io-stream-closing-read$(EXEEXT): $(test_io_stream_closing_read_OBJECTS) $(test_io_stream_closing_read_DEPENDENCIES) $(EXTRA_test_io_stream_closing_read_DEPENDENCIES)
+ @rm -f test-io-stream-closing-read$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_io_stream_closing_read_OBJECTS) $(test_io_stream_closing_read_LDADD) $(LIBS)
+
+test-io-stream-closing-write$(EXEEXT): $(test_io_stream_closing_write_OBJECTS) $(test_io_stream_closing_write_DEPENDENCIES) $(EXTRA_test_io_stream_closing_write_DEPENDENCIES)
+ @rm -f test-io-stream-closing-write$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_io_stream_closing_write_OBJECTS) $(test_io_stream_closing_write_LDADD) $(LIBS)
+
+test-io-stream-pollable$(EXEEXT): $(test_io_stream_pollable_OBJECTS) $(test_io_stream_pollable_DEPENDENCIES) $(EXTRA_test_io_stream_pollable_DEPENDENCIES)
+ @rm -f test-io-stream-pollable$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_io_stream_pollable_OBJECTS) $(test_io_stream_pollable_LDADD) $(LIBS)
+
+test-io-stream-thread$(EXEEXT): $(test_io_stream_thread_OBJECTS) $(test_io_stream_thread_DEPENDENCIES) $(EXTRA_test_io_stream_thread_DEPENDENCIES)
+ @rm -f test-io-stream-thread$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_io_stream_thread_OBJECTS) $(test_io_stream_thread_LDADD) $(LIBS)
+
+test-new-trickle$(EXEEXT): $(test_new_trickle_OBJECTS) $(test_new_trickle_DEPENDENCIES) $(EXTRA_test_new_trickle_DEPENDENCIES)
+ @rm -f test-new-trickle$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_new_trickle_OBJECTS) $(test_new_trickle_LDADD) $(LIBS)
+
+test-nomination$(EXEEXT): $(test_nomination_OBJECTS) $(test_nomination_DEPENDENCIES) $(EXTRA_test_nomination_DEPENDENCIES)
+ @rm -f test-nomination$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_nomination_OBJECTS) $(test_nomination_LDADD) $(LIBS)
+
+test-priority$(EXEEXT): $(test_priority_OBJECTS) $(test_priority_DEPENDENCIES) $(EXTRA_test_priority_DEPENDENCIES)
+ @rm -f test-priority$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_priority_OBJECTS) $(test_priority_LDADD) $(LIBS)
+
+test-pseudotcp$(EXEEXT): $(test_pseudotcp_OBJECTS) $(test_pseudotcp_DEPENDENCIES) $(EXTRA_test_pseudotcp_DEPENDENCIES)
+ @rm -f test-pseudotcp$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_pseudotcp_OBJECTS) $(test_pseudotcp_LDADD) $(LIBS)
+
+test-pseudotcp-fin$(EXEEXT): $(test_pseudotcp_fin_OBJECTS) $(test_pseudotcp_fin_DEPENDENCIES) $(EXTRA_test_pseudotcp_fin_DEPENDENCIES)
+ @rm -f test-pseudotcp-fin$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_pseudotcp_fin_OBJECTS) $(test_pseudotcp_fin_LDADD) $(LIBS)
+
+test-pseudotcp-fuzzy$(EXEEXT): $(test_pseudotcp_fuzzy_OBJECTS) $(test_pseudotcp_fuzzy_DEPENDENCIES) $(EXTRA_test_pseudotcp_fuzzy_DEPENDENCIES)
+ @rm -f test-pseudotcp-fuzzy$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_pseudotcp_fuzzy_OBJECTS) $(test_pseudotcp_fuzzy_LDADD) $(LIBS)
+
+test-restart$(EXEEXT): $(test_restart_OBJECTS) $(test_restart_DEPENDENCIES) $(EXTRA_test_restart_DEPENDENCIES)
+ @rm -f test-restart$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_restart_OBJECTS) $(test_restart_LDADD) $(LIBS)
+
+test-send-recv$(EXEEXT): $(test_send_recv_OBJECTS) $(test_send_recv_DEPENDENCIES) $(EXTRA_test_send_recv_DEPENDENCIES)
+ @rm -f test-send-recv$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_send_recv_OBJECTS) $(test_send_recv_LDADD) $(LIBS)
+
+test-socket-is-based-on$(EXEEXT): $(test_socket_is_based_on_OBJECTS) $(test_socket_is_based_on_DEPENDENCIES) $(EXTRA_test_socket_is_based_on_DEPENDENCIES)
+ @rm -f test-socket-is-based-on$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_socket_is_based_on_OBJECTS) $(test_socket_is_based_on_LDADD) $(LIBS)
+
+test-tcp$(EXEEXT): $(test_tcp_OBJECTS) $(test_tcp_DEPENDENCIES) $(EXTRA_test_tcp_DEPENDENCIES)
+ @rm -f test-tcp$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_tcp_OBJECTS) $(test_tcp_LDADD) $(LIBS)
+
+test-thread$(EXEEXT): $(test_thread_OBJECTS) $(test_thread_DEPENDENCIES) $(EXTRA_test_thread_DEPENDENCIES)
+ @rm -f test-thread$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_thread_OBJECTS) $(test_thread_LDADD) $(LIBS)
+
+test-trickle$(EXEEXT): $(test_trickle_OBJECTS) $(test_trickle_DEPENDENCIES) $(EXTRA_test_trickle_DEPENDENCIES)
+ @rm -f test-trickle$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_trickle_OBJECTS) $(test_trickle_LDADD) $(LIBS)
+
+test-turn$(EXEEXT): $(test_turn_OBJECTS) $(test_turn_DEPENDENCIES) $(EXTRA_test_turn_DEPENDENCIES)
+ @rm -f test-turn$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_turn_OBJECTS) $(test_turn_LDADD) $(LIBS)
+
+test-udp-turn-fragmentation$(EXEEXT): $(test_udp_turn_fragmentation_OBJECTS) $(test_udp_turn_fragmentation_DEPENDENCIES) $(EXTRA_test_udp_turn_fragmentation_DEPENDENCIES)
+ @rm -f test-udp-turn-fragmentation$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_udp_turn_fragmentation_OBJECTS) $(test_udp_turn_fragmentation_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-add-remove-stream.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-address.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-bsd.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-build-io-stream.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-credentials.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-different-number-streams.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-drop-invalid.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-fallback.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-fullmode.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-icetcp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-io-stream-cancelling.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-io-stream-closing-read.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-io-stream-closing-write.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-io-stream-common.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-io-stream-pollable.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-io-stream-thread.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-new-trickle.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-nomination.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-priority.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-pseudotcp-fin.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-pseudotcp-fuzzy.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-pseudotcp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-restart.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-send-recv.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-socket-is-based-on.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-tcp.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-thread.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-trickle.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-turn.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-udp-turn-fragmentation.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_gstreamer-test-gstreamer.Po@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+test_gstreamer-test-gstreamer.o: test-gstreamer.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_gstreamer_CFLAGS) $(CFLAGS) -MT test_gstreamer-test-gstreamer.o -MD -MP -MF $(DEPDIR)/test_gstreamer-test-gstreamer.Tpo -c -o test_gstreamer-test-gstreamer.o `test -f 'test-gstreamer.c' || echo '$(srcdir)/'`test-gstreamer.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_gstreamer-test-gstreamer.Tpo $(DEPDIR)/test_gstreamer-test-gstreamer.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-gstreamer.c' object='test_gstreamer-test-gstreamer.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_gstreamer_CFLAGS) $(CFLAGS) -c -o test_gstreamer-test-gstreamer.o `test -f 'test-gstreamer.c' || echo '$(srcdir)/'`test-gstreamer.c
+
+test_gstreamer-test-gstreamer.obj: test-gstreamer.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_gstreamer_CFLAGS) $(CFLAGS) -MT test_gstreamer-test-gstreamer.obj -MD -MP -MF $(DEPDIR)/test_gstreamer-test-gstreamer.Tpo -c -o test_gstreamer-test-gstreamer.obj `if test -f 'test-gstreamer.c'; then $(CYGPATH_W) 'test-gstreamer.c'; else $(CYGPATH_W) '$(srcdir)/test-gstreamer.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_gstreamer-test-gstreamer.Tpo $(DEPDIR)/test_gstreamer-test-gstreamer.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-gstreamer.c' object='test_gstreamer-test-gstreamer.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(test_gstreamer_CFLAGS) $(CFLAGS) -c -o test_gstreamer-test-gstreamer.obj `if test -f 'test-gstreamer.c'; then $(CYGPATH_W) 'test-gstreamer.c'; else $(CYGPATH_W) '$(srcdir)/test-gstreamer.c'; fi`
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+# Recover from deleted '.trs' file; this should ensure that
+# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create
+# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells
+# to avoid problems with "make -n".
+.log.trs:
+ rm -f $< $@
+ $(MAKE) $(AM_MAKEFLAGS) $<
+
+# Leading 'am--fnord' is there to ensure the list of targets does not
+# expand to empty, as could happen e.g. with make check TESTS=''.
+am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck)
+am--force-recheck:
+ @:
+
+$(TEST_SUITE_LOG): $(TEST_LOGS)
+ @$(am__set_TESTS_bases); \
+ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \
+ redo_bases=`for i in $$bases; do \
+ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \
+ done`; \
+ if test -n "$$redo_bases"; then \
+ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \
+ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \
+ if $(am__make_dryrun); then :; else \
+ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \
+ fi; \
+ fi; \
+ if test -n "$$am__remaking_logs"; then \
+ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \
+ "recursion detected" >&2; \
+ elif test -n "$$redo_logs"; then \
+ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \
+ fi; \
+ if $(am__make_dryrun); then :; else \
+ st=0; \
+ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \
+ for i in $$redo_bases; do \
+ test -f $$i.trs && test -r $$i.trs \
+ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \
+ test -f $$i.log && test -r $$i.log \
+ || { echo "$$errmsg $$i.log" >&2; st=1; }; \
+ done; \
+ test $$st -eq 0 || exit 1; \
+ fi
+ @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \
+ ws='[ ]'; \
+ results=`for b in $$bases; do echo $$b.trs; done`; \
+ test -n "$$results" || results=/dev/null; \
+ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \
+ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \
+ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \
+ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \
+ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \
+ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \
+ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \
+ if test `expr $$fail + $$xpass + $$error` -eq 0; then \
+ success=true; \
+ else \
+ success=false; \
+ fi; \
+ br='==================='; br=$$br$$br$$br$$br; \
+ result_count () \
+ { \
+ if test x"$$1" = x"--maybe-color"; then \
+ maybe_colorize=yes; \
+ elif test x"$$1" = x"--no-color"; then \
+ maybe_colorize=no; \
+ else \
+ echo "$@: invalid 'result_count' usage" >&2; exit 4; \
+ fi; \
+ shift; \
+ desc=$$1 count=$$2; \
+ if test $$maybe_colorize = yes && test $$count -gt 0; then \
+ color_start=$$3 color_end=$$std; \
+ else \
+ color_start= color_end=; \
+ fi; \
+ echo "$${color_start}# $$desc $$count$${color_end}"; \
+ }; \
+ create_testsuite_report () \
+ { \
+ result_count $$1 "TOTAL:" $$all "$$brg"; \
+ result_count $$1 "PASS: " $$pass "$$grn"; \
+ result_count $$1 "SKIP: " $$skip "$$blu"; \
+ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \
+ result_count $$1 "FAIL: " $$fail "$$red"; \
+ result_count $$1 "XPASS:" $$xpass "$$red"; \
+ result_count $$1 "ERROR:" $$error "$$mgn"; \
+ }; \
+ { \
+ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \
+ $(am__rst_title); \
+ create_testsuite_report --no-color; \
+ echo; \
+ echo ".. contents:: :depth: 2"; \
+ echo; \
+ for b in $$bases; do echo $$b; done \
+ | $(am__create_global_log); \
+ } >$(TEST_SUITE_LOG).tmp || exit 1; \
+ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \
+ if $$success; then \
+ col="$$grn"; \
+ else \
+ col="$$red"; \
+ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \
+ fi; \
+ echo "$${col}$$br$${std}"; \
+ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \
+ echo "$${col}$$br$${std}"; \
+ create_testsuite_report --maybe-color; \
+ echo "$$col$$br$$std"; \
+ if $$success; then :; else \
+ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \
+ if test -n "$(PACKAGE_BUGREPORT)"; then \
+ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \
+ fi; \
+ echo "$$col$$br$$std"; \
+ fi; \
+ $$success || exit 1
+
+check-TESTS: $(check_PROGRAMS) $(dist_check_SCRIPTS)
+ @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list
+ @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list
+ @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+ @set +e; $(am__set_TESTS_bases); \
+ log_list=`for i in $$bases; do echo $$i.log; done`; \
+ trs_list=`for i in $$bases; do echo $$i.trs; done`; \
+ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \
+ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \
+ exit $$?;
+recheck: all $(check_PROGRAMS) $(dist_check_SCRIPTS)
+ @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+ @set +e; $(am__set_TESTS_bases); \
+ bases=`for i in $$bases; do echo $$i; done \
+ | $(am__list_recheck_tests)` || exit 1; \
+ log_list=`for i in $$bases; do echo $$i.log; done`; \
+ log_list=`echo $$log_list`; \
+ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \
+ am__force_recheck=am--force-recheck \
+ TEST_LOGS="$$log_list"; \
+ exit $$?
+test-pseudotcp.log: test-pseudotcp$(EXEEXT)
+ @p='test-pseudotcp$(EXEEXT)'; \
+ b='test-pseudotcp'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-pseudotcp-fin.log: test-pseudotcp-fin$(EXEEXT)
+ @p='test-pseudotcp-fin$(EXEEXT)'; \
+ b='test-pseudotcp-fin'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-pseudotcp-fuzzy.log: test-pseudotcp-fuzzy$(EXEEXT)
+ @p='test-pseudotcp-fuzzy$(EXEEXT)'; \
+ b='test-pseudotcp-fuzzy'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-bsd.log: test-bsd$(EXEEXT)
+ @p='test-bsd$(EXEEXT)'; \
+ b='test-bsd'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+test.log: test$(EXEEXT)
+ @p='test$(EXEEXT)'; \
+ b='test'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-address.log: test-address$(EXEEXT)
+ @p='test-address$(EXEEXT)'; \
+ b='test-address'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-add-remove-stream.log: test-add-remove-stream$(EXEEXT)
+ @p='test-add-remove-stream$(EXEEXT)'; \
+ b='test-add-remove-stream'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-build-io-stream.log: test-build-io-stream$(EXEEXT)
+ @p='test-build-io-stream$(EXEEXT)'; \
+ b='test-build-io-stream'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-io-stream-thread.log: test-io-stream-thread$(EXEEXT)
+ @p='test-io-stream-thread$(EXEEXT)'; \
+ b='test-io-stream-thread'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-io-stream-closing-write.log: test-io-stream-closing-write$(EXEEXT)
+ @p='test-io-stream-closing-write$(EXEEXT)'; \
+ b='test-io-stream-closing-write'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-io-stream-closing-read.log: test-io-stream-closing-read$(EXEEXT)
+ @p='test-io-stream-closing-read$(EXEEXT)'; \
+ b='test-io-stream-closing-read'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-io-stream-cancelling.log: test-io-stream-cancelling$(EXEEXT)
+ @p='test-io-stream-cancelling$(EXEEXT)'; \
+ b='test-io-stream-cancelling'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-io-stream-pollable.log: test-io-stream-pollable$(EXEEXT)
+ @p='test-io-stream-pollable$(EXEEXT)'; \
+ b='test-io-stream-pollable'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-send-recv.log: test-send-recv$(EXEEXT)
+ @p='test-send-recv$(EXEEXT)'; \
+ b='test-send-recv'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-socket-is-based-on.log: test-socket-is-based-on$(EXEEXT)
+ @p='test-socket-is-based-on$(EXEEXT)'; \
+ b='test-socket-is-based-on'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-udp-turn-fragmentation.log: test-udp-turn-fragmentation$(EXEEXT)
+ @p='test-udp-turn-fragmentation$(EXEEXT)'; \
+ b='test-udp-turn-fragmentation'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-priority.log: test-priority$(EXEEXT)
+ @p='test-priority$(EXEEXT)'; \
+ b='test-priority'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-fullmode.log: test-fullmode$(EXEEXT)
+ @p='test-fullmode$(EXEEXT)'; \
+ b='test-fullmode'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-different-number-streams.log: test-different-number-streams$(EXEEXT)
+ @p='test-different-number-streams$(EXEEXT)'; \
+ b='test-different-number-streams'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-restart.log: test-restart$(EXEEXT)
+ @p='test-restart$(EXEEXT)'; \
+ b='test-restart'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-fallback.log: test-fallback$(EXEEXT)
+ @p='test-fallback$(EXEEXT)'; \
+ b='test-fallback'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-thread.log: test-thread$(EXEEXT)
+ @p='test-thread$(EXEEXT)'; \
+ b='test-thread'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-trickle.log: test-trickle$(EXEEXT)
+ @p='test-trickle$(EXEEXT)'; \
+ b='test-trickle'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-new-trickle.log: test-new-trickle$(EXEEXT)
+ @p='test-new-trickle$(EXEEXT)'; \
+ b='test-new-trickle'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-tcp.log: test-tcp$(EXEEXT)
+ @p='test-tcp$(EXEEXT)'; \
+ b='test-tcp'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-icetcp.log: test-icetcp$(EXEEXT)
+ @p='test-icetcp$(EXEEXT)'; \
+ b='test-icetcp'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-credentials.log: test-credentials$(EXEEXT)
+ @p='test-credentials$(EXEEXT)'; \
+ b='test-credentials'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-turn.log: test-turn$(EXEEXT)
+ @p='test-turn$(EXEEXT)'; \
+ b='test-turn'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-drop-invalid.log: test-drop-invalid$(EXEEXT)
+ @p='test-drop-invalid$(EXEEXT)'; \
+ b='test-drop-invalid'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-nomination.log: test-nomination$(EXEEXT)
+ @p='test-nomination$(EXEEXT)'; \
+ b='test-nomination'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-gstreamer.log: test-gstreamer$(EXEEXT)
+ @p='test-gstreamer$(EXEEXT)'; \
+ b='test-gstreamer'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+check-test-fullmode-with-stun.sh.log: check-test-fullmode-with-stun.sh
+ @p='check-test-fullmode-with-stun.sh'; \
+ b='check-test-fullmode-with-stun.sh'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+test-pseudotcp-random.sh.log: test-pseudotcp-random.sh
+ @p='test-pseudotcp-random.sh'; \
+ b='test-pseudotcp-random.sh'; \
+ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+.test.log:
+ @p='$<'; \
+ $(am__set_b); \
+ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+ --log-file $$b.log --trs-file $$b.trs \
+ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+ "$$tst" $(AM_TESTS_FD_REDIRECT)
+@am__EXEEXT_TRUE@.test$(EXEEXT).log:
+@am__EXEEXT_TRUE@ @p='$<'; \
+@am__EXEEXT_TRUE@ $(am__set_b); \
+@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \
+@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT)
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) \
+ $(dist_check_SCRIPTS)
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-am
+all-am: Makefile $(HEADERS) all-local
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+ -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS)
+ -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs)
+ -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-checkPROGRAMS clean-generic clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/test-add-remove-stream.Po
+ -rm -f ./$(DEPDIR)/test-address.Po
+ -rm -f ./$(DEPDIR)/test-bsd.Po
+ -rm -f ./$(DEPDIR)/test-build-io-stream.Po
+ -rm -f ./$(DEPDIR)/test-credentials.Po
+ -rm -f ./$(DEPDIR)/test-different-number-streams.Po
+ -rm -f ./$(DEPDIR)/test-drop-invalid.Po
+ -rm -f ./$(DEPDIR)/test-fallback.Po
+ -rm -f ./$(DEPDIR)/test-fullmode.Po
+ -rm -f ./$(DEPDIR)/test-icetcp.Po
+ -rm -f ./$(DEPDIR)/test-io-stream-cancelling.Po
+ -rm -f ./$(DEPDIR)/test-io-stream-closing-read.Po
+ -rm -f ./$(DEPDIR)/test-io-stream-closing-write.Po
+ -rm -f ./$(DEPDIR)/test-io-stream-common.Po
+ -rm -f ./$(DEPDIR)/test-io-stream-pollable.Po
+ -rm -f ./$(DEPDIR)/test-io-stream-thread.Po
+ -rm -f ./$(DEPDIR)/test-new-trickle.Po
+ -rm -f ./$(DEPDIR)/test-nomination.Po
+ -rm -f ./$(DEPDIR)/test-priority.Po
+ -rm -f ./$(DEPDIR)/test-pseudotcp-fin.Po
+ -rm -f ./$(DEPDIR)/test-pseudotcp-fuzzy.Po
+ -rm -f ./$(DEPDIR)/test-pseudotcp.Po
+ -rm -f ./$(DEPDIR)/test-restart.Po
+ -rm -f ./$(DEPDIR)/test-send-recv.Po
+ -rm -f ./$(DEPDIR)/test-socket-is-based-on.Po
+ -rm -f ./$(DEPDIR)/test-tcp.Po
+ -rm -f ./$(DEPDIR)/test-thread.Po
+ -rm -f ./$(DEPDIR)/test-trickle.Po
+ -rm -f ./$(DEPDIR)/test-turn.Po
+ -rm -f ./$(DEPDIR)/test-udp-turn-fragmentation.Po
+ -rm -f ./$(DEPDIR)/test.Po
+ -rm -f ./$(DEPDIR)/test_gstreamer-test-gstreamer.Po
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f ./$(DEPDIR)/test-add-remove-stream.Po
+ -rm -f ./$(DEPDIR)/test-address.Po
+ -rm -f ./$(DEPDIR)/test-bsd.Po
+ -rm -f ./$(DEPDIR)/test-build-io-stream.Po
+ -rm -f ./$(DEPDIR)/test-credentials.Po
+ -rm -f ./$(DEPDIR)/test-different-number-streams.Po
+ -rm -f ./$(DEPDIR)/test-drop-invalid.Po
+ -rm -f ./$(DEPDIR)/test-fallback.Po
+ -rm -f ./$(DEPDIR)/test-fullmode.Po
+ -rm -f ./$(DEPDIR)/test-icetcp.Po
+ -rm -f ./$(DEPDIR)/test-io-stream-cancelling.Po
+ -rm -f ./$(DEPDIR)/test-io-stream-closing-read.Po
+ -rm -f ./$(DEPDIR)/test-io-stream-closing-write.Po
+ -rm -f ./$(DEPDIR)/test-io-stream-common.Po
+ -rm -f ./$(DEPDIR)/test-io-stream-pollable.Po
+ -rm -f ./$(DEPDIR)/test-io-stream-thread.Po
+ -rm -f ./$(DEPDIR)/test-new-trickle.Po
+ -rm -f ./$(DEPDIR)/test-nomination.Po
+ -rm -f ./$(DEPDIR)/test-priority.Po
+ -rm -f ./$(DEPDIR)/test-pseudotcp-fin.Po
+ -rm -f ./$(DEPDIR)/test-pseudotcp-fuzzy.Po
+ -rm -f ./$(DEPDIR)/test-pseudotcp.Po
+ -rm -f ./$(DEPDIR)/test-restart.Po
+ -rm -f ./$(DEPDIR)/test-send-recv.Po
+ -rm -f ./$(DEPDIR)/test-socket-is-based-on.Po
+ -rm -f ./$(DEPDIR)/test-tcp.Po
+ -rm -f ./$(DEPDIR)/test-thread.Po
+ -rm -f ./$(DEPDIR)/test-trickle.Po
+ -rm -f ./$(DEPDIR)/test-turn.Po
+ -rm -f ./$(DEPDIR)/test-udp-turn-fragmentation.Po
+ -rm -f ./$(DEPDIR)/test.Po
+ -rm -f ./$(DEPDIR)/test_gstreamer-test-gstreamer.Po
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: check-am install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am all-local am--depfiles check \
+ check-TESTS check-am clean clean-checkPROGRAMS clean-generic \
+ clean-libtool cscopelist-am ctags ctags-am distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am recheck tags tags-am uninstall \
+ uninstall-am
+
+.PRECIOUS: Makefile
+
+
+check-valgrind:
+ $(MAKE) TESTS_ENVIRONMENT="USE_VALGRIND=1 " check
+
+.PHONY: check-valgrind
+
+all-local:
+ chmod a+x $(srcdir)/check-test-fullmode-with-stun.sh
+ chmod a+x $(srcdir)/test-pseudotcp-random.sh
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
--- /dev/null
+#! /bin/sh
+
+if test -n "${BUILT_WITH_MESON}"; then
+ STUND=$1
+ TEST_FULLMODE=$2
+else
+ STUND=../stun/tools/stund
+ TEST_FULLMODE=./test-fullmode
+fi
+
+echo "Starting ICE full-mode with STUN unit test."
+
+[ -e "$STUND" ] || {
+ echo "STUN server not found: Cannot run unit test!" >&2
+ exit 77
+}
+
+set -x
+pidfile=./stund.pid
+
+export NICE_STUN_SERVER=127.0.0.1
+export NICE_STUN_SERVER_PORT=3800
+
+echo "Launching $STUND on port ${NICE_STUN_SERVER_PORT}."
+
+rm -f -- "$pidfile"
+(sh -c "echo \$\$ > \"$pidfile\" && exec "$STUND" ${NICE_STUN_SERVER_PORT}") &
+sleep 1
+
+"${TEST_FULLMODE}"
+error=$?
+
+kill "$(cat "$pidfile")"
+rm -f -- "$pidfile"
+wait
+exit ${error}
--- /dev/null
+{
+ gnutls-init-calloc
+ Memcheck:Leak
+ fun:calloc
+ ...
+ fun:gtls_gnutls_init
+}
+
+{
+ gnutls-init-realloc
+ Memcheck:Leak
+ fun:realloc
+ ...
+ fun:gtls_gnutls_init
+}
+
+{
+ g-tls-backend-gnutls-init
+ Memcheck:Leak
+ fun:g_once_impl
+ fun:g_tls_backend_gnutls_init
+}
+
+{
+ p11-tokens-init
+ Memcheck:Leak
+ fun:calloc
+ ...
+ fun:create_tokens_inlock
+ fun:initialize_module_inlock_reentrant
+}
+
+{
+ gobject-init-malloc
+ Memcheck:Leak
+ fun:malloc
+ ...
+ fun:gobject_init_ctor
+}
+
+{
+ gobject-init-realloc
+ Memcheck:Leak
+ fun:realloc
+ ...
+ fun:gobject_init_ctor
+}
+
+{
+ gobject-init-calloc
+ Memcheck:Leak
+ fun:calloc
+ ...
+ fun:gobject_init_ctor
+}
+
+{
+ g-type-register-dynamic
+ Memcheck:Leak
+ fun:malloc
+ ...
+ fun:g_type_register_dynamic
+}
+
+{
+ g-type-register-static
+ Memcheck:Leak
+ fun:malloc
+ ...
+ fun:g_type_register_static
+}
+
+{
+ g-type-register-static-realloc
+ Memcheck:Leak
+ fun:realloc
+ ...
+ fun:g_type_register_static
+}
+
+{
+ g-type-register-static-calloc
+ Memcheck:Leak
+ fun:calloc
+ ...
+ fun:g_type_register_static
+}
+
+{
+ g-type-add-interface-dynamic
+ Memcheck:Leak
+ fun:malloc
+ ...
+ fun:g_type_add_interface_dynamic
+}
+
+{
+ g-type-add-interface-static
+ Memcheck:Leak
+ fun:malloc
+ ...
+ fun:g_type_add_interface_static
+}
+
+{
+ g-test-rand-init
+ Memcheck:Leak
+ fun:calloc
+ ...
+ fun:g_rand_new_with_seed_array
+ fun:test_run_seed
+ ...
+ fun:g_test_run
+}
+
+{
+ g-test-rand-init2
+ Memcheck:Leak
+ fun:calloc
+ ...
+ fun:g_rand_new_with_seed_array
+ ...
+ fun:get_global_random
+ ...
+ fun:g_test_init
+}
+
+{
+ g-quark-table-new
+ Memcheck:Leak
+ fun:g_hash_table_new
+ ...
+ fun:quark_new
+}
+
+{
+ g-quark-table-resize
+ Memcheck:Leak
+ fun:g_hash_table_resize
+ ...
+ fun:quark_new
+}
+
+{
+ g-type-interface-init
+ Memcheck:Leak
+ fun:malloc
+ ...
+ fun:type_iface_vtable_base_init_Wm
+}
+
+{
+ g-type-class-init
+ Memcheck:Leak
+ fun:calloc
+ ...
+ fun:type_class_init_Wm
+}
+
+{
+ g-io-module-default-singleton-malloc
+ Memcheck:Leak
+ fun:malloc
+ ...
+ fun:g_type_create_instance
+ ...
+ fun:_g_io_module_get_default
+}
+
+{
+ g-io-module-default-singleton-module
+ Memcheck:Leak
+ fun:calloc
+ ...
+ fun:g_module_open
+ ...
+ fun:_g_io_module_get_default
+}
+
+{
+ g-get-language-names
+ Memcheck:Leak
+ fun:malloc
+ ...
+ fun:g_get_language_names
+}
+
+{
+ g-static-mutex
+ Memcheck:Leak
+ fun:malloc
+ ...
+ fun:g_static_mutex_get_mutex_impl
+}
+
+{
+ g-system-thread-init
+ Memcheck:Leak
+ fun:calloc
+ ...
+ fun:g_system_thread_new
+}
+
+{
+ g-io-module-default-proxy-resolver-gnome
+ Memcheck:Leak
+ fun:calloc
+ ...
+ fun:g_proxy_resolver_gnome_init
+ ...
+ fun:_g_io_module_get_default
+}
+
+{
+ g-private-get
+ drd:ConflictingAccess
+ fun:g_private_get
+}
+{
+ g-private-get-helgrind
+ Helgrind:Race
+ fun:g_private_get
+}
+
+
+{
+ g-private-set
+ drd:ConflictingAccess
+ fun:g_private_set
+}
+{
+ g-private-set-helgrind
+ Helgrind:Race
+ fun:g_private_set
+}
+
+{
+ g-type-construct-free
+ drd:ConflictingAccess
+ fun:g_type_free_instance
+}
+{
+ g-type-construct-free-helgrind
+ Helgrind:Race
+ fun:g_type_free_instance
+}
+
+{
+ g-variant-unref
+ drd:ConflictingAccess
+ fun:g_variant_unref
+}
+{
+ g-variant-unref-helgrind
+ Helgrind:Race
+ fun:g_variant_unref
+}
+
+# TODO: haven't checked these entirely rigorously
+{
+ g-unix-signals-main
+ drd:ConflictingAccess
+ fun:_g_main_create_unix_signal_watch
+}
+{
+ g-unix-signals-dispatch
+ drd:ConflictingAccess
+ ...
+ fun:dispatch_unix_signals*
+}
+{
+ g-unix-signals-dispatch-helgrind
+ Helgrind:Race
+ ...
+ fun:dispatch_unix_signals*
+}
+{
+ g-unix-signals-other
+ drd:ConflictingAccess
+ fun:g_unix_signal_watch*
+}
+{
+ g-unix-signals-other-helgrind
+ Helgrind:Race
+ fun:g_unix_signal_watch*
+}
+{
+ g-unix-signals-handler
+ drd:ConflictingAccess
+ fun:g_unix_signal_handler*
+}
+{
+ g-unix-signals-handler-helgrind
+ Helgrind:Race
+ fun:g_unix_signal_handler*
+}
+{
+ g-unix-signals-worker
+ drd:ConflictingAccess
+ fun:glib_worker_main
+}
+{
+ g-unix-signals-worker-helgrind
+ Helgrind:Race
+ fun:glib_worker_main
+}
+
+# TODO: haven't checked this thoroughly either
+{
+ g-wakeup-acknowledge
+ drd:ConflictingAccess
+ fun:read
+ fun:g_wakeup_acknowledge
+}
+
+# TODO: or these
+{
+ g-type-fundamental
+ drd:ConflictingAccess
+ fun:g_type_fundamental
+}
+{
+ g-type-fundamental-helgrind
+ Helgrind:Race
+ fun:g_type_fundamental
+}
+{
+ g-type-class-peek-static
+ drd:ConflictingAccess
+ fun:g_type_class_peek_static
+}
+{
+ g-type-class-peek-static-helgrind
+ Helgrind:Race
+ fun:g_type_class_peek_static
+}
+{
+ g-type-is-a
+ drd:ConflictingAccess
+ ...
+ fun:g_type_is_a
+}
+{
+ g-type-is-a-helgrind
+ Helgrind:Race
+ ...
+ fun:g_type_is_a
+}
+
+# TODO: ????
+{
+ g-inet-address-get-type
+ drd:ConflictingAccess
+ fun:g_inet_address_get_type
+}
+{
+ g-inet-address-get-type-helgrind
+ Helgrind:Race
+ fun:g_inet_address_get_type
+}
+{
+ nice-get-type-helgrind
+ Helgrind:Race
+ fun:nice_*_get_type
+}
+
+# From: https://github.com/fredericgermain/valgrind/blob/master/glibc-2.X-drd.supp
+{
+ drd-libc-stdio
+ drd:ConflictingAccess
+ obj:*/lib*/libc-*
+}
+{
+ drd-libc-recv
+ drd:ConflictingAccess
+ fun:recv
+}
+{
+ drd-libc-send
+ drd:ConflictingAccess
+ fun:send
+}
+
+# GSources do an opportunistic ref count check
+{
+ g-source-set-ready-time
+ drd:ConflictingAccess
+ fun:g_source_set_ready_time
+}
+{
+ g-source-set-ready-time-helgrind
+ Helgrind:Race
+ fun:g_source_set_ready_time
+}
+
+# TODO: Check this
+{
+ g-source-iter-next
+ Helgrind:Race
+ fun:g_source_iter_next
+ fun:g_main_context_*
+ fun:g_main_context_iterate
+}
+
+{
+ g-object-instance-private
+ drd:ConflictingAccess
+ fun:*_get_instance_private
+}
+{
+ g-object-instance-private-helgrind
+ Helgrind:Race
+ fun:*_get_instance_private
+}
+
+# GLib legitimately calls pthread_cond_signal without a mutex held
+{
+ g-task-thread-complete
+ drd:CondErr
+ ...
+ fun:g_cond_signal
+ fun:g_task_thread_complete
+}
+{
+ g-task-thread-complete
+ Helgrind:Misc
+ ...
+ fun:g_cond_signal
+ fun:g_task_thread_complete
+}
+
+# False positive
+{
+ nice-output-stream-cond
+ Helgrind:Misc
+ ...
+ fun:g_cond_clear
+ fun:write_data_unref
+}
+
+# False positive, but I can't explain how (FIXME)
+{
+ g-task-cond
+ Helgrind:Misc
+ ...
+ fun:g_cond_clear
+ fun:g_task_finalize
+}
+
+# TODO FIXME: This is definitely a race.
+# https://bugzilla.gnome.org/show_bug.cgi?id=735754
+{
+ g-tls-base-stream-close
+ Helgrind:Race
+ ...
+ fun:g_*_stream_close
+ fun:streams_removed_cb
+}
+{
+ g-tls-base-stream-close2
+ Helgrind:Race
+ ...
+ fun:g_*_stream_close
+ fun:g_tls_connection_gnutls_close
+}
+
+# Real race, but is_cancelled() is an opportunistic function anyway
+{
+ g-cancellable-is-cancelled
+ Helgrind:Race
+ fun:g_cancellable_is_cancelled
+}
+
+# False positive
+{
+ g-main-context-cond
+ Helgrind:Misc
+ ...
+ fun:g_cond_clear
+ fun:g_main_context_unref
+}
+
+# False positives
+{
+ g-source-unlocked
+ Helgrind:Race
+ fun:g_source_*_unlocked
+}
+{
+ g-source-internal
+ Helgrind:Race
+ fun:g_source_*_internal
+}
+
+# FIXME: Probably actually a race
+{
+ test-io-stream-common-termination
+ Helgrind:Race
+ fun:check_for_termination
+}
+{
+ test-io-stream-common-wait
+ Helgrind:Race
+ fun:wait_for_start
+}
+{
+ test-io-stream-common-main
+ Helgrind:Race
+ fun:main_thread_cb
+}
+{
+ test-io-stream-common-read
+ Helgrind:Race
+ fun:read_thread_cb
+}
+{
+ test-io-stream-common-write
+ Helgrind:Race
+ fun:write_thread_cb
+}
+
+# False positive
+{
+ g_object_real_dispose
+ Helgrind:Race
+ fun:g_object_real_dispose
+}
+
+# False positive
+{
+ g_object_new_valist
+ Helgrind:Race
+ ...
+ fun:g_object_new_valist
+}
--- /dev/null
+nice_tests = [
+ 'test-pseudotcp',
+ # 'test-pseudotcp-fuzzy', FIXME: this test is not reliable, times out sometimes
+ 'test-bsd',
+ 'test',
+ 'test-address',
+ 'test-add-remove-stream',
+ 'test-build-io-stream',
+ 'test-io-stream-thread',
+ 'test-io-stream-closing-write',
+ 'test-io-stream-closing-read',
+ 'test-io-stream-cancelling',
+ 'test-io-stream-pollable',
+ 'test-send-recv',
+ 'test-socket-is-based-on',
+ 'test-udp-turn-fragmentation',
+ 'test-priority',
+ 'test-fullmode',
+ 'test-different-number-streams',
+ 'test-restart',
+ 'test-fallback',
+ 'test-thread',
+ 'test-trickle',
+ 'test-tcp',
+ 'test-icetcp',
+ 'test-credentials',
+ 'test-turn',
+ 'test-drop-invalid',
+ 'test-nomination',
+]
+
+if cc.has_header('arpa/inet.h')
+ nice_tests += [
+ 'test-pseudotcp-fin',
+ 'test-new-trickle',
+ ]
+endif
+
+tenv = environment()
+tenv.set('BUILT_WITH_MESON', '1')
+
+foreach tname : nice_tests
+ if tname.startswith('test-io-stream') or tname.startswith('test-send-recv')
+ extra_src = ['test-io-stream-common.c']
+ else
+ extra_src = []
+ endif
+ exe = executable('nice-@0@'.format(tname),
+ '@0@.c'.format(tname), extra_src,
+ c_args: '-DG_LOG_DOMAIN="libnice-tests"',
+ include_directories: nice_incs,
+ dependencies: [nice_deps, libm],
+ link_with: [libagent, libstun, libsocket, librandom],
+ install: false)
+ set_variable(tname.underscorify(), exe)
+ test(tname, exe, env: tenv)
+endforeach
+
+if gst_dep.found()
+ gst_check = dependency('gstreamer-check-1.0', required: get_option('gstreamer'),
+ fallback : ['gstreamer', 'gst_check_dep'])
+ if gst_check.found()
+ exe = executable('nice-test-gstreamer',
+ 'test-gstreamer.c', extra_src,
+ c_args: '-DG_LOG_DOMAIN="libnice-tests"',
+ include_directories: nice_incs,
+ dependencies: [nice_deps, gst_check, libm],
+ link_with: libnice,
+ install: false)
+ gst_env = tenv
+ gst_env.append('GST_PLUGIN_PATH_1_0', join_paths(meson.current_build_dir(), '..', 'gst'))
+ test('test-gstreamer', exe, env: gst_env)
+ endif
+endif
+
+if find_program('sh', required : false).found()
+ dd = find_program('dd', required : false)
+ diff = find_program('diff', required : false)
+ if dd.found() and diff.found()
+ test('test-pseudotcp-random', find_program('test-pseudotcp-random.sh'),
+ args: test_pseudotcp,
+ env: tenv)
+ endif
+
+ test('test-fullmode-with-stun', files('check-test-fullmode-with-stun.sh'),
+ args: [stund_exe, test_fullmode],
+ env: tenv,
+ is_parallel: false)
+endif
+
+debugenv = environment()
+debugenv.set('G_MESSAGES_DEBUG', 'all')
+debugenv.set('NICE_DEBUG', 'all')
+add_test_setup('debug', env: debugenv)
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2006, 2007 Collabora Ltd.
+ * Contact: Dafydd Harries
+ * (C) 2006, 2007 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Dafydd Harries, Collabora Ltd.
+ * Kai Vehmanen, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "agent.h"
+#include "agent-priv.h"
+#include <string.h>
+
+int
+main (void)
+{
+ NiceAgent *agent;
+ NiceAddress addr;
+
+#ifdef G_OS_WIN32
+ WSADATA w;
+ WSAStartup(0x0202, &w);
+#endif
+ nice_address_init (&addr);
+
+ if (!nice_address_set_from_string (&addr, "127.0.0.1"))
+ g_assert_not_reached ();
+
+ agent = nice_agent_new (NULL, NICE_COMPATIBILITY_RFC5245);
+ nice_agent_add_local_address (agent, &addr);
+
+ g_assert (nice_agent_add_stream (agent, 1) == 1);
+ g_assert (nice_agent_add_stream (agent, 10) == 2);
+ g_assert (nice_agent_add_stream (agent, 2) == 3);
+
+ g_assert (NULL != agent->streams);
+
+ nice_agent_remove_stream (agent, 1);
+ nice_agent_remove_stream (agent, 2);
+ nice_agent_remove_stream (agent, 3);
+
+ g_assert (NULL == agent->streams);
+
+ g_object_unref (agent);
+#ifdef G_OS_WIN32
+ WSACleanup();
+#endif
+ return 0;
+}
+
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2006, 2007 Collabora Ltd.
+ * Contact: Dafydd Harries
+ * (C) 2006, 2007 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Dafydd Harries, Collabora Ltd.
+ * Kai Vehmanen, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include "address.h"
+
+static void
+test_ipv4 (void)
+{
+ NiceAddress addr;
+ NiceAddress other;
+ gchar str[NICE_ADDRESS_STRING_LEN];
+
+ nice_address_init (&addr);
+ nice_address_init (&other);
+ nice_address_set_ipv4 (&addr, 0x01020304);
+ g_assert (addr.s.ip4.sin_family == AF_INET);
+
+ nice_address_to_string (&addr, str);
+ g_assert (0 == strcmp (str, "1.2.3.4"));
+
+ nice_address_to_string (&addr, str);
+
+ /* same address */
+ nice_address_set_ipv4 (&other, 0x01020304);
+ g_assert (TRUE == nice_address_equal (&addr, &other));
+
+ /* from sockaddr_in */
+ nice_address_set_port (&other, 9876); /* in native byte order */
+ other.s.ip4.sin_family = AF_INET;
+ nice_address_set_from_string (&addr, "1.2.3.4");
+ nice_address_set_port (&addr, 9876); /* in native byte order */
+ nice_address_to_string (&addr, str);
+ nice_address_to_string (&other, str);
+ g_assert (TRUE == nice_address_equal (&addr, &other));
+
+ /* different IP */
+ nice_address_set_ipv4 (&other, 0x01020305);
+ g_assert (FALSE == nice_address_equal (&addr, &other));
+
+ /* different port */
+ nice_address_set_ipv4 (&other, 0x01020304);
+ nice_address_set_port (&addr, 1);
+ g_assert (FALSE == nice_address_equal (&addr, &other));
+
+ /* test private address check */
+ {
+ NiceAddress *heap_addr = nice_address_new ();
+ g_assert (nice_address_set_from_string (heap_addr, "127.0.0.1") == TRUE);
+ g_assert (nice_address_is_private (heap_addr) == TRUE);
+ g_assert (nice_address_set_from_string (heap_addr, "127.0.0.1.1") != TRUE);
+ nice_address_free (heap_addr);
+ }
+}
+
+static void
+test_ipv6 (void)
+{
+ NiceAddress addr, other, v4addr;
+ gchar str[NICE_ADDRESS_STRING_LEN];
+ union {
+ struct sockaddr_in6 in6;
+ struct sockaddr addr;
+ } sin, sin2;
+
+ g_assert (nice_address_set_from_string (&v4addr, "172.1.0.1") == TRUE);
+
+ memset (&sin, 0, sizeof (sin));
+ memset (&sin2, 0, sizeof (sin2));
+
+ memset (&addr, 0, sizeof (NiceAddress));
+ memset (&other, 0, sizeof (NiceAddress));
+ nice_address_init (&addr);
+ nice_address_init (&other);
+ nice_address_set_ipv6 (&addr, (guchar *)
+ "\x00\x11\x22\x33"
+ "\x44\x55\x66\x77"
+ "\x88\x99\xaa\xbb"
+ "\xcc\xdd\xee\xff");
+ g_assert (addr.s.ip6.sin6_family == AF_INET6);
+
+ nice_address_to_string (&addr, str);
+ g_assert (0 == strcmp (str, "11:2233:4455:6677:8899:aabb:ccdd:eeff"));
+
+ nice_address_set_port (&addr, 9876); /* in native byte order */
+ nice_address_set_from_string (&other, "11:2233:4455:6677:8899:aabb:ccdd:eeff");
+ nice_address_set_port (&other, 9876); /* in native byte order */
+
+ nice_address_copy_to_sockaddr (&other, &sin2.addr);
+ nice_address_copy_to_sockaddr (&addr, &sin.addr);
+ g_assert (nice_address_equal (&addr, &other) == TRUE);
+ nice_address_to_string (&addr, str);
+ nice_address_to_string (&other, str);
+
+ g_assert (memcmp (&sin, &sin2, sizeof(sin)) == 0);
+
+ /* private IPv6 address */
+ nice_address_set_ipv6 (&addr, (guchar *)
+ "\xfc\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x01");
+ g_assert (nice_address_is_private (&addr) == TRUE);
+ nice_address_set_ipv6 (&addr, (guchar *)
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x00"
+ "\x00\x00\x00\x01");
+ g_assert (nice_address_is_private (&addr) == TRUE);
+
+ /* mismatching address families */
+ g_assert (nice_address_equal (&addr, &v4addr) != TRUE);
+
+ /* mismatched type */
+ addr.s.addr.sa_family = AF_UNSPEC;
+ /*g_assert (nice_address_equal (&addr, &v4addr) != TRUE);*/
+}
+
+int
+main (void)
+{
+#ifdef G_OS_WIN32
+ WSADATA w;
+#endif
+
+#ifdef G_OS_WIN32
+ WSAStartup(0x0202, &w);
+#endif
+ test_ipv4 ();
+ test_ipv6 ();
+
+#ifdef G_OS_WIN32
+ WSACleanup();
+#endif
+ return 0;
+}
+
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2006, 2007, 2014 Collabora Ltd.
+ * Contact: Dafydd Harries
+ * (C) 2006, 2007 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Dafydd Harries, Collabora Ltd.
+ * Philip Withnall, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+
+#include "socket.h"
+
+static gssize
+socket_recv (NiceSocket *sock, NiceAddress *addr, gsize buf_len, gchar *buf)
+{
+ GInputVector local_buf = { buf, buf_len };
+ NiceInputMessage local_message = { &local_buf, 1, addr, 0 };
+ gint ret;
+
+ ret = nice_socket_recv_messages (sock, &local_message, 1);
+ if (ret <= 0)
+ return ret;
+
+ return local_buf.size;
+}
+
+static void
+test_socket_initial_properties (void)
+{
+ NiceSocket *sock;
+
+ sock = nice_udp_bsd_socket_new (NULL);
+ g_assert (sock != NULL);
+
+ // not bound to a particular interface
+ g_assert_cmpint (sock->addr.s.ip4.sin_addr.s_addr, ==, 0);
+ // is bound to a particular port
+ g_assert_cmpuint (nice_address_get_port (&sock->addr), !=, 0);
+
+ nice_socket_free (sock);
+}
+
+static void
+test_socket_address_properties (void)
+{
+ NiceSocket *sock;
+ NiceAddress tmp;
+
+ sock = nice_udp_bsd_socket_new (NULL);
+ g_assert (sock != NULL);
+
+ g_assert (nice_address_set_from_string (&tmp, "127.0.0.1"));
+ g_assert_cmpuint (nice_address_get_port (&sock->addr), !=, 0);
+ nice_address_set_port (&tmp, nice_address_get_port (&sock->addr));
+ g_assert_cmpuint (nice_address_get_port (&tmp), !=, 0);
+
+ nice_socket_free (sock);
+}
+
+static void
+test_simple_send_recv (void)
+{
+ NiceSocket *server;
+ NiceSocket *client;
+ NiceAddress tmp;
+ gchar buf[5];
+
+ server = nice_udp_bsd_socket_new (NULL);
+ g_assert (server != NULL);
+
+ client = nice_udp_bsd_socket_new (NULL);
+ g_assert (client != NULL);
+
+ g_assert (nice_address_set_from_string (&tmp, "127.0.0.1"));
+ nice_address_set_port (&tmp, nice_address_get_port (&server->addr));
+
+ /* Send and receive stuff. */
+ g_assert_cmpint (nice_socket_send (client, &tmp, 5, "hello"), ==, 5);
+
+ g_assert_cmpint (socket_recv (server, &tmp, 5, buf), ==, 5);
+ g_assert_cmpint (strncmp (buf, "hello", 5), ==, 0);
+
+ g_assert_cmpint (nice_socket_send (server, &tmp, 5, "uryyb"), ==, 5);
+
+ g_assert_cmpint (socket_recv (client, &tmp, 5, buf), ==, 5);
+ g_assert_cmpint (strncmp (buf, "uryyb", 5), ==, 0);
+
+ nice_socket_free (client);
+ nice_socket_free (server);
+}
+
+/* Check that sending and receiving to/from zero-length buffers returns
+ * immediately. */
+static void
+test_zero_send_recv (void)
+{
+ NiceSocket *sock;
+ NiceAddress tmp;
+ gchar buf[5];
+ NiceOutputMessage local_out_message;
+ NiceInputMessage local_in_message;
+
+ sock = nice_udp_bsd_socket_new (NULL);
+ g_assert (sock != NULL);
+
+ g_assert (nice_address_set_from_string (&tmp, "127.0.0.1"));
+ g_assert_cmpuint (nice_address_get_port (&sock->addr), !=, 0);
+ nice_address_set_port (&tmp, nice_address_get_port (&sock->addr));
+ g_assert_cmpuint (nice_address_get_port (&tmp), !=, 0);
+
+ g_assert_cmpint (nice_socket_send (sock, &tmp, 0, "ignore-me"), ==, 0);
+ g_assert_cmpint (nice_socket_send (sock, &tmp, 0, NULL), ==, 0);
+
+ g_assert_cmpint (socket_recv (sock, &tmp, 0, buf), ==, 0);
+ g_assert_cmpint (socket_recv (sock, &tmp, 0, NULL), ==, 0);
+
+ /* And again with messages. */
+ g_assert_cmpint (nice_socket_send_messages (sock, &tmp,
+ &local_out_message, 0), ==, 0);
+ g_assert_cmpint (nice_socket_send_messages (sock, &tmp, NULL, 0), ==, 0);
+
+ g_assert_cmpint (nice_socket_recv_messages (sock,
+ &local_in_message, 0), ==, 0);
+ g_assert_cmpint (nice_socket_recv_messages (sock, NULL, 0), ==, 0);
+
+ nice_socket_free (sock);
+}
+
+/* Test receiving into multiple tiny buffers. */
+static void
+test_multi_buffer_recv (void)
+{
+ NiceSocket *server;
+ NiceSocket *client;
+ NiceAddress tmp;
+ guint8 buf[20];
+ guint8 dummy_buf[9];
+
+ server = nice_udp_bsd_socket_new (NULL);
+ g_assert (server != NULL);
+
+ client = nice_udp_bsd_socket_new (NULL);
+ g_assert (client != NULL);
+
+ g_assert (nice_address_set_from_string (&tmp, "127.0.0.1"));
+ nice_address_set_port (&tmp, nice_address_get_port (&server->addr));
+
+ /* Send and receive stuff. */
+ {
+ GInputVector bufs[7] = {
+ { &buf[0], 1 },
+ { &buf[1], 4 },
+ { &buf[1], 0 }, /* should be unused (zero-length) */
+ { &buf[5], 1 },
+ { &buf[6], 5 },
+ { &buf[11], 9 }, /* should be unused (message fits in prior buffers) */
+ { &buf[11], 0 }, /* should be unused (zero-length) */
+ };
+ NiceInputMessage message = { bufs, G_N_ELEMENTS (bufs), NULL, 0 };
+
+ /* Initialise the buffers so we can try and catch out-of-bounds accesses. */
+ memset (buf, 0xaa, sizeof (buf));
+ memset (dummy_buf, 0xaa, sizeof (dummy_buf));
+
+ /* Send and receive. */
+ g_assert_cmpint (nice_socket_send (client, &tmp, 11, "hello-world"), ==, 11);
+ g_assert_cmpuint (nice_socket_recv_messages (server, &message, 1), ==, 1);
+ g_assert_cmpuint (message.length, ==, 11);
+
+ /* Check all of the things. The sizes should not have been modified. */
+ g_assert_cmpuint (bufs[0].size, ==, 1);
+ g_assert_cmpuint (bufs[1].size, ==, 4);
+ g_assert_cmpuint (bufs[2].size, ==, 0);
+ g_assert_cmpuint (bufs[3].size, ==, 1);
+ g_assert_cmpuint (bufs[4].size, ==, 5);
+ g_assert_cmpuint (bufs[5].size, ==, 9);
+ g_assert_cmpuint (bufs[6].size, ==, 0);
+
+ g_assert_cmpint (strncmp ((gchar *) buf, "hello-world", 11), ==, 0);
+ g_assert_cmpint (memcmp (buf + 11, dummy_buf, 9), ==, 0);
+ }
+
+ nice_socket_free (client);
+ nice_socket_free (server);
+}
+
+/* Fill a buffer with deterministic but non-repeated data, so that transmission
+ * and reception corruption is more likely to be detected. */
+static void
+fill_send_buf (guint8 *buf, gsize buf_len, guint seed)
+{
+ gsize i;
+
+ for (i = 0; i < buf_len; i++) {
+ buf[i] = '0' + (seed % 10);
+ seed++;
+ }
+}
+
+/* Test receiving multiple messages in a single call. */
+static void
+test_multi_message_recv (guint n_sends, guint n_receives,
+ guint n_bufs_per_message, gsize send_buf_size, gsize recv_buf_size,
+ guint expected_n_received_messages, guint expected_n_sent_messages)
+{
+ NiceSocket *server;
+ NiceSocket *client;
+ NiceAddress tmp;
+
+ server = nice_udp_bsd_socket_new (NULL);
+ g_assert (server != NULL);
+
+ client = nice_udp_bsd_socket_new (NULL);
+ g_assert (client != NULL);
+
+ g_assert (nice_address_set_from_string (&tmp, "127.0.0.1"));
+ nice_address_set_port (&tmp, nice_address_get_port (&server->addr));
+
+ /* Send and receive stuff. */
+ {
+ GInputVector *recv_bufs;
+ NiceInputMessage *recv_messages;
+ GOutputVector *send_bufs;
+ NiceOutputMessage *send_messages;
+ guint i, j;
+ guint8 *_expected_recv_buf;
+ gsize expected_recv_buf_len;
+
+ /* Set up the send buffers. */
+ send_bufs = g_malloc0_n (n_sends * n_bufs_per_message,
+ sizeof (GOutputVector));
+ send_messages = g_malloc0_n (n_sends, sizeof (NiceOutputMessage));
+
+ for (i = 0; i < n_sends; i++) {
+ for (j = 0; j < n_bufs_per_message; j++) {
+ guint8 *buf = g_slice_alloc (send_buf_size);
+
+ send_bufs[i * n_bufs_per_message + j].buffer = buf;
+ send_bufs[i * n_bufs_per_message + j].size = send_buf_size;
+
+ /* Set up the buffer data. */
+ fill_send_buf (buf, send_buf_size, i);
+ }
+
+ send_messages[i].buffers = send_bufs + i * n_bufs_per_message;
+ send_messages[i].n_buffers = n_bufs_per_message;
+ }
+
+ /* Set up the receive buffers. Yay for dynamic tests! */
+ recv_bufs = g_malloc0_n (n_receives * n_bufs_per_message,
+ sizeof (GInputVector));
+ recv_messages = g_malloc0_n (n_receives, sizeof (NiceInputMessage));
+
+ for (i = 0; i < n_receives; i++) {
+ for (j = 0; j < n_bufs_per_message; j++) {
+ recv_bufs[i * n_bufs_per_message + j].buffer =
+ g_slice_alloc (recv_buf_size);
+ recv_bufs[i * n_bufs_per_message + j].size = recv_buf_size;
+
+ /* Initialise the buffer to try to catch out-of-bounds accesses. */
+ memset (recv_bufs[i * n_bufs_per_message + j].buffer, 0xaa,
+ recv_buf_size);
+ }
+
+ recv_messages[i].buffers = recv_bufs + i * n_bufs_per_message;
+ recv_messages[i].n_buffers = n_bufs_per_message;
+ recv_messages[i].from = NULL;
+ recv_messages[i].length = 0;
+ }
+
+ /* Send multiple packets. */
+ g_assert_cmpint (
+ nice_socket_send_messages (client, &tmp, send_messages, n_sends), ==,
+ expected_n_sent_messages);
+
+ /* Receive things. */
+ g_assert_cmpint (
+ nice_socket_recv_messages (server, recv_messages, n_receives), ==,
+ expected_n_received_messages);
+
+ /* Check all of the things. The sizes should not have been modified. */
+ expected_recv_buf_len = recv_buf_size * n_bufs_per_message;
+ _expected_recv_buf = g_slice_alloc (expected_recv_buf_len);
+
+ for (i = 0; i < expected_n_received_messages; i++) {
+ NiceInputMessage *message = &recv_messages[i];
+ guint8 *expected_recv_buf = _expected_recv_buf;
+ gsize expected_len;
+
+ expected_len = MIN (send_buf_size * n_bufs_per_message,
+ expected_recv_buf_len);
+ g_assert_cmpuint (message->length, ==, expected_len);
+
+ /* Build the expected buffer as a concatenation of the expected values of
+ * all receive buffers in the message. */
+ memset (expected_recv_buf, 0xaa, expected_recv_buf_len);
+ fill_send_buf (expected_recv_buf, expected_len, i);
+
+ for (j = 0; j < n_bufs_per_message; j++) {
+ g_assert_cmpuint (message->buffers[j].size, ==, recv_buf_size);
+ g_assert_cmpint (
+ memcmp (message->buffers[j].buffer, expected_recv_buf,
+ recv_buf_size), ==, 0);
+
+ expected_recv_buf += recv_buf_size;
+ }
+ }
+
+ g_slice_free1 (expected_recv_buf_len, _expected_recv_buf);
+
+ for (i = 0; i < n_receives; i++) {
+ for (j = 0; j < n_bufs_per_message; j++) {
+ g_slice_free1 (recv_buf_size,
+ recv_bufs[i * n_bufs_per_message + j].buffer);
+ }
+ }
+
+ for (i = 0; i < n_sends; i++) {
+ for (j = 0; j < n_bufs_per_message; j++) {
+ g_slice_free1 (send_buf_size,
+ (gpointer) send_bufs[i * n_bufs_per_message + j].buffer);
+ }
+ }
+
+ g_free (recv_messages);
+ g_free (recv_bufs);
+ g_free (send_messages);
+ g_free (send_bufs);
+ }
+
+ nice_socket_free (client);
+ nice_socket_free (server);
+}
+
+int
+main (void)
+{
+ test_socket_initial_properties ();
+ test_socket_address_properties ();
+ test_simple_send_recv ();
+ test_zero_send_recv ();
+ test_multi_buffer_recv ();
+
+ /* Multi-message testing. Serious business. */
+ {
+ guint i;
+ struct {
+ guint n_sends; /* messages */
+ guint expected_n_sent_messages;
+
+ guint n_receives; /* messages */
+ guint expected_n_received_messages;
+
+ guint n_bufs_per_message;
+ gsize send_buf_size;
+ gsize recv_buf_size;
+ } test_cases[] = {
+ /* same number of sends and receives */
+ { 2, 2, 2, 2, 1, 100, 100 }, /* send 200B, receive 200B */
+ /* more sends than receives */
+ { 4, 4, 2, 2, 2, 100, 77 }, /* send 800B, receive 308B */
+ /* more receives than sends */
+ { 1, 1, 4, 1, 4, 10, 100 }, /* send 40B, receive 1600B */
+ /* small receive buffer (data loss) */
+ { 100, 100, 100, 100, 1, 100, 64 }, /* send 10000B, receive 6400B */
+ /* small receive buffers (data loss) */
+ { 50, 50, 50, 50, 10, 100, 8 }, /* send 50000B, receive 4000B */
+ };
+
+ for (i = 0; i < G_N_ELEMENTS (test_cases); i++) {
+ test_multi_message_recv (test_cases[i].n_sends, test_cases[i].n_receives,
+ test_cases[i].n_bufs_per_message, test_cases[i].send_buf_size,
+ test_cases[i].recv_buf_size,
+ test_cases[i].expected_n_received_messages,
+ test_cases[i].expected_n_sent_messages);
+ }
+ }
+
+ return 0;
+}
+
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2013 Collabora Ltd.
+ * Contact: Philip Withnall
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Philip Withnall, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#include "agent.h"
+
+#include "iostream.h"
+
+#include "test-io-stream-common.h"
+
+static void
+test_invalid_stream (NiceAddress *addr)
+{
+ NiceAgent *agent;
+ GIOStream *io_stream;
+
+ agent = nice_agent_new_reliable (NULL, NICE_COMPATIBILITY_RFC5245);
+ g_object_set (G_OBJECT (agent), "upnp", FALSE, NULL);
+ nice_agent_add_local_address (agent, addr);
+
+ /* Try building an I/O stream for an invalid stream. All its operations should
+ * return G_IO_ERROR_BROKEN_PIPE. */
+ io_stream = nice_agent_get_io_stream (agent, 5, 5);
+ g_assert (io_stream == NULL);
+
+ g_object_unref (agent);
+}
+
+static void
+test_io_stream_properties (NiceAddress *addr)
+{
+ NiceAgent *agent;
+ guint stream_id;
+ GIOStream *io_stream;
+ GInputStream *input_stream;
+ GOutputStream *output_stream;
+
+ agent = nice_agent_new_reliable (NULL, NICE_COMPATIBILITY_RFC5245);
+ g_object_set (G_OBJECT (agent), "upnp", FALSE, NULL);
+ nice_agent_add_local_address (agent, addr);
+
+ stream_id = nice_agent_add_stream (agent, 1);
+
+ /* Try building an I/O stream around it. */
+ io_stream = nice_agent_get_io_stream (agent, stream_id, 1);
+ g_assert (G_IS_IO_STREAM (io_stream));
+ g_assert (NICE_IS_IO_STREAM (io_stream));
+
+ /* Check various initial properties. */
+ g_assert (!g_io_stream_is_closed (G_IO_STREAM (io_stream)));
+ g_assert (!g_io_stream_has_pending (G_IO_STREAM (io_stream)));
+
+ /* Check the input stream’s properties. */
+ input_stream = g_io_stream_get_input_stream (G_IO_STREAM (io_stream));
+ g_assert (G_IS_INPUT_STREAM (input_stream));
+ g_assert (NICE_IS_INPUT_STREAM (input_stream));
+
+ g_assert (!g_input_stream_is_closed (input_stream));
+ g_assert (!g_input_stream_has_pending (input_stream));
+
+ /* Check the output stream’s properties. */
+ output_stream = g_io_stream_get_output_stream (G_IO_STREAM (io_stream));
+ g_assert (G_IS_OUTPUT_STREAM (output_stream));
+ g_assert (NICE_IS_OUTPUT_STREAM (output_stream));
+
+ g_assert (!g_output_stream_is_closing (output_stream));
+ g_assert (!g_output_stream_is_closed (output_stream));
+ g_assert (!g_output_stream_has_pending (output_stream));
+
+ /* Remove the component and check that the I/O streams close. */
+ nice_agent_remove_stream (agent, stream_id);
+
+ g_assert (g_io_stream_is_closed (G_IO_STREAM (io_stream)));
+ g_assert (g_input_stream_is_closed (input_stream));
+ g_assert (g_output_stream_is_closed (output_stream));
+
+ g_object_unref (io_stream);
+ g_object_unref (agent);
+}
+
+static void
+test_pollable_properties (NiceAddress *addr)
+{
+ NiceAgent *agent;
+ guint stream_id;
+ GIOStream *io_stream;
+ GInputStream *input_stream;
+ GOutputStream *output_stream;
+ GPollableInputStream *pollable_input_stream;
+ GPollableOutputStream *pollable_output_stream;
+ guint8 buf[65536];
+ GError *error = NULL;
+ GSource *stream_source;
+
+ agent = nice_agent_new_reliable (NULL, NICE_COMPATIBILITY_RFC5245);
+ g_object_set (G_OBJECT (agent), "upnp", FALSE, NULL);
+ nice_agent_add_local_address (agent, addr);
+
+ /* Add a stream. */
+ stream_id = nice_agent_add_stream (agent, 1);
+
+ /* Try building an I/O stream around it. */
+ io_stream = nice_agent_get_io_stream (agent, stream_id, 1);
+ g_assert (G_IS_IO_STREAM (io_stream));
+ g_assert (NICE_IS_IO_STREAM (io_stream));
+
+ /* Check the input stream’s properties. */
+ input_stream = g_io_stream_get_input_stream (G_IO_STREAM (io_stream));
+ g_assert (G_IS_POLLABLE_INPUT_STREAM (input_stream));
+ pollable_input_stream = G_POLLABLE_INPUT_STREAM (input_stream);
+
+ g_assert (g_pollable_input_stream_can_poll (pollable_input_stream));
+ g_assert (!g_pollable_input_stream_is_readable (pollable_input_stream));
+
+ g_assert (
+ g_pollable_input_stream_read_nonblocking (pollable_input_stream,
+ buf, sizeof (buf), NULL, &error) == -1);
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK);
+ g_clear_error (&error);
+
+ stream_source =
+ g_pollable_input_stream_create_source (pollable_input_stream, NULL);
+ g_assert (stream_source != NULL);
+ g_source_unref (stream_source);
+
+ /* Check the output stream’s properties. */
+ output_stream = g_io_stream_get_output_stream (G_IO_STREAM (io_stream));
+ g_assert (G_IS_POLLABLE_OUTPUT_STREAM (output_stream));
+ pollable_output_stream = G_POLLABLE_OUTPUT_STREAM (output_stream);
+
+ g_assert (g_pollable_output_stream_can_poll (pollable_output_stream));
+ g_assert (!g_pollable_output_stream_is_writable (pollable_output_stream));
+
+ g_assert (
+ g_pollable_output_stream_write_nonblocking (pollable_output_stream,
+ buf, sizeof (buf), NULL, &error) == -1);
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK);
+ g_clear_error (&error);
+
+ stream_source =
+ g_pollable_output_stream_create_source (pollable_output_stream, NULL);
+ g_assert (stream_source != NULL);
+ g_source_unref (stream_source);
+
+ /* Remove the component and check that the I/O streams close. */
+ nice_agent_remove_stream (agent, stream_id);
+
+ g_assert (!g_pollable_input_stream_is_readable (pollable_input_stream));
+ g_assert (!g_pollable_output_stream_is_writable (pollable_output_stream));
+
+ g_assert (
+ g_pollable_input_stream_read_nonblocking (pollable_input_stream,
+ buf, sizeof (buf), NULL, &error) == 0);
+ g_assert_no_error (error);
+
+ g_assert (
+ g_pollable_output_stream_write_nonblocking (pollable_output_stream,
+ buf, sizeof (buf), NULL, &error) == -1);
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED);
+ g_clear_error (&error);
+
+ g_object_unref (io_stream);
+ g_object_unref (agent);
+}
+
+static gboolean
+source_cancel_cb (gpointer user_data)
+{
+ GCancellable *cancellable = user_data;
+
+ g_cancellable_cancel (cancellable);
+
+ return FALSE;
+}
+
+static gboolean
+source_cancelled_cb (GObject *pollable_stream, gpointer user_data)
+{
+ GMainLoop *main_loop = user_data;
+
+ /* Try and check that the callback was invoked due to cancellation rather than
+ * a poll() event on the socket itself. */
+ if (G_IS_POLLABLE_INPUT_STREAM (pollable_stream)) {
+ g_assert (
+ !g_pollable_input_stream_is_readable (
+ G_POLLABLE_INPUT_STREAM (pollable_stream)));
+ } else {
+ g_assert (
+ !g_pollable_output_stream_is_writable (
+ G_POLLABLE_OUTPUT_STREAM (pollable_stream)));
+ }
+
+ g_main_loop_quit (main_loop);
+
+ return FALSE;
+}
+
+static gboolean
+source_timeout_cb (gpointer user_data)
+{
+ g_error ("check_pollable_source_cancellation() took too long. Aborting.");
+
+ return FALSE;
+}
+
+/* Check that cancelling a GCancellable which is associated with a pollable
+ * stream’s GSource invokes a callback from that source in the main loop. This
+ * uses a main context with three sources: the pollable source, an idle source
+ * to trigger the cancellation, and a timeout source to fail the test if it
+ * takes too long. */
+static void
+check_pollable_source_cancellation (GSource *pollable_source,
+ GCancellable *cancellable)
+{
+ GMainContext *main_context;
+ GMainLoop *main_loop;
+ GSource *idle_source, *timeout_source;
+
+ main_context = g_main_context_new ();
+ main_loop = g_main_loop_new (main_context, FALSE);
+
+ /* Set up the pollable source. */
+ g_source_set_callback (pollable_source, G_SOURCE_FUNC (source_cancelled_cb),
+ main_loop, NULL);
+ g_source_attach (pollable_source, main_context);
+
+ /* Idle source to cancel the cancellable. */
+ idle_source = g_idle_source_new ();
+ g_source_set_callback (idle_source, (GSourceFunc) source_cancel_cb,
+ cancellable, NULL);
+ g_source_attach (idle_source, main_context);
+ g_source_unref (idle_source);
+
+ /* Timeout. */
+ timeout_source = g_timeout_source_new (30000);
+ g_source_set_callback (timeout_source, (GSourceFunc) source_timeout_cb,
+ NULL, NULL);
+ g_source_attach (timeout_source, main_context);
+ g_source_unref (timeout_source);
+
+ /* Run the main loop and expect to quit it immediately as the pollable source
+ * is cancelled. */
+ g_main_loop_run (main_loop);
+
+ g_assert (g_cancellable_is_cancelled (cancellable));
+
+ g_main_loop_unref (main_loop);
+ g_main_context_unref (main_context);
+}
+
+static void
+test_pollable_cancellation (NiceAddress *addr)
+{
+ NiceAgent *agent;
+ guint stream_id;
+ GIOStream *io_stream;
+ GInputStream *input_stream;
+ GOutputStream *output_stream;
+ GPollableInputStream *pollable_input_stream;
+ GPollableOutputStream *pollable_output_stream;
+ guint8 buf[65536];
+ GError *error = NULL;
+ GSource *stream_source;
+ GCancellable *cancellable;
+
+ agent = nice_agent_new_reliable (NULL, NICE_COMPATIBILITY_RFC5245);
+ g_object_set (G_OBJECT (agent), "upnp", FALSE, NULL);
+ nice_agent_add_local_address (agent, addr);
+
+ /* Add a stream. */
+ stream_id = nice_agent_add_stream (agent, 1);
+
+ /* Try building an I/O stream around it. */
+ io_stream = nice_agent_get_io_stream (agent, stream_id, 1);
+ g_assert (G_IS_IO_STREAM (io_stream));
+ g_assert (NICE_IS_IO_STREAM (io_stream));
+
+ /* Grab the input and output streams. */
+ input_stream = g_io_stream_get_input_stream (G_IO_STREAM (io_stream));
+ g_assert (G_IS_POLLABLE_INPUT_STREAM (input_stream));
+ pollable_input_stream = G_POLLABLE_INPUT_STREAM (input_stream);
+
+ output_stream = g_io_stream_get_output_stream (G_IO_STREAM (io_stream));
+ g_assert (G_IS_POLLABLE_OUTPUT_STREAM (output_stream));
+ pollable_output_stream = G_POLLABLE_OUTPUT_STREAM (output_stream);
+
+ /* Check the non-blocking read() and write() return immediately if called with
+ * a cancelled cancellable. */
+ cancellable = g_cancellable_new ();
+ g_cancellable_cancel (cancellable);
+
+ g_assert (
+ g_pollable_input_stream_read_nonblocking (pollable_input_stream,
+ buf, sizeof (buf), cancellable, &error) == -1);
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
+ g_clear_error (&error);
+
+ g_assert (
+ g_pollable_output_stream_write_nonblocking (pollable_output_stream,
+ buf, sizeof (buf), cancellable, &error) == -1);
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
+ g_clear_error (&error);
+
+ g_object_unref (cancellable);
+
+ /* Check the GSources invoke a callback when run with the cancellable
+ * cancelled. */
+ cancellable = g_cancellable_new ();
+ stream_source =
+ g_pollable_input_stream_create_source (pollable_input_stream,
+ cancellable);
+
+ check_pollable_source_cancellation (stream_source, cancellable);
+
+ g_source_unref (stream_source);
+ g_object_unref (cancellable);
+
+ /* And for the output stream. */
+ cancellable = g_cancellable_new ();
+ stream_source =
+ g_pollable_output_stream_create_source (pollable_output_stream,
+ cancellable);
+
+ check_pollable_source_cancellation (stream_source, cancellable);
+
+ g_object_unref (io_stream);
+ g_source_unref (stream_source);
+ g_object_unref (cancellable);
+ g_object_unref (agent);
+}
+
+static void
+test_zero_length_reads_writes (NiceAddress *addr)
+{
+ NiceAgent *agent;
+ guint stream_id;
+ GIOStream *io_stream;
+ GInputStream *input_stream;
+ GOutputStream *output_stream;
+ GPollableInputStream *pollable_input_stream;
+ GPollableOutputStream *pollable_output_stream;
+ GError *error = NULL;
+ guint8 buf[1]; /* should never be accessed */
+
+ agent = nice_agent_new_reliable (NULL, NICE_COMPATIBILITY_RFC5245);
+ g_object_set (G_OBJECT (agent), "upnp", FALSE, NULL);
+ nice_agent_add_local_address (agent, addr);
+
+ /* Add a stream. */
+ stream_id = nice_agent_add_stream (agent, 1);
+
+ /* Try building an I/O stream around it. */
+ io_stream = nice_agent_get_io_stream (agent, stream_id, 1);
+ g_assert (G_IS_IO_STREAM (io_stream));
+ g_assert (NICE_IS_IO_STREAM (io_stream));
+
+ input_stream = g_io_stream_get_input_stream (G_IO_STREAM (io_stream));
+ output_stream = g_io_stream_get_output_stream (G_IO_STREAM (io_stream));
+ pollable_input_stream = G_POLLABLE_INPUT_STREAM (input_stream);
+ pollable_output_stream = G_POLLABLE_OUTPUT_STREAM (output_stream);
+
+ /* Check zero-length reads and writes complete immediately without error. */
+ g_assert (g_input_stream_read (input_stream, buf, 0, NULL, &error) == 0);
+ g_assert_no_error (error);
+
+ g_assert (g_output_stream_write (output_stream, buf, 0, NULL, &error) == 0);
+ g_assert_no_error (error);
+
+ g_assert (
+ g_pollable_input_stream_read_nonblocking (pollable_input_stream,
+ buf, 0, NULL, &error) == 0);
+ g_assert_no_error (error);
+
+ g_assert (
+ g_pollable_output_stream_write_nonblocking (pollable_output_stream,
+ buf, 0, NULL, &error) == 0);
+ g_assert_no_error (error);
+
+ /* Remove the component and check that zero-length reads and writes still
+ * result in a 0 response, rather than any error. */
+ nice_agent_remove_stream (agent, stream_id);
+ g_assert (g_io_stream_is_closed (G_IO_STREAM (io_stream)));
+
+ g_assert (g_input_stream_read (input_stream, buf, 0, NULL, &error) == 0);
+ g_assert_no_error (error);
+
+ g_assert (g_output_stream_write (output_stream, buf, 0, NULL, &error) == 0);
+ g_assert_no_error (error);
+
+ g_assert (
+ g_pollable_input_stream_read_nonblocking (pollable_input_stream,
+ buf, 0, NULL, &error) == 0);
+ g_assert_no_error (error);
+
+ g_assert (
+ g_pollable_output_stream_write_nonblocking (pollable_output_stream,
+ buf, 0, NULL, &error) == 0);
+ g_assert_no_error (error);
+
+ g_object_unref (io_stream);
+ g_object_unref (agent);
+}
+
+int
+main (void)
+{
+ NiceAddress addr;
+
+#ifdef G_OS_WIN32
+ WSADATA w;
+ WSAStartup (0x0202, &w);
+#endif
+ nice_address_init (&addr);
+
+ g_assert (nice_address_set_from_string (&addr, "127.0.0.1"));
+
+ test_invalid_stream (&addr);
+ test_io_stream_properties (&addr);
+ test_pollable_properties (&addr);
+ test_pollable_cancellation (&addr);
+ test_zero_length_reads_writes (&addr);
+
+#ifdef G_OS_WIN32
+ WSACleanup ();
+#endif
+
+ return 0;
+}
+
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2015 Rohan Garg <rohan@garg.io>
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Dafydd Harries, Collabora Ltd.
+ * Kai Vehmanen, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "agent.h"
+#include "agent-priv.h"
+#include <string.h>
+#include <stdio.h>
+
+#define LEFT_AGENT GINT_TO_POINTER(1)
+#define RIGHT_AGENT GINT_TO_POINTER(2)
+#define USE_UPNP 0
+
+static GMainLoop *loop = NULL;
+
+static void cb_nice_recv (NiceAgent *agent, guint stream_id, guint component_id, guint len, gchar *buf, gpointer user_data)
+{
+ g_debug ("test-credentials:%s: %p", G_STRFUNC, user_data);
+}
+
+static void set_credentials(NiceAgent *lagent, NiceAgent *ragent)
+{
+ gchar *ufrag = NULL, *password = NULL;
+
+ g_debug ("test-credentials:%s", G_STRFUNC);
+
+ nice_agent_get_local_credentials (lagent, 1, &ufrag, &password);
+ nice_agent_set_remote_credentials (ragent, 1, ufrag, password);
+
+ g_free (ufrag);
+ g_free (password);
+
+ nice_agent_get_local_credentials (ragent, 1, &ufrag, &password);
+ nice_agent_set_remote_credentials (lagent, 1, ufrag, password);
+
+ g_free (ufrag);
+ g_free (password);
+}
+
+static void swap_candidates(NiceAgent *local, guint local_id, NiceAgent *remote, guint remote_id)
+{
+ GSList *cands = NULL;
+
+ g_debug ("test-credentials:%s", G_STRFUNC);
+ cands = nice_agent_get_local_candidates(local, local_id,
+ NICE_COMPONENT_TYPE_RTP);
+ g_assert(nice_agent_set_remote_candidates(remote, remote_id,
+ NICE_COMPONENT_TYPE_RTP, cands));
+
+ g_slist_free_full (cands, (GDestroyNotify) nice_candidate_free);
+}
+
+
+static void cb_candidate_gathering_done(NiceAgent *agent, guint stream_id, gpointer data)
+{
+ static gboolean L_CAND_DONE = false, R_CAND_DONE = false;
+ static NiceAgent *lagent = NULL, *ragent = NULL;
+
+ g_debug ("test-credentials:%s: %p", G_STRFUNC, data);
+ if (GPOINTER_TO_UINT(data) == 1) {
+ g_debug ("lagent finished gathering candidates");
+ L_CAND_DONE = true;
+ lagent = agent;
+ } else if (GPOINTER_TO_UINT(data) == 2) {
+ g_debug ("ragent finished gathering candidates");
+ R_CAND_DONE = true;
+ ragent = agent;
+ }
+
+ if (L_CAND_DONE && R_CAND_DONE) {
+ set_credentials (lagent, ragent);
+ swap_candidates (lagent, 1, ragent, 1);
+ swap_candidates (ragent, 1, lagent, 1);
+ }
+}
+
+static void cb_component_state_changed (NiceAgent *agent, guint stream_id, guint component_id, guint state, gpointer data)
+{
+ if (state == NICE_COMPONENT_STATE_READY) {
+ g_main_loop_quit(loop);
+ }
+}
+
+static void setup(NiceAgent *lagent, NiceAgent *ragent)
+{
+ NiceAddress addr;
+
+ g_assert (nice_agent_add_stream (lagent, 1) == 1);
+ g_assert (nice_agent_add_stream (ragent, 1) == 1);
+ g_assert (NULL != lagent->streams);
+ g_assert (NULL != ragent->streams);
+
+ nice_address_init (&addr);
+ g_assert (nice_address_set_from_string (&addr, "127.0.0.1"));
+ nice_agent_add_local_address (lagent, &addr);
+ nice_agent_add_local_address (ragent, &addr);
+
+ nice_agent_attach_recv (lagent, 1, NICE_COMPONENT_TYPE_RTP,
+ g_main_context_default (),
+ cb_nice_recv, LEFT_AGENT);
+ nice_agent_attach_recv (ragent, 1, NICE_COMPONENT_TYPE_RTP,
+ g_main_context_default (),
+ cb_nice_recv, RIGHT_AGENT);
+
+ g_signal_connect(G_OBJECT(lagent), "candidate-gathering-done",
+ G_CALLBACK(cb_candidate_gathering_done), LEFT_AGENT);
+ g_signal_connect(G_OBJECT(ragent), "candidate-gathering-done",
+ G_CALLBACK(cb_candidate_gathering_done), RIGHT_AGENT);
+
+ g_signal_connect(G_OBJECT(lagent), "component-state-changed",
+ G_CALLBACK(cb_component_state_changed), LEFT_AGENT);
+
+ g_object_set (G_OBJECT (lagent), "ice-tcp", FALSE, NULL);
+ g_object_set (G_OBJECT (ragent), "ice-tcp", FALSE, NULL);
+
+ g_object_set (G_OBJECT (lagent), "controlling-mode", TRUE, NULL);
+ g_object_set (G_OBJECT (ragent), "controlling-mode", FALSE, NULL);
+
+ g_object_set (G_OBJECT (lagent), "upnp", USE_UPNP, NULL);
+ g_object_set (G_OBJECT (ragent), "upnp", USE_UPNP, NULL);
+
+ g_object_set_data (G_OBJECT (lagent), "other-agent", ragent);
+ g_object_set_data (G_OBJECT (ragent), "other-agent", lagent);
+}
+
+static void teardown(NiceAgent *lagent, NiceAgent *ragent)
+{
+ nice_agent_remove_stream (lagent, 1);
+ nice_agent_remove_stream (ragent, 1);
+}
+
+int main (void)
+{
+ NiceAgent *lagent = NULL, *ragent = NULL;
+ gchar *ufrag = NULL, *password = NULL;
+
+#ifdef G_OS_WIN32
+ WSADATA w;
+ WSAStartup(0x0202, &w);
+#endif
+
+ loop = g_main_loop_new (NULL, FALSE);
+
+ lagent = nice_agent_new (NULL, NICE_COMPATIBILITY_RFC5245);
+ ragent = nice_agent_new (NULL, NICE_COMPATIBILITY_RFC5245);
+
+ setup (lagent, ragent);
+
+ nice_agent_set_local_credentials (lagent, 1, "unicorns", "awesome");
+ nice_agent_get_local_credentials (lagent, 1, &ufrag, &password);
+ g_assert (g_strcmp0("unicorns", ufrag) == 0);
+ g_assert (g_strcmp0("awesome", password) == 0);
+ g_free (ufrag);
+ g_free (password);
+
+ nice_agent_gather_candidates (lagent, 1);
+ nice_agent_gather_candidates (ragent, 1);
+
+ g_main_loop_run (loop);
+
+ teardown (lagent, ragent);
+
+ g_object_unref (lagent);
+ g_object_unref (ragent);
+
+#ifdef G_OS_WIN32
+ WSACleanup();
+#endif
+ return 0;
+}
--- /dev/null
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "agent.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#define ADD_2_STREAMS TRUE
+#define USE_SECOND_STREAM TRUE
+
+static GMainLoop *global_mainloop = NULL;
+
+static guint global_components_ready = 0;
+static guint global_components_ready_exit = 0;
+
+static gboolean timer_cb (gpointer pointer)
+{
+ g_debug ("test-different-number-streams:%s: %p", G_STRFUNC, pointer);
+
+ /* signal status via a global variable */
+
+ /* note: should not be reached, abort */
+ g_error ("ERROR: test has got stuck, aborting...");
+
+ return FALSE;
+}
+
+static void cb_candidate_gathering_done(NiceAgent *agent, guint stream_id, gpointer data)
+{
+ g_debug ("%p: gathering done (stream_id: %u)", agent, stream_id);
+}
+
+static void cb_component_state_changed (NiceAgent *agent, guint stream_id, guint component_id, guint state, gpointer data)
+{
+ g_debug ("%p: component state changed (stream_id: %u, component_id: %u, state: %s)",
+ agent, stream_id, component_id, nice_component_state_to_string (state));
+
+ if (state == NICE_COMPONENT_STATE_READY) {
+ global_components_ready++;
+ }
+
+ /* signal status via a global variable */
+ if (global_components_ready == global_components_ready_exit) {
+ g_debug ("Components ready/failed achieved. Stopping mailoop");
+ g_main_loop_quit (global_mainloop);
+ }
+}
+
+static void set_candidates (NiceAgent *from, guint from_stream,
+ NiceAgent *to, guint to_stream, guint component)
+{
+ GSList *cands = NULL, *i;
+
+ cands = nice_agent_get_local_candidates (from, from_stream, component);
+ nice_agent_set_remote_candidates (to, to_stream, component, cands);
+
+ for (i = cands; i; i = i->next)
+ nice_candidate_free ((NiceCandidate *) i->data);
+ g_slist_free (cands);
+}
+
+static void cb_nice_recv (NiceAgent *agent, guint stream_id, guint component_id, guint len, gchar *buf, gpointer user_data)
+{
+ g_debug ("%p: recv (stream_id: %u, component_id: %u)", agent, stream_id, component_id);
+}
+
+int main (void)
+{
+ NiceAgent *lagent, *ragent;
+ guint timer_id;
+ guint ls_id, rs_id_1, rs_id_2;
+ gchar *lufrag = NULL, *lpassword = NULL;
+ gchar *rufrag1 = NULL, *rpassword1 = NULL, *rufrag2 = NULL, *rpassword2 = NULL;
+ NiceAddress *addr;
+
+
+#ifdef G_OS_WIN32
+ WSADATA w;
+
+ WSAStartup(0x0202, &w);
+#endif
+
+ /* Initialize nice agents */
+ addr = nice_address_new ();
+ nice_address_set_from_string (addr, "127.0.0.1");
+
+ global_mainloop = g_main_loop_new (NULL, FALSE);
+
+ /* step: create the agents L and R */
+ lagent = nice_agent_new (g_main_loop_get_context (global_mainloop),
+ NICE_COMPATIBILITY_GOOGLE);
+ g_debug ("lagent: %p", lagent);
+
+ nice_agent_add_local_address (lagent, addr);
+ nice_agent_set_software (lagent, "test-different-number-streams, Left Agent");
+ g_object_set (G_OBJECT (lagent), "ice-tcp", FALSE, NULL);
+ g_object_set (G_OBJECT (lagent), "controlling-mode", TRUE, NULL);
+ g_object_set (G_OBJECT (lagent), "upnp", FALSE, NULL);
+ g_signal_connect (G_OBJECT (lagent), "candidate-gathering-done",
+ G_CALLBACK (cb_candidate_gathering_done), NULL);
+ g_signal_connect (G_OBJECT (lagent), "component-state-changed",
+ G_CALLBACK (cb_component_state_changed), NULL);
+
+ ragent = nice_agent_new (g_main_loop_get_context (global_mainloop),
+ NICE_COMPATIBILITY_GOOGLE);
+ g_debug ("ragent: %p", ragent);
+
+ nice_agent_add_local_address (ragent, addr);
+ nice_agent_set_software (ragent, "test-different-number-streams, Right Agent");
+ g_object_set (G_OBJECT (ragent), "ice-tcp", FALSE, NULL);
+ g_object_set (G_OBJECT (ragent), "controlling-mode", FALSE, NULL);
+ g_object_set (G_OBJECT (ragent), "upnp", FALSE, NULL);
+ g_signal_connect (G_OBJECT (ragent), "candidate-gathering-done",
+ G_CALLBACK (cb_candidate_gathering_done), NULL);
+ g_signal_connect (G_OBJECT (ragent), "component-state-changed",
+ G_CALLBACK (cb_component_state_changed), NULL);
+
+ /* step: add a timer to catch state changes triggered by signals */
+ timer_id = g_timeout_add (30000, timer_cb, NULL);
+
+ ls_id = nice_agent_add_stream (lagent, 2);
+ g_assert (ls_id > 0);
+ nice_agent_get_local_credentials(lagent, ls_id, &lufrag, &lpassword);
+
+ /* step: attach to mainloop (needed to register the fds) */
+ nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv, NULL);
+ nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTCP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv, NULL);
+
+ global_components_ready_exit = 4;
+
+ if (ADD_2_STREAMS) {
+ rs_id_1 = nice_agent_add_stream (ragent, 2);
+ g_assert (rs_id_1 > 0);
+ nice_agent_get_local_credentials(ragent, rs_id_1, &rufrag1, &rpassword1);
+
+ rs_id_2 = nice_agent_add_stream (ragent, 2);
+ g_assert (rs_id_2 > 0);
+ nice_agent_get_local_credentials(ragent, rs_id_2, &rufrag2, &rpassword2);
+
+ nice_agent_set_remote_credentials (ragent, rs_id_2, lufrag, lpassword);
+ nice_agent_set_remote_credentials (lagent, ls_id, rufrag2, rpassword2);
+
+ g_assert (nice_agent_gather_candidates (lagent, ls_id) == TRUE);
+ g_assert (nice_agent_gather_candidates (ragent, rs_id_2) == TRUE);
+ g_assert (nice_agent_gather_candidates (ragent, rs_id_1) == TRUE);
+
+ if (USE_SECOND_STREAM) {
+ set_candidates (ragent, rs_id_2, lagent, ls_id, NICE_COMPONENT_TYPE_RTP);
+ set_candidates (ragent, rs_id_2, lagent, ls_id, NICE_COMPONENT_TYPE_RTCP);
+ set_candidates (lagent, ls_id, ragent, rs_id_2, NICE_COMPONENT_TYPE_RTP);
+ set_candidates (lagent, ls_id, ragent, rs_id_2, NICE_COMPONENT_TYPE_RTCP);
+ } else {
+ set_candidates (ragent, rs_id_1, lagent, ls_id, NICE_COMPONENT_TYPE_RTP);
+ set_candidates (ragent, rs_id_1, lagent, ls_id, NICE_COMPONENT_TYPE_RTCP);
+ set_candidates (lagent, ls_id, ragent, rs_id_1, NICE_COMPONENT_TYPE_RTP);
+ set_candidates (lagent, ls_id, ragent, rs_id_1, NICE_COMPONENT_TYPE_RTCP);
+ }
+
+ /* step: attach to mainloop (needed to register the fds) */
+ nice_agent_attach_recv (ragent, rs_id_1, NICE_COMPONENT_TYPE_RTP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv, NULL);
+ nice_agent_attach_recv (ragent, rs_id_1, NICE_COMPONENT_TYPE_RTCP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv, NULL);
+ nice_agent_attach_recv (ragent, rs_id_2, NICE_COMPONENT_TYPE_RTP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv, NULL);
+ nice_agent_attach_recv (ragent, rs_id_2, NICE_COMPONENT_TYPE_RTCP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv, NULL);
+ } else {
+ rs_id_1 = nice_agent_add_stream (ragent, 2);
+ g_assert (rs_id_1 > 0);
+ nice_agent_get_local_credentials(ragent, rs_id_1, &rufrag1, &rpassword1);
+
+ nice_agent_set_remote_credentials (ragent, rs_id_1, lufrag, lpassword);
+ nice_agent_set_remote_credentials (lagent, ls_id, rufrag1, rpassword1);
+
+ g_assert (nice_agent_gather_candidates (lagent, ls_id) == TRUE);
+ g_assert (nice_agent_gather_candidates (ragent, rs_id_1) == TRUE);
+
+ /* step: attach to mainloop (needed to register the fds) */
+ nice_agent_attach_recv (ragent, rs_id_1, NICE_COMPONENT_TYPE_RTP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv, NULL);
+ nice_agent_attach_recv (ragent, rs_id_1, NICE_COMPONENT_TYPE_RTCP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv, NULL);
+
+ set_candidates (ragent, rs_id_1, lagent, ls_id, NICE_COMPONENT_TYPE_RTP);
+ set_candidates (ragent, rs_id_1, lagent, ls_id, NICE_COMPONENT_TYPE_RTCP);
+ set_candidates (lagent, ls_id, ragent, rs_id_1, NICE_COMPONENT_TYPE_RTP);
+ set_candidates (lagent, ls_id, ragent, rs_id_1, NICE_COMPONENT_TYPE_RTCP);
+ }
+
+ /* step: run the mainloop until connectivity checks succeed
+ * (see timer_cb() above) */
+ g_main_loop_run (global_mainloop);
+
+ g_free (lufrag);
+ g_free (lpassword);
+ g_free (rufrag1);
+ g_free (rpassword1);
+ g_free (rufrag2);
+ g_free (rpassword2);
+ g_object_unref (lagent);
+ g_object_unref (ragent);
+
+ g_main_loop_unref (global_mainloop);
+ global_mainloop = NULL;
+
+ g_source_remove (timer_id);
+
+#ifdef G_OS_WIN32
+ WSACleanup();
+#endif
+
+ return 0;
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * Unit test for ICE full-mode related features.
+ *
+ * (C) 2007 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ * (C) 2017 Collabora Ltd
+ * Contact: Olivier Crete <olivier.crete@collabora.com>
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Kai Vehmanen, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "agent.h"
+
+#include "socket/socket.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+
+
+static NiceComponentState global_lagent_state[2] = { NICE_COMPONENT_STATE_LAST, NICE_COMPONENT_STATE_LAST };
+static NiceComponentState global_ragent_state[2] = { NICE_COMPONENT_STATE_LAST, NICE_COMPONENT_STATE_LAST };
+static guint global_components_ready = 0;
+static guint global_components_ready_exit = 0;
+static guint global_components_failed = 0;
+static guint global_components_failed_exit = 0;
+static GMainLoop *global_mainloop = NULL;
+static gboolean global_lagent_gathering_done = FALSE;
+static gboolean global_ragent_gathering_done = FALSE;
+static gboolean global_lagent_ibr_received = FALSE;
+static gboolean global_ragent_ibr_received = FALSE;
+static int global_lagent_cands = 0;
+static int global_ragent_cands = 0;
+static gint global_ragent_read = 0;
+static guint global_exit_when_ibr_received = 0;
+
+static void priv_print_global_status (void)
+{
+ g_debug ("\tgathering_done=%d", global_lagent_gathering_done && global_ragent_gathering_done);
+ g_debug ("\tlstate[rtp]=%d [rtcp]=%d", global_lagent_state[0], global_lagent_state[1]);
+ g_debug ("\trstate[rtp]=%d [rtcp]=%d", global_ragent_state[0], global_ragent_state[1]);
+ g_debug ("\tL cands=%d R cands=%d", global_lagent_cands, global_ragent_cands);
+}
+
+static gboolean timer_cb (gpointer pointer)
+{
+ g_debug ("test-drop-invalid:%s: %p", G_STRFUNC, pointer);
+
+ /* signal status via a global variable */
+
+ /* note: should not be reached, abort */
+ g_error ("ERROR: test has got stuck, aborting...");
+
+ return FALSE;
+}
+
+static void cb_nice_recv (NiceAgent *agent, guint stream_id, guint component_id, guint len, gchar *buf, gpointer user_data)
+{
+ g_debug ("test-drop-invalid:%s: %p", G_STRFUNC, user_data);
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent; (void)stream_id; (void)component_id; (void)buf;
+
+ /* Core of the test
+ * Assert on any unreleated packet received. This would include anything
+ * send before the negotiation is over.
+ */
+ g_assert (len == 16);
+ g_assert (strncmp ("1234567812345678", buf, 16) == 0);
+
+ if (component_id == 2)
+ return;
+
+ if (GPOINTER_TO_UINT (user_data) == 2) {
+ g_debug ("right agent received %d bytes, stopping mainloop", len);
+ global_ragent_read = len;
+ g_main_loop_quit (global_mainloop);
+ }
+}
+
+static void cb_candidate_gathering_done(NiceAgent *agent, guint stream_id, gpointer data)
+{
+ g_debug ("test-drop-invalid:%s: %p", G_STRFUNC, data);
+
+ if (GPOINTER_TO_UINT (data) == 1)
+ global_lagent_gathering_done = TRUE;
+ else if (GPOINTER_TO_UINT (data) == 2)
+ global_ragent_gathering_done = TRUE;
+
+ if (global_lagent_gathering_done &&
+ global_ragent_gathering_done)
+ g_main_loop_quit (global_mainloop);
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent;
+}
+
+static void cb_component_state_changed (NiceAgent *agent, guint stream_id, guint component_id, guint state, gpointer data)
+{
+ gboolean ready_to_connected = FALSE;
+ g_debug ("test-drop-invalid:%s: %p", G_STRFUNC, data);
+
+ if (GPOINTER_TO_UINT (data) == 1) {
+ if (global_lagent_state[component_id - 1] == NICE_COMPONENT_STATE_READY &&
+ state == NICE_COMPONENT_STATE_CONNECTED)
+ ready_to_connected = TRUE;
+ global_lagent_state[component_id - 1] = state;
+ } else if (GPOINTER_TO_UINT (data) == 2) {
+ if (global_ragent_state[component_id - 1] == NICE_COMPONENT_STATE_READY &&
+ state == NICE_COMPONENT_STATE_CONNECTED)
+ ready_to_connected = TRUE;
+ global_ragent_state[component_id - 1] = state;
+ }
+
+ if (state == NICE_COMPONENT_STATE_READY)
+ global_components_ready++;
+ else if (state == NICE_COMPONENT_STATE_CONNECTED && ready_to_connected)
+ global_components_ready--;
+ if (state == NICE_COMPONENT_STATE_FAILED)
+ global_components_failed++;
+
+ g_debug ("test-drop-invalid: checks READY/EXIT-AT %u/%u.", global_components_ready, global_components_ready_exit);
+ g_debug ("test-drop-invalid: checks FAILED/EXIT-AT %u/%u.", global_components_failed, global_components_failed_exit);
+
+ /* signal status via a global variable */
+ if (global_components_ready == global_components_ready_exit &&
+ global_components_failed == global_components_failed_exit) {
+ g_debug ("Components ready/failed achieved. Stopping mailoop");
+ g_main_loop_quit (global_mainloop);
+ return;
+ }
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent; (void)stream_id; (void)data; (void)component_id;
+}
+
+static void cb_new_selected_pair(NiceAgent *agent, guint stream_id, guint component_id,
+ gchar *lfoundation, gchar* rfoundation, gpointer data)
+{
+ g_debug ("test-drop-invalid:%s: %p", G_STRFUNC, data);
+
+ if (GPOINTER_TO_UINT (data) == 1)
+ ++global_lagent_cands;
+ else if (GPOINTER_TO_UINT (data) == 2)
+ ++global_ragent_cands;
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent; (void)stream_id; (void)component_id; (void)lfoundation; (void)rfoundation;
+}
+
+static void cb_new_candidate(NiceAgent *agent, guint stream_id, guint component_id,
+ gchar *foundation, gpointer data)
+{
+ g_debug ("test-drop-invalid:%s: %p", G_STRFUNC, data);
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent; (void)stream_id; (void)data; (void)component_id; (void)foundation;
+}
+
+static void cb_initial_binding_request_received(NiceAgent *agent, guint stream_id, gpointer data)
+{
+ g_debug ("test-drop-invalid:%s: %p", G_STRFUNC, data);
+
+ if (GPOINTER_TO_UINT (data) == 1)
+ global_lagent_ibr_received = TRUE;
+ else if (GPOINTER_TO_UINT (data) == 2)
+ global_ragent_ibr_received = TRUE;
+
+ if (global_exit_when_ibr_received) {
+ g_debug ("Received initial binding request. Stopping mailoop");
+ g_main_loop_quit (global_mainloop);
+ }
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent; (void)stream_id; (void)data;
+}
+
+static void set_candidates (NiceAgent *from, guint from_stream,
+ NiceAgent *to, guint to_stream, guint component)
+{
+ GSList *cands = NULL;
+ GSList *peer_cands = NULL;
+ GSList *item1, *item2;
+
+ cands = nice_agent_get_local_candidates (from, from_stream, component);
+ peer_cands = nice_agent_get_local_candidates (to, to_stream, component);
+
+ /*
+ * Core of the test:
+ *
+ * Send packets that shoudl be dropped.
+ */
+
+ for (item1 = cands; item1; item1 = item1->next) {
+ NiceCandidate *cand = item1->data;
+ NiceSocket *nicesock = cand->sockptr;
+
+ g_assert (nicesock);
+
+ for (item2 = peer_cands; item2; item2 = item2->next) {
+ NiceCandidate *target_cand = item2->data;
+
+ nice_socket_send (nicesock, &target_cand->addr, 12, "123456789AB");
+ }
+
+ }
+
+ nice_agent_set_remote_candidates (to, to_stream, component, cands);
+
+ g_slist_free_full (cands, (GDestroyNotify) nice_candidate_free);
+ g_slist_free_full (peer_cands, (GDestroyNotify) nice_candidate_free);
+}
+
+static void set_credentials (NiceAgent *lagent, guint lstream,
+ NiceAgent *ragent, guint rstream)
+{
+ gchar *ufrag = NULL, *password = NULL;
+
+ nice_agent_get_local_credentials(lagent, lstream, &ufrag, &password);
+ nice_agent_set_remote_credentials (ragent, rstream, ufrag, password);
+ g_free (ufrag);
+ g_free (password);
+ nice_agent_get_local_credentials(ragent, rstream, &ufrag, &password);
+ nice_agent_set_remote_credentials (lagent, lstream, ufrag, password);
+ g_free (ufrag);
+ g_free (password);
+}
+
+static guint16
+get_port (NiceAgent *agent, guint stream_id, guint component_id)
+{
+ GSList *cands = nice_agent_get_local_candidates (agent, stream_id,
+ component_id);
+ GSList *item;
+ guint16 port = 0;
+
+ g_assert (cands != NULL);
+
+ for (item = cands; item; item = item->next) {
+ NiceCandidate *cand = item->data;
+ port = nice_address_get_port (&cand->addr);
+ break;
+ }
+ g_assert (port != 0);
+
+ g_slist_free_full (cands, (GDestroyNotify) nice_candidate_free);
+
+ return port;
+}
+
+static int run_full_test (NiceAgent *lagent, NiceAgent *ragent, NiceAddress *baseaddr, guint ready, guint failed)
+{
+ guint ls_id, rs_id;
+ gint ret;
+ guint16 port;
+
+ /* XXX: dear compiler, this is for you */
+ (void)baseaddr;
+
+ /* step: initialize variables modified by the callbacks */
+ global_components_ready = 0;
+ global_components_ready_exit = ready;
+ global_components_failed = 0;
+ global_components_failed_exit = failed;
+ global_lagent_gathering_done = FALSE;
+ global_ragent_gathering_done = FALSE;
+ global_lagent_ibr_received =
+ global_ragent_ibr_received = FALSE;
+ global_lagent_cands =
+ global_ragent_cands = 0;
+
+ g_object_set (G_OBJECT (lagent), "controlling-mode", TRUE, NULL);
+ g_object_set (G_OBJECT (ragent), "controlling-mode", FALSE, NULL);
+
+ /* step: add one stream, with RTP+RTCP components, to each agent */
+ ls_id = nice_agent_add_stream (lagent, 2);
+
+ rs_id = nice_agent_add_stream (ragent, 2);
+ g_assert (ls_id > 0);
+ g_assert (rs_id > 0);
+
+ /* Gather candidates and test nice_agent_set_port_range */
+ nice_agent_set_port_range (lagent, ls_id, 1, 10000, 11000);
+ nice_agent_set_port_range (lagent, ls_id, 2, 11000, 12000);
+ g_assert (nice_agent_gather_candidates (lagent, ls_id) == TRUE);
+
+ port = get_port (lagent, ls_id, 1);
+ nice_agent_set_port_range (ragent, rs_id, 1, 12000, 13000);
+ nice_agent_set_port_range (ragent, rs_id, 2, port, port);
+ g_assert (nice_agent_gather_candidates (ragent, rs_id) == FALSE);
+ g_assert (nice_agent_get_local_candidates (ragent, rs_id, 1) == NULL);
+ g_assert (nice_agent_get_local_candidates (ragent, rs_id, 2) == NULL);
+ nice_agent_set_port_range (ragent, rs_id, 2, 13000, 14000);
+ g_assert (nice_agent_gather_candidates (ragent, rs_id) == TRUE);
+
+ {
+ GSList *cands = NULL, *i;
+ NiceCandidate *cand = NULL;
+
+ cands = nice_agent_get_local_candidates (lagent, ls_id, 1);
+ g_assert (g_slist_length (cands) == 1);
+ cand = cands->data;
+ g_assert (cand->type == NICE_CANDIDATE_TYPE_HOST);
+ g_assert (nice_address_get_port (&cand->addr) >= 10000);
+ g_assert (nice_address_get_port (&cand->addr) <= 11000);
+ for (i = cands; i; i = i->next)
+ nice_candidate_free ((NiceCandidate *) i->data);
+ g_slist_free (cands);
+
+ cands = nice_agent_get_local_candidates (lagent, ls_id, 2);
+ g_assert (g_slist_length (cands) == 1);
+ cand = cands->data;
+ g_assert (cand->type == NICE_CANDIDATE_TYPE_HOST);
+ g_assert (nice_address_get_port (&cand->addr) >= 11000);
+ g_assert (nice_address_get_port (&cand->addr) <= 12000);
+ for (i = cands; i; i = i->next)
+ nice_candidate_free ((NiceCandidate *) i->data);
+ g_slist_free (cands);
+
+ cands = nice_agent_get_local_candidates (ragent, rs_id, 1);
+ g_assert (g_slist_length (cands) == 1);
+ cand = cands->data;
+ g_assert (cand->type == NICE_CANDIDATE_TYPE_HOST);
+ g_assert (nice_address_get_port (&cand->addr) >= 12000);
+ g_assert (nice_address_get_port (&cand->addr) <= 13000);
+ for (i = cands; i; i = i->next)
+ nice_candidate_free ((NiceCandidate *) i->data);
+ g_slist_free (cands);
+
+ cands = nice_agent_get_local_candidates (ragent, rs_id, 2);
+ g_assert (g_slist_length (cands) == 1);
+ cand = cands->data;
+ g_assert (cand->type == NICE_CANDIDATE_TYPE_HOST);
+ g_assert (nice_address_get_port (&cand->addr) >= 13000);
+ g_assert (nice_address_get_port (&cand->addr) <= 14000);
+ for (i = cands; i; i = i->next)
+ nice_candidate_free ((NiceCandidate *) i->data);
+ g_slist_free (cands);
+
+ }
+
+ /* step: attach to mainloop (needed to register the fds) */
+ nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv,
+ GUINT_TO_POINTER (1));
+ nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTCP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv,
+ GUINT_TO_POINTER (1));
+ nice_agent_attach_recv (ragent, rs_id, NICE_COMPONENT_TYPE_RTP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv,
+ GUINT_TO_POINTER (2));
+ nice_agent_attach_recv (ragent, rs_id, NICE_COMPONENT_TYPE_RTCP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv,
+ GUINT_TO_POINTER (2));
+
+ /* step: run mainloop until local candidates are ready
+ * (see timer_cb() above) */
+ if (global_lagent_gathering_done != TRUE ||
+ global_ragent_gathering_done != TRUE) {
+ g_debug ("test-drop-invalid: Added streams, running mainloop until 'candidate-gathering-done'...");
+ g_main_loop_run (global_mainloop);
+ g_assert (global_lagent_gathering_done == TRUE);
+ g_assert (global_ragent_gathering_done == TRUE);
+ }
+
+ set_credentials (lagent, ls_id, ragent, rs_id);
+
+ /* step: pass the remote candidates to agents */
+ set_candidates (ragent, rs_id, lagent, ls_id, NICE_COMPONENT_TYPE_RTP);
+ set_candidates (ragent, rs_id, lagent, ls_id, NICE_COMPONENT_TYPE_RTCP);
+ set_candidates (lagent, ls_id, ragent, rs_id, NICE_COMPONENT_TYPE_RTP);
+ set_candidates (lagent, ls_id, ragent, rs_id, NICE_COMPONENT_TYPE_RTCP);
+
+ g_debug ("test-drop-invalid: Set properties, next running mainloop until connectivity checks succeed...");
+
+ /* step: run the mainloop until connectivity checks succeed
+ * (see timer_cb() above) */
+ g_main_loop_run (global_mainloop);
+
+ /* note: verify that STUN binding requests were sent */
+ g_assert (global_lagent_ibr_received == TRUE);
+ g_assert (global_ragent_ibr_received == TRUE);
+
+ /* note: Send a packet from another address */
+ /* These should also be ignored */
+ {
+ NiceCandidate *local_cand = NULL;
+ NiceCandidate *remote_cand = NULL;
+ NiceSocket *tmpsock;
+
+ g_assert (nice_agent_get_selected_pair (lagent, ls_id, 1, &local_cand,
+ &remote_cand));
+ g_assert (local_cand);
+ g_assert (remote_cand);
+
+ tmpsock = nice_udp_bsd_socket_new (NULL);
+ nice_socket_send (tmpsock, &remote_cand->addr, 4, "ABCD");
+ nice_socket_send (tmpsock, &local_cand->addr, 5, "ABCDE");
+ nice_socket_free (tmpsock);
+ }
+
+ /* note: test payload send and receive */
+ global_ragent_read = 0;
+ ret = nice_agent_send (lagent, ls_id, 1, 16, "1234567812345678");
+ g_assert (ret != -1);
+ g_debug ("Sent %d bytes", ret);
+ g_assert (ret == 16);
+ while (global_ragent_read != 16)
+ g_main_context_iteration (NULL, TRUE);
+ g_assert (global_ragent_read == 16);
+
+ g_debug ("test-drop-invalid: Ran mainloop, removing streams...");
+
+ /* step: clean up resources and exit */
+
+ nice_agent_remove_stream (lagent, ls_id);
+ nice_agent_remove_stream (ragent, rs_id);
+
+ return 0;
+}
+
+int main (void)
+{
+ NiceAgent *lagent, *ragent; /* agent's L and R */
+ NiceAddress baseaddr;
+ int result;
+ guint timer_id;
+
+#ifdef G_OS_WIN32
+ WSADATA w;
+
+ WSAStartup(0x0202, &w);
+#endif
+
+ global_mainloop = g_main_loop_new (NULL, FALSE);
+
+ /* step: create the agents L and R */
+ lagent = nice_agent_new (g_main_loop_get_context (global_mainloop),
+ NICE_COMPATIBILITY_RFC5245);
+ ragent = nice_agent_new (g_main_loop_get_context (global_mainloop),
+ NICE_COMPATIBILITY_RFC5245);
+
+ g_object_set (G_OBJECT (lagent), "ice-tcp", FALSE, NULL);
+ g_object_set (G_OBJECT (ragent), "ice-tcp", FALSE, NULL);
+
+ g_object_set (G_OBJECT (lagent), "upnp", FALSE, NULL);
+ g_object_set (G_OBJECT (ragent), "upnp", FALSE, NULL);
+
+ nice_agent_set_software (lagent, "test-drop-invalid, Left Agent");
+ nice_agent_set_software (ragent, "test-drop-invalid, Right Agent");
+
+ /* step: add a timer to catch state changes triggered by signals */
+ timer_id = g_timeout_add (30000, timer_cb, NULL);
+
+ /* step: specify which local interface to use */
+ if (!nice_address_set_from_string (&baseaddr, "127.0.0.1"))
+ g_assert_not_reached ();
+ nice_agent_add_local_address (lagent, &baseaddr);
+ nice_agent_add_local_address (ragent, &baseaddr);
+
+ g_signal_connect (G_OBJECT (lagent), "candidate-gathering-done",
+ G_CALLBACK (cb_candidate_gathering_done), GUINT_TO_POINTER(1));
+ g_signal_connect (G_OBJECT (ragent), "candidate-gathering-done",
+ G_CALLBACK (cb_candidate_gathering_done), GUINT_TO_POINTER (2));
+ g_signal_connect (G_OBJECT (lagent), "component-state-changed",
+ G_CALLBACK (cb_component_state_changed), GUINT_TO_POINTER (1));
+ g_signal_connect (G_OBJECT (ragent), "component-state-changed",
+ G_CALLBACK (cb_component_state_changed), GUINT_TO_POINTER (2));
+ g_signal_connect (G_OBJECT (lagent), "new-selected-pair",
+ G_CALLBACK (cb_new_selected_pair), GUINT_TO_POINTER(1));
+ g_signal_connect (G_OBJECT (ragent), "new-selected-pair",
+ G_CALLBACK (cb_new_selected_pair), GUINT_TO_POINTER (2));
+ g_signal_connect (G_OBJECT (lagent), "new-candidate",
+ G_CALLBACK (cb_new_candidate), GUINT_TO_POINTER (1));
+ g_signal_connect (G_OBJECT (ragent), "new-candidate",
+ G_CALLBACK (cb_new_candidate), GUINT_TO_POINTER (2));
+ g_signal_connect (G_OBJECT (lagent), "initial-binding-request-received",
+ G_CALLBACK (cb_initial_binding_request_received),
+ GUINT_TO_POINTER (1));
+ g_signal_connect (G_OBJECT (ragent), "initial-binding-request-received",
+ G_CALLBACK (cb_initial_binding_request_received),
+ GUINT_TO_POINTER (2));
+
+ g_object_set (G_OBJECT (lagent), "upnp", FALSE, NULL);
+ g_object_set (G_OBJECT (ragent), "upnp", FALSE, NULL);
+
+
+ /* step: run test the first time */
+ g_debug ("test-drop-invalid: TEST STARTS / running test for the 1st time");
+ result = run_full_test (lagent, ragent, &baseaddr, 4 ,0);
+ priv_print_global_status ();
+ g_assert (result == 0);
+ g_assert (global_lagent_state[0] == NICE_COMPONENT_STATE_READY);
+ g_assert (global_lagent_state[1] == NICE_COMPONENT_STATE_READY);
+ g_assert (global_ragent_state[0] == NICE_COMPONENT_STATE_READY);
+ g_assert (global_ragent_state[1] == NICE_COMPONENT_STATE_READY);
+ /* When using TURN, we get peer reflexive candidates for the host cands
+ that we removed so we can get another new_selected_pair signal later
+ depending on timing/racing, we could double (or not) the amount we expected
+ */
+
+ /* note: verify that correct number of local candidates were reported */
+ g_assert (global_lagent_cands == 2);
+ g_assert (global_ragent_cands == 2);
+
+ g_object_unref (lagent);
+ g_object_unref (ragent);
+
+ g_main_loop_unref (global_mainloop);
+ global_mainloop = NULL;
+
+ g_source_remove (timer_id);
+#ifdef G_OS_WIN32
+ WSACleanup();
+#endif
+ return result;
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * Contains a unit test for functionality to fallback to non-ICE
+ * operation if remote party does not support ICE.
+ *
+ * (C) 2007 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Kai Vehmanen, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "agent.h"
+#include "agent-priv.h" /* for testing purposes */
+
+#include <stdlib.h>
+#include <string.h>
+#ifdef _WIN32
+#include <io.h>
+#endif
+
+
+static NiceComponentState global_lagent_state = NICE_COMPONENT_STATE_LAST;
+static NiceComponentState global_ragent_state = NICE_COMPONENT_STATE_LAST;
+static guint global_components_ready = 0;
+static guint global_components_ready_exit = 0;
+static guint global_components_failed = 0;
+static guint global_components_failed_exit = 0;
+static GMainLoop *global_mainloop = NULL;
+static gboolean global_lagent_gathering_done = FALSE;
+static gboolean global_ragent_gathering_done = FALSE;
+static gboolean global_lagent_ibr_received = FALSE;
+static gboolean global_ragent_ibr_received = FALSE;
+static int global_lagent_cands = 0;
+static int global_ragent_cands = 0;
+static gint global_ragent_read = 0;
+static gint global_ragent_read_exit = 0;
+static gboolean global_accept_non_data = TRUE;
+
+static void priv_print_global_status (void)
+{
+ g_debug ("\tgathering_done=%d", global_lagent_gathering_done && global_ragent_gathering_done);
+ g_debug ("\tlstate=%d", global_lagent_state);
+ g_debug ("\trstate=%d", global_ragent_state);
+}
+
+static gboolean timer_cb (gpointer pointer)
+{
+ g_debug ("test-fallback:%s: %p", G_STRFUNC, pointer);
+
+ /* signal status via a global variable */
+
+ /* note: should not be reached, abort */
+ g_error ("ERROR: test has got stuck, aborting...");
+
+ return FALSE;
+}
+
+static void cb_nice_recv (NiceAgent *agent, guint stream_id, guint component_id, guint len, gchar *buf, gpointer user_data)
+{
+ g_debug ("test-fallback:%s: %p", G_STRFUNC, user_data);
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent; (void)stream_id; (void)component_id; (void)buf;
+
+ /*
+ * Lets ignore stun packets that got through
+ */
+ if (len != 16 || strncmp ("1234567812345678", buf, 16)) {
+ if (global_accept_non_data)
+ return;
+ else
+ g_error ("Got non-data packet of lenght %u", len);
+ }
+
+ if ((intptr_t)user_data == 2) {
+ global_ragent_read += len;
+
+ if (global_ragent_read == global_ragent_read_exit)
+ g_main_loop_quit (global_mainloop);
+ }
+}
+
+static void cb_candidate_gathering_done(NiceAgent *agent, guint stream_id, gpointer data)
+{
+ g_debug ("test-fallback:%s: %p", G_STRFUNC, data);
+
+ if ((intptr_t)data == 1)
+ global_lagent_gathering_done = TRUE;
+ else if ((intptr_t)data == 2)
+ global_ragent_gathering_done = TRUE;
+
+ if (global_lagent_gathering_done &&
+ global_ragent_gathering_done)
+ g_main_loop_quit (global_mainloop);
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent;
+}
+
+static void cb_component_state_changed (NiceAgent *agent, guint stream_id, guint component_id, guint state, gpointer data)
+{
+ g_debug ("test-fallback:%s: %p", G_STRFUNC, data);
+
+ if ((intptr_t)data == 1)
+ global_lagent_state = state;
+ else if ((intptr_t)data == 2)
+ global_ragent_state = state;
+
+ if (state == NICE_COMPONENT_STATE_READY)
+ global_components_ready++;
+ if (state == NICE_COMPONENT_STATE_FAILED)
+ global_components_failed++;
+
+ g_debug ("test-fallback: READY %u exit at %u.", global_components_ready, global_components_ready_exit);
+
+ /* signal status via a global variable */
+ if (global_components_ready == global_components_ready_exit) {
+ g_main_loop_quit (global_mainloop);
+ return;
+ }
+
+ /* signal status via a global variable */
+ if (global_components_failed == global_components_failed_exit) {
+ g_main_loop_quit (global_mainloop);
+ return;
+ }
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent; (void)stream_id; (void)data; (void)component_id;
+}
+
+static void cb_new_selected_pair(NiceAgent *agent, guint stream_id, guint component_id,
+ gchar *lfoundation, gchar* rfoundation, gpointer data)
+{
+ g_debug ("test-fallback:%s: %p", G_STRFUNC, data);
+
+ if ((intptr_t)data == 1)
+ ++global_lagent_cands;
+ else if ((intptr_t)data == 2)
+ ++global_ragent_cands;
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent; (void)stream_id; (void)component_id; (void)lfoundation; (void)rfoundation;
+}
+
+static void cb_new_candidate(NiceAgent *agent, guint stream_id, guint component_id,
+ gchar *foundation, gpointer data)
+{
+ g_debug ("test-fallback:%s: %p", G_STRFUNC, data);
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent; (void)stream_id; (void)data; (void)component_id; (void)foundation;
+}
+
+static void cb_initial_binding_request_received(NiceAgent *agent, guint stream_id, gpointer data)
+{
+ g_debug ("test-fallback:%s: %p", G_STRFUNC, data);
+
+ if ((intptr_t)data == 1)
+ global_lagent_ibr_received = TRUE;
+ else if ((intptr_t)data == 2)
+ global_ragent_ibr_received = TRUE;
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent; (void)stream_id; (void)data;
+}
+
+static void priv_get_local_addr (NiceAgent *agent, guint stream_id, guint component_id, NiceAddress *dstaddr)
+{
+ GSList *cands, *i;
+ cands = nice_agent_get_local_candidates(agent, stream_id, component_id);
+ for (i = cands; i; i = i->next) {
+ NiceCandidate *cand = i->data;
+ if (cand) {
+ g_assert (dstaddr);
+ *dstaddr = cand->addr;
+ break;
+ }
+ }
+ for (i = cands; i; i = i->next)
+ nice_candidate_free ((NiceCandidate *) i->data);
+ g_slist_free (cands);
+}
+
+static int run_fallback_test (NiceAgent *lagent, NiceAgent *ragent, NiceAddress *baseaddr)
+{
+ NiceAddress laddr, raddr, laddr_rtcp, raddr_rtcp;
+ NiceCandidate cdes;
+ GSList *cands;
+ guint ls_id, rs_id;
+
+ memset (&cdes, 0, sizeof(NiceCandidate));
+ cdes.priority = 100000;
+ strcpy (cdes.foundation, "1");
+ cdes.type = NICE_CANDIDATE_TYPE_HOST;
+ cdes.transport = NICE_CANDIDATE_TRANSPORT_UDP;
+ cdes.base_addr = *baseaddr;
+
+ /* step: initialize variables modified by the callbacks */
+ global_components_ready = 0;
+ global_components_ready_exit = 4;
+ global_components_failed = 0;
+ global_components_failed_exit = 4;
+ global_lagent_gathering_done = FALSE;
+ global_ragent_gathering_done = FALSE;
+ global_lagent_ibr_received =
+ global_ragent_ibr_received = FALSE;
+ global_lagent_cands =
+ global_ragent_cands = 0;
+ global_ragent_read_exit = -1;
+
+ g_object_set (G_OBJECT (lagent), "controlling-mode", TRUE, NULL);
+ g_object_set (G_OBJECT (ragent), "controlling-mode", FALSE, NULL);
+
+ /* step: add one stream, with RTP+RTCP components, to each agent */
+ ls_id = nice_agent_add_stream (lagent, 2);
+ rs_id = nice_agent_add_stream (ragent, 2);
+ g_assert (ls_id > 0);
+ g_assert (rs_id > 0);
+
+ nice_agent_gather_candidates (lagent, ls_id);
+ nice_agent_gather_candidates (ragent, rs_id);
+
+ /* step: attach to mainloop (needed to register the fds) */
+ nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv, (gpointer)1);
+ nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTCP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv, (gpointer)1);
+ nice_agent_attach_recv (ragent, rs_id, NICE_COMPONENT_TYPE_RTP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv, (gpointer)2);
+ nice_agent_attach_recv (ragent, rs_id, NICE_COMPONENT_TYPE_RTCP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv, (gpointer)2);
+
+ /* step: run mainloop until local candidates are ready
+ * (see timer_cb() above) */
+ if (global_lagent_gathering_done != TRUE ||
+ global_ragent_gathering_done != TRUE) {
+ g_debug ("test-fallback: Added streams, running mainloop until 'candidate-gathering-done'...");
+ g_main_loop_run (global_mainloop);
+ g_assert (global_lagent_gathering_done == TRUE);
+ g_assert (global_ragent_gathering_done == TRUE);
+ }
+
+ /* step: find out the local candidates of each agent */
+
+ priv_get_local_addr (ragent, rs_id, NICE_COMPONENT_TYPE_RTP, &raddr);
+ g_debug ("test-fallback: local RTP port R %u",
+ nice_address_get_port (&raddr));
+
+ priv_get_local_addr (lagent, ls_id, NICE_COMPONENT_TYPE_RTP, &laddr);
+ g_debug ("test-fallback: local RTP port L %u",
+ nice_address_get_port (&laddr));
+
+ priv_get_local_addr (ragent, rs_id, NICE_COMPONENT_TYPE_RTCP, &raddr_rtcp);
+ g_debug ("test-fallback: local RTCP port R %u",
+ nice_address_get_port (&raddr_rtcp));
+
+ priv_get_local_addr (lagent, ls_id, NICE_COMPONENT_TYPE_RTCP, &laddr_rtcp);
+ g_debug ("test-fallback: local RTCP port L %u",
+ nice_address_get_port (&laddr_rtcp));
+
+ /* step: exchange candidate information but not the credentials */
+
+ cands = g_slist_append (NULL, &cdes);
+ cdes.component_id = NICE_COMPONENT_TYPE_RTP;
+ cdes.addr = raddr;
+ nice_agent_set_remote_candidates (lagent, ls_id, NICE_COMPONENT_TYPE_RTP, cands);
+ cdes.addr = laddr;
+ nice_agent_set_remote_candidates (ragent, rs_id, NICE_COMPONENT_TYPE_RTP, cands);
+ cdes.component_id = NICE_COMPONENT_TYPE_RTCP;
+ cdes.addr = raddr_rtcp;
+ nice_agent_set_remote_candidates (lagent, ls_id, NICE_COMPONENT_TYPE_RTCP, cands);
+ cdes.addr = laddr_rtcp;
+ nice_agent_set_remote_candidates (ragent, rs_id, NICE_COMPONENT_TYPE_RTCP, cands);
+
+ /* step: fall back to non-ICE mode on both sides */
+ g_assert (nice_agent_set_selected_pair (lagent, ls_id, NICE_COMPONENT_TYPE_RTP, "1", "1") == TRUE);
+ g_assert (nice_agent_set_selected_pair (lagent, ls_id, NICE_COMPONENT_TYPE_RTCP, "1", "1") == TRUE);
+ g_assert (nice_agent_set_selected_pair (ragent, rs_id, NICE_COMPONENT_TYPE_RTP, "1", "1") == TRUE);
+ g_assert (nice_agent_set_selected_pair (ragent, rs_id, NICE_COMPONENT_TYPE_RTCP, "1", "1") == TRUE);
+
+ g_debug ("test-fallback: Requested for fallback, running mainloop until component state change is completed...");
+
+ /* step: run the mainloop until connectivity checks succeed
+ * (see timer_cb() above) */
+ if (global_components_ready < global_components_ready_exit)
+ g_main_loop_run (global_mainloop);
+
+ /* note: verify that agents are in correct state */
+ g_assert (global_lagent_state == NICE_COMPONENT_STATE_READY);
+ g_assert (global_ragent_state == NICE_COMPONENT_STATE_READY);
+
+ /* step: next send a packet -> should work even if no ICE processing
+ * has been done */
+
+ g_debug ("test-fallback: Sent a payload packet, run mainloop until packet received.");
+
+ /* step: send a new test packet from L ot R */
+ global_ragent_read = 0;
+ g_assert (nice_agent_send (lagent, ls_id, 1, 16, "1234567812345678") == 16);
+ global_ragent_read_exit = 16;
+ g_main_loop_run (global_mainloop);
+
+ /* note: verify that payload was succesfully received */
+ g_assert (global_ragent_read == 16);
+
+ g_debug ("test-fallback: Ran mainloop, removing streams...");
+
+ /* step: clean up resources and exit */
+
+ g_slist_free (cands);
+ nice_agent_remove_stream (lagent, ls_id);
+ nice_agent_remove_stream (ragent, rs_id);
+
+ g_debug ("test-fallback: test COMPLETED");
+
+ return 0;
+}
+
+
+static int run_safe_fallback_test (NiceAgent *lagent, NiceAgent *ragent, NiceAddress *baseaddr)
+{
+ NiceAddress laddr, raddr, laddr_rtcp, raddr_rtcp;
+ NiceCandidate cdes;
+ guint ls_id, rs_id;
+
+ memset (&cdes, 0, sizeof(NiceCandidate));
+ cdes.priority = 100000;
+ strcpy (cdes.foundation, "1");
+ cdes.type = NICE_CANDIDATE_TYPE_HOST;
+ cdes.transport = NICE_CANDIDATE_TRANSPORT_UDP;
+ cdes.base_addr = *baseaddr;
+
+ /* step: initialize variables modified by the callbacks */
+ global_components_ready = 0;
+ global_components_ready_exit = 4;
+ global_components_failed = 0;
+ global_components_failed_exit = 4;
+ global_lagent_gathering_done = FALSE;
+ global_ragent_gathering_done = FALSE;
+ global_lagent_ibr_received =
+ global_ragent_ibr_received = FALSE;
+ global_lagent_cands =
+ global_ragent_cands = 0;
+ global_ragent_read_exit = -1;
+ global_accept_non_data = FALSE;
+
+ g_object_set (G_OBJECT (lagent), "controlling-mode", TRUE, NULL);
+ g_object_set (G_OBJECT (ragent), "controlling-mode", FALSE, NULL);
+
+ /* step: add one stream, with RTP+RTCP components, to each agent */
+ ls_id = nice_agent_add_stream (lagent, 2);
+ rs_id = nice_agent_add_stream (ragent, 2);
+ g_assert (ls_id > 0);
+ g_assert (rs_id > 0);
+
+ nice_agent_gather_candidates (lagent, ls_id);
+ nice_agent_gather_candidates (ragent, rs_id);
+
+ /* step: attach to mainloop (needed to register the fds) */
+ nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv, (gpointer)1);
+ nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTCP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv, (gpointer)1);
+ nice_agent_attach_recv (ragent, rs_id, NICE_COMPONENT_TYPE_RTP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv, (gpointer)2);
+ nice_agent_attach_recv (ragent, rs_id, NICE_COMPONENT_TYPE_RTCP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv, (gpointer)2);
+
+ /* step: run mainloop until local candidates are ready
+ * (see timer_cb() above) */
+ if (global_lagent_gathering_done != TRUE ||
+ global_ragent_gathering_done != TRUE) {
+ g_debug ("test-fallback: Added streams, running mainloop until 'candidate-gathering-done'...");
+ g_main_loop_run (global_mainloop);
+ g_assert (global_lagent_gathering_done == TRUE);
+ g_assert (global_ragent_gathering_done == TRUE);
+ }
+
+ /* step: find out the local candidates of each agent */
+
+ priv_get_local_addr (ragent, rs_id, NICE_COMPONENT_TYPE_RTP, &raddr);
+ g_debug ("test-fallback: local RTP port R %u",
+ nice_address_get_port (&raddr));
+
+ priv_get_local_addr (lagent, ls_id, NICE_COMPONENT_TYPE_RTP, &laddr);
+ g_debug ("test-fallback: local RTP port L %u",
+ nice_address_get_port (&laddr));
+
+ priv_get_local_addr (ragent, rs_id, NICE_COMPONENT_TYPE_RTCP, &raddr_rtcp);
+ g_debug ("test-fallback: local RTCP port R %u",
+ nice_address_get_port (&raddr_rtcp));
+
+ priv_get_local_addr (lagent, ls_id, NICE_COMPONENT_TYPE_RTCP, &laddr_rtcp);
+ g_debug ("test-fallback: local RTCP port L %u",
+ nice_address_get_port (&laddr_rtcp));
+
+ /* step: exchange candidate information but not the credentials */
+
+ cdes.component_id = NICE_COMPONENT_TYPE_RTP;
+ cdes.addr = raddr;
+ g_assert (nice_agent_set_selected_remote_candidate (lagent, ls_id, NICE_COMPONENT_TYPE_RTP, &cdes));
+
+ cdes.addr = laddr;
+ g_assert (nice_agent_set_selected_remote_candidate (ragent, rs_id, NICE_COMPONENT_TYPE_RTP, &cdes));
+
+ cdes.component_id = NICE_COMPONENT_TYPE_RTCP;
+ cdes.addr = raddr_rtcp;
+ g_assert (nice_agent_set_selected_remote_candidate (lagent, ls_id, NICE_COMPONENT_TYPE_RTCP, &cdes));
+
+ cdes.addr = laddr_rtcp;
+ g_assert (nice_agent_set_selected_remote_candidate (ragent, rs_id, NICE_COMPONENT_TYPE_RTCP, &cdes));
+
+ g_debug ("test-fallback: Requested for fallback, running mainloop until component state change is completed...");
+
+ /* step: run the mainloop until connectivity checks succeed
+ * (see timer_cb() above) */
+ if (global_components_ready < global_components_ready_exit)
+ g_main_loop_run (global_mainloop);
+
+ /* note: verify that agents are in correct state */
+ g_assert (global_lagent_state == NICE_COMPONENT_STATE_READY);
+ g_assert (global_ragent_state == NICE_COMPONENT_STATE_READY);
+
+ /* step: next send a packet -> should work even if no ICE processing
+ * has been done */
+
+ g_debug ("test-fallback: Sent a payload packet, run mainloop until packet received.");
+
+ /* step: send a new test packet from L ot R */
+ global_ragent_read = 0;
+ g_assert (nice_agent_send (lagent, ls_id, 1, 16, "1234567812345678") == 16);
+ global_ragent_read_exit = 16;
+ g_main_loop_run (global_mainloop);
+
+ /* note: verify that payload was succesfully received */
+ g_assert (global_ragent_read == 16);
+
+ g_debug ("test-fallback: Ran mainloop, removing streams...");
+
+ /* step: clean up resources and exit */
+
+ nice_agent_remove_stream (lagent, ls_id);
+ nice_agent_remove_stream (ragent, rs_id);
+
+ g_debug ("test-fallback: test COMPLETED");
+
+ return 0;
+}
+
+int main (void)
+{
+ NiceAgent *lagent, *ragent; /* agent's L and R */
+ NiceAddress baseaddr;
+ int result;
+ guint timer_id;
+ const char *stun_server = NULL, *stun_server_port = NULL;
+
+#ifdef G_OS_WIN32
+ WSADATA w;
+
+ WSAStartup(0x0202, &w);
+#endif
+
+ global_mainloop = g_main_loop_new (NULL, FALSE);
+
+ /* Note: impl limits ...
+ * - no multi-stream support
+ * - no IPv6 support
+ */
+
+ /* step: create the agents L and R */
+ lagent = nice_agent_new (g_main_loop_get_context (global_mainloop), NICE_COMPATIBILITY_RFC5245);
+ ragent = nice_agent_new (g_main_loop_get_context (global_mainloop), NICE_COMPATIBILITY_RFC5245);
+
+ g_object_set (G_OBJECT (lagent), "upnp", FALSE, NULL);
+ g_object_set (G_OBJECT (ragent), "upnp", FALSE, NULL);
+
+ /* step: add a timer to catch state changes triggered by signals */
+ timer_id = g_timeout_add (30000, timer_cb, NULL);
+
+ /* step: specify which local interface to use */
+ if (!nice_address_set_from_string (&baseaddr, "127.0.0.1"))
+ g_assert_not_reached ();
+ nice_agent_add_local_address (lagent, &baseaddr);
+ nice_agent_add_local_address (ragent, &baseaddr);
+
+ g_signal_connect (G_OBJECT (lagent), "candidate-gathering-done",
+ G_CALLBACK (cb_candidate_gathering_done), (gpointer)1);
+ g_signal_connect (G_OBJECT (ragent), "candidate-gathering-done",
+ G_CALLBACK (cb_candidate_gathering_done), (gpointer)2);
+ g_signal_connect (G_OBJECT (lagent), "component-state-changed",
+ G_CALLBACK (cb_component_state_changed), (gpointer)1);
+ g_signal_connect (G_OBJECT (ragent), "component-state-changed",
+ G_CALLBACK (cb_component_state_changed), (gpointer)2);
+ g_signal_connect (G_OBJECT (lagent), "new-selected-pair",
+ G_CALLBACK (cb_new_selected_pair), (gpointer)1);
+ g_signal_connect (G_OBJECT (ragent), "new-selected-pair",
+ G_CALLBACK (cb_new_selected_pair), (gpointer)2);
+ g_signal_connect (G_OBJECT (lagent), "new-candidate",
+ G_CALLBACK (cb_new_candidate), (gpointer)1);
+ g_signal_connect (G_OBJECT (ragent), "new-candidate",
+ G_CALLBACK (cb_new_candidate), (gpointer)2);
+ g_signal_connect (G_OBJECT (lagent), "initial-binding-request-received",
+ G_CALLBACK (cb_initial_binding_request_received), (gpointer)1);
+ g_signal_connect (G_OBJECT (ragent), "initial-binding-request-received",
+ G_CALLBACK (cb_initial_binding_request_received), (gpointer)2);
+
+ stun_server = getenv ("NICE_STUN_SERVER");
+ stun_server_port = getenv ("NICE_STUN_SERVER_PORT");
+ if (stun_server) {
+ g_object_set (G_OBJECT (lagent), "stun-server", stun_server, NULL);
+ g_object_set (G_OBJECT (lagent), "stun-server-port", atoi (stun_server_port), NULL);
+ g_object_set (G_OBJECT (ragent), "stun-server", stun_server, NULL);
+ g_object_set (G_OBJECT (ragent), "stun-server-port", atoi (stun_server_port), NULL);
+ }
+
+ /* step: run test the first time */
+ g_debug ("test-fallback: TEST STARTS / fallback test");
+ result = run_fallback_test (lagent, ragent, &baseaddr);
+ priv_print_global_status ();
+ g_assert (result == 0);
+ g_assert (global_lagent_state == NICE_COMPONENT_STATE_READY);
+ g_assert (global_ragent_state == NICE_COMPONENT_STATE_READY);
+
+ /* step: run the safe test without sending any stnu */
+ g_debug ("test-fallback: TEST STARTS / safe fallback test");
+ result = run_safe_fallback_test (lagent, ragent, &baseaddr);
+ priv_print_global_status ();
+ g_assert (result == 0);
+ g_assert (global_lagent_state == NICE_COMPONENT_STATE_READY);
+ g_assert (global_ragent_state == NICE_COMPONENT_STATE_READY);
+
+ g_object_unref (lagent);
+ g_object_unref (ragent);
+
+ g_main_loop_unref (global_mainloop);
+ global_mainloop = NULL;
+
+ g_source_remove (timer_id);
+#ifdef G_OS_WIN32
+ WSACleanup();
+#endif
+ return result;
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * Unit test for ICE full-mode related features.
+ *
+ * (C) 2007 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Kai Vehmanen, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "agent.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+
+#define USE_TURN 0
+#define USE_LOOPBACK 1
+#define USE_PROXY 0
+#define USE_UPNP 0
+#define USE_RELIABLE 0
+#define TEST_GOOGLE 0
+
+#define PROXY_IP "127.0.0.1"
+#define PROXY_PORT 1080
+#define PROXY_USERNAME NULL
+#define PROXY_PASSWORD NULL
+
+#if USE_PROXY
+#define PROXY_TYPE NICE_PROXY_TYPE_SOCKS5
+#else
+#define PROXY_TYPE NICE_PROXY_TYPE_NONE
+#endif
+
+#if TEST_GOOGLE
+#define NICE_COMPATIBILITY NICE_COMPATIBILITY_GOOGLE
+
+#if USE_TURN
+#undef USE_LOOPBACK
+#define USE_LOOPBACK 0
+
+#define TURN_IP "209.85.163.126"
+#define TURN_PORT 443
+#define TURN_USER "ih9ppiM0P6vN34DB"
+#define TURN_PASS ""
+#define TURN_USER2 TURN_USER
+#define TURN_PASS2 TURN_PASS
+#define TURN_TYPE NICE_RELAY_TYPE_TURN_TLS
+
+#endif
+
+#else
+#define NICE_COMPATIBILITY NICE_COMPATIBILITY_RFC5245
+#if USE_LOOPBACK
+#define USE_TURN_SERVER_ORG 1
+#else
+#define USE_TURN_SERVER_ORG 0
+#endif
+
+#define NUMB_IP "64.251.22.149"
+#define NUMB_PORT 3478
+#define NUMB_USER "youness.alaoui@collabora.co.uk"
+#define NUMB_PASS "badger"
+
+#define TSORG_IP "127.0.0.1"
+#define TSORG_PORT 3478
+#define TSORG_USER "toto"
+#define TSORG_PASS "password"
+
+
+#if USE_TURN_SERVER_ORG
+#define TURN_IP TSORG_IP
+#define TURN_PORT TSORG_PORT
+#define TURN_USER TSORG_USER
+#define TURN_PASS TSORG_PASS
+#define TURN_USER2 TSORG_USER
+#define TURN_PASS2 TSORG_PASS
+#define TURN_TYPE NICE_RELAY_TYPE_TURN_TCP
+#else
+#define TURN_IP NUMB_IP
+#define TURN_PORT NUMB_PORT
+#define TURN_USER NUMB_USER
+#define TURN_PASS NUMB_PASS
+#define TURN_USER2 NUMB_USER
+#define TURN_PASS2 NUMB_PASS
+#define TURN_TYPE NICE_RELAY_TYPE_TURN_UDP
+#endif
+
+#endif
+
+
+static NiceComponentState global_lagent_state[2] = { NICE_COMPONENT_STATE_LAST, NICE_COMPONENT_STATE_LAST };
+static NiceComponentState global_ragent_state[2] = { NICE_COMPONENT_STATE_LAST, NICE_COMPONENT_STATE_LAST };
+static guint global_components_ready = 0;
+static guint global_components_ready_exit = 0;
+static guint global_components_failed = 0;
+static guint global_components_failed_exit = 0;
+static GMainLoop *global_mainloop = NULL;
+static gboolean global_lagent_gathering_done = FALSE;
+static gboolean global_ragent_gathering_done = FALSE;
+static gboolean global_lagent_ibr_received = FALSE;
+static gboolean global_ragent_ibr_received = FALSE;
+static int global_lagent_cands = 0;
+static int global_ragent_cands = 0;
+static gint global_ragent_read = 0;
+static guint global_exit_when_ibr_received = 0;
+
+static void priv_print_global_status (void)
+{
+ g_debug ("\tgathering_done=%d", global_lagent_gathering_done && global_ragent_gathering_done);
+ g_debug ("\tlstate[rtp]=%d [rtcp]=%d", global_lagent_state[0], global_lagent_state[1]);
+ g_debug ("\trstate[rtp]=%d [rtcp]=%d", global_ragent_state[0], global_ragent_state[1]);
+ g_debug ("\tL cands=%d R cands=%d", global_lagent_cands, global_ragent_cands);
+}
+
+static gboolean timer_cb (gpointer pointer)
+{
+ g_debug ("test-fullmode:%s: %p", G_STRFUNC, pointer);
+
+ /* signal status via a global variable */
+
+ /* note: should not be reached, abort */
+ g_error ("ERROR: test has got stuck, aborting...");
+
+ return FALSE;
+}
+
+static void cb_writable (NiceAgent*agent, guint stream_id, guint component_id,
+ gpointer user_data)
+{
+ guint *ls_id = user_data;
+
+ if (stream_id == *ls_id && component_id == 1) {
+ g_debug ("Transport is now writable, stopping mainloop");
+ *ls_id = 0;
+ }
+}
+
+static void cb_nice_recv (NiceAgent *agent, guint stream_id, guint component_id, guint len, gchar *buf, gpointer user_data)
+{
+ g_debug ("test-fullmode:%s: %p", G_STRFUNC, user_data);
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent; (void)stream_id; (void)component_id; (void)buf;
+
+ /*
+ * Lets ignore stun packets that got through
+ */
+ if (len < 8)
+ return;
+ if (strncmp ("12345678", buf, 8))
+ return;
+
+ if (component_id == 2)
+ return;
+
+ if (GPOINTER_TO_UINT (user_data) == 2) {
+ g_debug ("right agent received %d bytes, stopping mainloop", len);
+ global_ragent_read = len;
+ g_main_loop_quit (global_mainloop);
+ }
+}
+
+static void cb_candidate_gathering_done(NiceAgent *agent, guint stream_id, gpointer data)
+{
+ g_debug ("test-fullmode:%s: %p", G_STRFUNC, data);
+
+ if (GPOINTER_TO_UINT (data) == 1)
+ global_lagent_gathering_done = TRUE;
+ else if (GPOINTER_TO_UINT (data) == 2)
+ global_ragent_gathering_done = TRUE;
+
+ if (global_lagent_gathering_done &&
+ global_ragent_gathering_done)
+ g_main_loop_quit (global_mainloop);
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent;
+}
+
+static void cb_component_state_changed (NiceAgent *agent, guint stream_id, guint component_id, guint state, gpointer data)
+{
+ gboolean ready_to_connected = FALSE;
+ g_debug ("test-fullmode:%s: %p", G_STRFUNC, data);
+
+ if (GPOINTER_TO_UINT (data) == 1) {
+ if (global_lagent_state[component_id - 1] == NICE_COMPONENT_STATE_READY &&
+ state == NICE_COMPONENT_STATE_CONNECTED)
+ ready_to_connected = TRUE;
+ global_lagent_state[component_id - 1] = state;
+ } else if (GPOINTER_TO_UINT (data) == 2) {
+ if (global_ragent_state[component_id - 1] == NICE_COMPONENT_STATE_READY &&
+ state == NICE_COMPONENT_STATE_CONNECTED)
+ ready_to_connected = TRUE;
+ global_ragent_state[component_id - 1] = state;
+ }
+
+ if (state == NICE_COMPONENT_STATE_READY)
+ global_components_ready++;
+ else if (state == NICE_COMPONENT_STATE_CONNECTED && ready_to_connected)
+ global_components_ready--;
+ if (state == NICE_COMPONENT_STATE_FAILED)
+ global_components_failed++;
+
+ g_debug ("test-fullmode: checks READY/EXIT-AT %u/%u.", global_components_ready, global_components_ready_exit);
+ g_debug ("test-fullmode: checks FAILED/EXIT-AT %u/%u.", global_components_failed, global_components_failed_exit);
+
+ /* signal status via a global variable */
+ if (global_components_ready == global_components_ready_exit &&
+ global_components_failed == global_components_failed_exit) {
+ g_debug ("Components ready/failed achieved. Stopping mailoop");
+ g_main_loop_quit (global_mainloop);
+ return;
+ }
+
+#if 0
+ /* signal status via a global variable */
+ if (global_components_failed == global_components_failed_exit) {
+ g_main_loop_quit (global_mainloop);
+ return;
+ }
+#endif
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent; (void)stream_id; (void)data; (void)component_id;
+}
+
+static void cb_new_selected_pair(NiceAgent *agent, guint stream_id, guint component_id,
+ gchar *lfoundation, gchar* rfoundation, gpointer data)
+{
+ g_debug ("test-fullmode:%s: %p", G_STRFUNC, data);
+
+ if (GPOINTER_TO_UINT (data) == 1)
+ ++global_lagent_cands;
+ else if (GPOINTER_TO_UINT (data) == 2)
+ ++global_ragent_cands;
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent; (void)stream_id; (void)component_id; (void)lfoundation; (void)rfoundation;
+}
+
+static void cb_new_candidate(NiceAgent *agent, guint stream_id, guint component_id,
+ gchar *foundation, gpointer data)
+{
+ g_debug ("test-fullmode:%s: %p", G_STRFUNC, data);
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent; (void)stream_id; (void)data; (void)component_id; (void)foundation;
+}
+
+static void cb_initial_binding_request_received(NiceAgent *agent, guint stream_id, gpointer data)
+{
+ g_debug ("test-fullmode:%s: %p", G_STRFUNC, data);
+
+ if (GPOINTER_TO_UINT (data) == 1)
+ global_lagent_ibr_received = TRUE;
+ else if (GPOINTER_TO_UINT (data) == 2)
+ global_ragent_ibr_received = TRUE;
+
+ if (global_exit_when_ibr_received) {
+ g_debug ("Received initial binding request. Stopping mailoop");
+ g_main_loop_quit (global_mainloop);
+ }
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent; (void)stream_id; (void)data;
+}
+
+static void cb_closed (GObject *src, GAsyncResult *result, gpointer data)
+{
+ NiceAgent *agent = NICE_AGENT (src);
+
+ g_debug ("test-fullmode:%s: %p", G_STRFUNC, agent);
+
+ *((gboolean *)data) = TRUE;
+}
+
+static void set_candidates (NiceAgent *from, guint from_stream,
+ NiceAgent *to, guint to_stream, guint component, gboolean remove_non_relay)
+{
+ GSList *cands = NULL, *i;
+
+ cands = nice_agent_get_local_candidates (from, from_stream, component);
+ if (remove_non_relay) {
+ restart:
+ for (i = cands; i; i = i->next) {
+ NiceCandidate *cand = i->data;
+ if (cand->type != NICE_CANDIDATE_TYPE_RELAYED) {
+ cands = g_slist_remove (cands, cand);
+ nice_candidate_free (cand);
+ goto restart;
+ }
+ }
+ }
+ nice_agent_set_remote_candidates (to, to_stream, component, cands);
+
+ for (i = cands; i; i = i->next)
+ nice_candidate_free ((NiceCandidate *) i->data);
+ g_slist_free (cands);
+}
+
+static void set_credentials (NiceAgent *lagent, guint lstream,
+ NiceAgent *ragent, guint rstream)
+{
+ gchar *ufrag = NULL, *password = NULL;
+
+ nice_agent_get_local_credentials(lagent, lstream, &ufrag, &password);
+ nice_agent_set_remote_credentials (ragent, rstream, ufrag, password);
+ g_free (ufrag);
+ g_free (password);
+ nice_agent_get_local_credentials(ragent, rstream, &ufrag, &password);
+ nice_agent_set_remote_credentials (lagent, lstream, ufrag, password);
+ g_free (ufrag);
+ g_free (password);
+}
+
+static guint16
+get_port (NiceAgent *agent, guint stream_id, guint component_id)
+{
+ GSList *cands = nice_agent_get_local_candidates (agent, stream_id,
+ component_id);
+ GSList *item;
+ guint16 port = 0;
+
+ g_assert (cands != NULL);
+
+ for (item = cands; item; item = item->next) {
+ NiceCandidate *cand = item->data;
+ port = nice_address_get_port (&cand->addr);
+ break;
+ }
+ g_assert (port != 0);
+
+ g_slist_free_full (cands, (GDestroyNotify) nice_candidate_free);
+
+ return port;
+}
+
+static int run_full_test (NiceAgent *lagent, NiceAgent *ragent, NiceAddress *baseaddr, guint ready, guint failed)
+{
+ guint ls_id, rs_id;
+ gint ret;
+ guint16 port;
+
+ /* XXX: dear compiler, this is for you */
+ (void)baseaddr;
+
+ /* step: initialize variables modified by the callbacks */
+ global_components_ready = 0;
+ global_components_ready_exit = ready;
+ global_components_failed = 0;
+ global_components_failed_exit = failed;
+ global_lagent_gathering_done = FALSE;
+ global_ragent_gathering_done = FALSE;
+ global_lagent_ibr_received =
+ global_ragent_ibr_received = FALSE;
+ global_lagent_cands =
+ global_ragent_cands = 0;
+
+ g_object_set (G_OBJECT (lagent), "controlling-mode", TRUE, NULL);
+ g_object_set (G_OBJECT (ragent), "controlling-mode", FALSE, NULL);
+
+ /* step: add one stream, with RTP+RTCP components, to each agent */
+ ls_id = nice_agent_add_stream (lagent, 2);
+
+ rs_id = nice_agent_add_stream (ragent, 2);
+ g_assert (ls_id > 0);
+ g_assert (rs_id > 0);
+#if USE_TURN
+ nice_agent_set_relay_info(lagent, ls_id, 1,
+ TURN_IP, TURN_PORT, TURN_USER, TURN_PASS, TURN_TYPE);
+ nice_agent_set_relay_info(lagent, ls_id, 2,
+ TURN_IP, TURN_PORT, TURN_USER, TURN_PASS, TURN_TYPE);
+ nice_agent_set_relay_info(ragent, rs_id, 1,
+ TURN_IP, TURN_PORT, TURN_USER2, TURN_PASS2, TURN_TYPE);
+ nice_agent_set_relay_info(ragent, rs_id, 2,
+ TURN_IP, TURN_PORT, TURN_USER2, TURN_PASS2, TURN_TYPE);
+#endif
+
+
+ /* Gather candidates and test nice_agent_set_port_range */
+ for (port = 10000; port < 60000; port++) {
+ nice_agent_set_port_range (lagent, ls_id, 1, port, port);
+ if (nice_agent_gather_candidates (lagent, ls_id))
+ break;
+ }
+
+ g_assert (port == get_port (lagent, ls_id, 1));
+
+ nice_agent_set_port_range (ragent, rs_id, 2, port, port);
+
+ g_assert (nice_agent_gather_candidates (ragent, rs_id) == FALSE);
+ g_assert (nice_agent_get_local_candidates (ragent, rs_id, 1) == NULL);
+ g_assert (nice_agent_get_local_candidates (ragent, rs_id, 2) == NULL);
+ nice_agent_set_port_range (ragent, rs_id, 2, 0, 0);
+ g_assert (nice_agent_gather_candidates (lagent, ls_id) == TRUE);
+ g_assert (nice_agent_gather_candidates (ragent, rs_id) == TRUE);
+
+#if USE_LOOPBACK
+ {
+ GSList *cands = NULL, *i;
+ NiceCandidate *cand = NULL;
+
+ cands = nice_agent_get_local_candidates (lagent, ls_id, 1);
+ g_assert (g_slist_length (cands) == 1);
+ cand = cands->data;
+ g_assert (cand->type == NICE_CANDIDATE_TYPE_HOST);
+ for (i = cands; i; i = i->next)
+ nice_candidate_free ((NiceCandidate *) i->data);
+ g_slist_free (cands);
+
+ cands = nice_agent_get_local_candidates (lagent, ls_id, 2);
+ g_assert (g_slist_length (cands) == 1);
+ cand = cands->data;
+ g_assert (cand->type == NICE_CANDIDATE_TYPE_HOST);
+ for (i = cands; i; i = i->next)
+ nice_candidate_free ((NiceCandidate *) i->data);
+ g_slist_free (cands);
+
+ cands = nice_agent_get_local_candidates (ragent, rs_id, 1);
+ g_assert (g_slist_length (cands) == 1);
+ cand = cands->data;
+ g_assert (cand->type == NICE_CANDIDATE_TYPE_HOST);
+ for (i = cands; i; i = i->next)
+ nice_candidate_free ((NiceCandidate *) i->data);
+ g_slist_free (cands);
+
+ cands = nice_agent_get_local_candidates (ragent, rs_id, 2);
+ g_assert (g_slist_length (cands) == 1);
+ cand = cands->data;
+ g_assert (cand->type == NICE_CANDIDATE_TYPE_HOST);
+ for (i = cands; i; i = i->next)
+ nice_candidate_free ((NiceCandidate *) i->data);
+ g_slist_free (cands);
+
+ }
+#endif
+
+ /* step: attach to mainloop (needed to register the fds) */
+ nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv,
+ GUINT_TO_POINTER (1));
+ nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTCP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv,
+ GUINT_TO_POINTER (1));
+ nice_agent_attach_recv (ragent, rs_id, NICE_COMPONENT_TYPE_RTP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv,
+ GUINT_TO_POINTER (2));
+ nice_agent_attach_recv (ragent, rs_id, NICE_COMPONENT_TYPE_RTCP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv,
+ GUINT_TO_POINTER (2));
+
+ /* step: run mainloop until local candidates are ready
+ * (see timer_cb() above) */
+ if (global_lagent_gathering_done != TRUE ||
+ global_ragent_gathering_done != TRUE) {
+ g_debug ("test-fullmode: Added streams, running mainloop until 'candidate-gathering-done'...");
+ g_main_loop_run (global_mainloop);
+ g_assert (global_lagent_gathering_done == TRUE);
+ g_assert (global_ragent_gathering_done == TRUE);
+ }
+
+ set_credentials (lagent, ls_id, ragent, rs_id);
+
+ /* step: pass the remote candidates to agents */
+ set_candidates (ragent, rs_id, lagent, ls_id, NICE_COMPONENT_TYPE_RTP, USE_TURN);
+ set_candidates (ragent, rs_id, lagent, ls_id, NICE_COMPONENT_TYPE_RTCP, USE_TURN);
+ set_candidates (lagent, ls_id, ragent, rs_id, NICE_COMPONENT_TYPE_RTP, USE_TURN);
+ set_candidates (lagent, ls_id, ragent, rs_id, NICE_COMPONENT_TYPE_RTCP, USE_TURN);
+
+ g_debug ("test-fullmode: Set properties, next running mainloop until connectivity checks succeed...");
+
+ /* step: run the mainloop until connectivity checks succeed
+ * (see timer_cb() above) */
+ g_main_loop_run (global_mainloop);
+
+ /* note: verify that STUN binding requests were sent */
+ g_assert (global_lagent_ibr_received == TRUE);
+ g_assert (global_ragent_ibr_received == TRUE);
+
+ /* note: test payload send and receive */
+ global_ragent_read = 0;
+ ret = nice_agent_send (lagent, ls_id, 1, 16, "1234567812345678");
+ if (ret == -1)
+ {
+ gboolean reliable = FALSE;
+ g_object_get (G_OBJECT (lagent), "reliable", &reliable, NULL);
+ g_debug ("Sending data returned -1 in %s mode", reliable?"Reliable":"Non-reliable");
+ if (reliable) {
+ gulong signal_handler;
+ guint ls_id_copy = ls_id;
+
+ signal_handler = g_signal_connect (G_OBJECT (lagent),
+ "reliable-transport-writable", G_CALLBACK (cb_writable), &ls_id_copy);
+ g_debug ("Running mainloop until transport is writable");
+ while (ls_id_copy == ls_id)
+ g_main_context_iteration (NULL, TRUE);
+ g_signal_handler_disconnect(G_OBJECT (lagent), signal_handler);
+
+ ret = nice_agent_send (lagent, ls_id, 1, 16, "1234567812345678");
+ }
+ }
+ g_debug ("Sent %d bytes", ret);
+ g_assert (ret == 16);
+ while (global_ragent_read != 16)
+ g_main_context_iteration (NULL, TRUE);
+ g_assert (global_ragent_read == 16);
+
+ g_debug ("test-fullmode: Ran mainloop, removing streams...");
+
+ /* step: clean up resources and exit */
+
+ nice_agent_remove_stream (lagent, ls_id);
+ nice_agent_remove_stream (ragent, rs_id);
+
+ return 0;
+}
+
+/*
+ * Simulate the case where answer to the offer is delayed and
+ * some STUN connectivity checks reach the offering party
+ * before it gets the remote SDP information.
+ */
+static int run_full_test_delayed_answer (NiceAgent *lagent, NiceAgent *ragent, NiceAddress *baseaddr, guint ready, guint failed)
+{
+ guint ls_id, rs_id;
+ gint ret;
+
+ /* XXX: dear compiler, this is for you */
+ (void)baseaddr;
+
+ /* step: initialize variables modified by the callbacks */
+ global_components_ready = 0;
+ global_components_ready_exit = ready;
+ global_components_failed = 0;
+ global_components_failed_exit = failed;
+ global_lagent_gathering_done = FALSE;
+ global_ragent_gathering_done = FALSE;
+ global_lagent_ibr_received =
+ global_ragent_ibr_received = FALSE;
+ global_exit_when_ibr_received = 1;
+ global_lagent_cands =
+ global_ragent_cands = 0;
+
+ g_object_set (G_OBJECT (lagent), "controlling-mode", TRUE, NULL);
+ g_object_set (G_OBJECT (ragent), "controlling-mode", FALSE, NULL);
+
+ /* step: add one stream, with RTP+RTCP components, to each agent */
+ ls_id = nice_agent_add_stream (lagent, 2);
+
+ rs_id = nice_agent_add_stream (ragent, 2);
+ g_assert (ls_id > 0);
+ g_assert (rs_id > 0);
+
+ /* We don't try this with TURN because as long as both agents don't
+ have the remote candidates, they won't be able to create the
+ permission on the TURN server, so the connchecks will never go through */
+
+ nice_agent_gather_candidates (lagent, ls_id);
+ nice_agent_gather_candidates (ragent, rs_id);
+
+ /* step: attach to mainloop (needed to register the fds) */
+ nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv,
+ GUINT_TO_POINTER (1));
+ nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTCP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv,
+ GUINT_TO_POINTER (1));
+ nice_agent_attach_recv (ragent, rs_id, NICE_COMPONENT_TYPE_RTP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv,
+ GUINT_TO_POINTER (2));
+ nice_agent_attach_recv (ragent, rs_id, NICE_COMPONENT_TYPE_RTCP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv,
+ GUINT_TO_POINTER (2));
+
+ /* step: run mainloop until local candidates are ready
+ * (see timer_cb() above) */
+ if (global_lagent_gathering_done != TRUE ||
+ global_ragent_gathering_done != TRUE) {
+ g_debug ("test-fullmode: Added streams, running mainloop until 'candidate-gathering-done'...");
+ g_main_loop_run (global_mainloop);
+ g_assert (global_lagent_gathering_done == TRUE);
+ g_assert (global_ragent_gathering_done == TRUE);
+ }
+
+ set_credentials (lagent, ls_id, ragent, rs_id);
+
+ /* step: set remote candidates for agent R (answering party) */
+ /* We have to disable TURN for this test because with the delayed answer,
+ we can't create turn permissions, so we won't receive any connchecks */
+ set_candidates (lagent, ls_id, ragent, rs_id, NICE_COMPONENT_TYPE_RTP, FALSE);
+ set_candidates (lagent, ls_id, ragent, rs_id, NICE_COMPONENT_TYPE_RTCP, FALSE);
+
+ g_debug ("test-fullmode: Set properties, next running mainloop until first check is received...");
+
+ /* step: run the mainloop until first connectivity check receveid */
+ g_main_loop_run (global_mainloop);
+ global_exit_when_ibr_received = 0;
+
+ /* note: verify that STUN binding requests were sent */
+ g_assert (global_lagent_ibr_received == TRUE);
+
+ g_debug ("test-fullmode: Delayed answer received, continuing processing..");
+
+ /* step: pass remove candidates to agent L (offering party) */
+ set_candidates (ragent, rs_id, lagent, ls_id, NICE_COMPONENT_TYPE_RTP, FALSE);
+ set_candidates (ragent, rs_id, lagent, ls_id, NICE_COMPONENT_TYPE_RTCP, FALSE);
+
+ g_debug ("test-fullmode: Running mainloop until connectivity checks succeeed.");
+
+ g_main_loop_run (global_mainloop);
+ g_assert (global_ragent_ibr_received == TRUE);
+ g_assert (global_components_failed == 0);
+
+ /* note: test payload send and receive */
+ global_ragent_read = 0;
+ ret = nice_agent_send (lagent, ls_id, 1, 16, "1234567812345678");
+ if (ret == -1) {
+ gboolean reliable = FALSE;
+ g_object_get (G_OBJECT (lagent), "reliable", &reliable, NULL);
+ if (reliable) {
+ gulong signal_handler;
+ guint ls_id_copy = ls_id;
+
+ signal_handler = g_signal_connect (G_OBJECT (lagent),
+ "reliable-transport-writable", G_CALLBACK (cb_writable), &ls_id_copy);
+ g_debug ("Running mainloop until transport is writable");
+ while (ls_id_copy == ls_id)
+ g_main_context_iteration (NULL, TRUE);
+ g_signal_handler_disconnect(G_OBJECT (lagent), signal_handler);
+
+ ret = nice_agent_send (lagent, ls_id, 1, 16, "1234567812345678");
+ }
+ }
+ global_ragent_read = 0;
+ g_assert (ret == 16);
+ g_main_loop_run (global_mainloop);
+ g_assert (global_ragent_read == 16);
+
+ g_debug ("test-fullmode: Ran mainloop, removing streams...");
+
+ /* step: clean up resources and exit */
+
+ nice_agent_remove_stream (lagent, ls_id);
+ nice_agent_remove_stream (ragent, rs_id);
+
+ return 0;
+}
+
+static int run_full_test_wrong_password (NiceAgent *lagent, NiceAgent *ragent, NiceAddress *baseaddr)
+{
+ guint ls_id, rs_id;
+
+ /* XXX: dear compiler, this is for you */
+ (void)baseaddr;
+
+ global_components_ready = 0;
+ global_components_ready_exit = 0;
+ global_components_failed = 0;
+ global_components_failed_exit = 2;
+ global_lagent_state[0] = global_lagent_state[1] =
+ global_ragent_state[0] = global_ragent_state[1]
+ = NICE_COMPONENT_STATE_LAST;
+ global_lagent_gathering_done =
+ global_ragent_gathering_done = FALSE;
+ global_lagent_cands =
+ global_ragent_cands = 0;
+
+ g_object_set (G_OBJECT (lagent), "controlling-mode", TRUE, NULL);
+ g_object_set (G_OBJECT (ragent), "controlling-mode", FALSE, NULL);
+
+ /* step: add one stream, with one component, to each agent */
+ ls_id = nice_agent_add_stream (lagent, 1);
+
+ rs_id = nice_agent_add_stream (ragent, 1);
+ g_assert (ls_id > 0);
+ g_assert (rs_id > 0);
+
+#if USE_TURN
+ nice_agent_set_relay_info(lagent, ls_id, 1,
+ TURN_IP, TURN_PORT, TURN_USER, TURN_PASS, TURN_TYPE);
+ nice_agent_set_relay_info(ragent, rs_id, 1,
+ TURN_IP, TURN_PORT, TURN_USER, TURN_PASS, TURN_TYPE);
+#endif
+
+ nice_agent_gather_candidates (lagent, ls_id);
+ nice_agent_gather_candidates (ragent, rs_id);
+
+ /* step: attach to mainloop (needed to register the fds) */
+ nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv,
+ GUINT_TO_POINTER (1));
+ nice_agent_attach_recv (ragent, rs_id, NICE_COMPONENT_TYPE_RTP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv,
+ GUINT_TO_POINTER (2));
+
+ /* step: run mainloop until local candidates are ready
+ * (see timer_cb() above) */
+ if (global_lagent_gathering_done != TRUE ||
+ global_ragent_gathering_done != TRUE) {
+ g_debug ("test-fullmode: Added streams, running mainloop until 'candidate-gathering-done'...");
+ g_main_loop_run (global_mainloop);
+ g_assert (global_lagent_gathering_done == TRUE);
+ g_assert (global_ragent_gathering_done == TRUE);
+ }
+
+ g_debug ("test-fullmode: Got local candidates...");
+
+ set_credentials (lagent, ls_id, ragent, rs_id);
+ nice_agent_set_remote_credentials (ragent, rs_id, "wrong", "password");
+ nice_agent_set_remote_credentials (lagent, ls_id, "wrong2", "password2");
+
+
+ /* step: pass the remote candidates to agents */
+ set_candidates (ragent, rs_id, lagent, ls_id, NICE_COMPONENT_TYPE_RTP, USE_TURN);
+ set_candidates (lagent, ls_id, ragent, rs_id, NICE_COMPONENT_TYPE_RTP, USE_TURN);
+
+ g_debug ("test-fullmode: Set properties, next running mainloop until connectivity checks succeed...");
+
+ /* step: run the mainloop until connectivity checks succeed
+ * (see timer_cb() above) */
+ g_main_loop_run (global_mainloop);
+
+ /* note: verify that correct number of local candidates were reported */
+ g_assert (global_lagent_cands == 0);
+ g_assert (global_ragent_cands == 0);
+
+ g_debug ("test-fullmode: Ran mainloop, removing streams...");
+
+ /* step: clean up resources and exit */
+
+ nice_agent_remove_stream (lagent, ls_id);
+ nice_agent_remove_stream (ragent, rs_id);
+
+ return 0;
+}
+
+static int run_full_test_control_conflict (NiceAgent *lagent, NiceAgent *ragent, NiceAddress *baseaddr, gboolean role)
+{
+ guint ls_id, rs_id;
+
+ /* XXX: dear compiler, this is for you */
+ (void)baseaddr;
+
+ global_components_ready = 0;
+ global_components_ready_exit = 2;
+ global_components_failed = 0;
+ global_components_failed_exit = 0;
+ global_lagent_gathering_done =
+ global_ragent_gathering_done = FALSE;
+ global_lagent_cands =
+ global_ragent_cands = 0;
+ global_lagent_ibr_received =
+ global_ragent_ibr_received = FALSE;
+
+ g_object_set (G_OBJECT (lagent), "controlling-mode", role, NULL);
+ g_object_set (G_OBJECT (ragent), "controlling-mode", role, NULL);
+
+ /* step: add one stream, with one component, to each agent */
+ ls_id = nice_agent_add_stream (lagent, 1);
+
+ rs_id = nice_agent_add_stream (ragent, 1);
+ g_assert (ls_id > 0);
+ g_assert (rs_id > 0);
+
+#if USE_TURN
+ nice_agent_set_relay_info(lagent, ls_id, 1,
+ TURN_IP, TURN_PORT, TURN_USER, TURN_PASS, TURN_TYPE);
+ nice_agent_set_relay_info(ragent, rs_id, 1,
+ TURN_IP, TURN_PORT, TURN_USER, TURN_PASS, TURN_TYPE);
+#endif
+
+ nice_agent_gather_candidates (lagent, ls_id);
+ nice_agent_gather_candidates (ragent, rs_id);
+
+ /* step: attach to mainloop (needed to register the fds) */
+ nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv,
+ GUINT_TO_POINTER (1));
+ nice_agent_attach_recv (ragent, rs_id, NICE_COMPONENT_TYPE_RTP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv,
+ GUINT_TO_POINTER (2));
+
+ /* step: run mainloop until local candidates are ready
+ * (see timer_cb() above) */
+ if (global_lagent_gathering_done != TRUE ||
+ global_ragent_gathering_done != TRUE) {
+ g_debug ("test-fullmode: Added streams, running mainloop until 'candidate-gathering-done'...");
+ g_main_loop_run (global_mainloop);
+ g_assert (global_lagent_gathering_done == TRUE);
+ g_assert (global_ragent_gathering_done == TRUE);
+ }
+
+ g_debug ("test-fullmode: Got local candidates...");
+
+ set_credentials (lagent, ls_id, ragent, rs_id);
+
+ /* step: pass the remote candidates to agents */
+ set_candidates (ragent, rs_id, lagent, ls_id, NICE_COMPONENT_TYPE_RTP, USE_TURN);
+ set_candidates (lagent, ls_id, ragent, rs_id, NICE_COMPONENT_TYPE_RTP, USE_TURN);
+
+ g_debug ("test-fullmode: Set properties, next running mainloop until connectivity checks succeed...");
+
+ /* step: run the mainloop until connectivity checks succeed
+ * (see timer_cb() above) */
+ g_main_loop_run (global_mainloop);
+
+ /* When using TURN, we get peer reflexive candidates for the host cands
+ that we removed so we can get another new_selected_pair signal later
+ depending on timing/racing, we could double (or not) the amount we expected
+ */
+#if !(USE_TURN)
+ /* note: verify that correct number of local candidates were reported */
+ g_assert (global_lagent_cands == 1);
+ g_assert (global_ragent_cands == 1);
+#endif
+
+ g_debug ("test-fullmode: Ran mainloop, removing streams...");
+
+ /* step: clean up resources and exit */
+
+ nice_agent_remove_stream (lagent, ls_id);
+ nice_agent_remove_stream (ragent, rs_id);
+
+ return 0;
+}
+
+int main (void)
+{
+ NiceAgent *lagent, *ragent; /* agent's L and R */
+ NiceAddress baseaddr;
+ int result;
+ guint timer_id;
+ const char *stun_server = NULL, *stun_server_port = NULL;
+ gboolean lagent_closed = FALSE;
+ gboolean ragent_closed = FALSE;
+
+#ifdef G_OS_WIN32
+ WSADATA w;
+
+ WSAStartup(0x0202, &w);
+#endif
+
+ global_mainloop = g_main_loop_new (NULL, FALSE);
+
+ /* Note: impl limits ...
+ * - no multi-stream support
+ * - no IPv6 support
+ */
+
+ /* step: create the agents L and R */
+#if USE_RELIABLE
+ lagent = nice_agent_new_reliable (g_main_loop_get_context (global_mainloop),
+ NICE_COMPATIBILITY);
+ ragent = nice_agent_new_reliable (g_main_loop_get_context (global_mainloop),
+ NICE_COMPATIBILITY);
+#else
+ lagent = nice_agent_new (g_main_loop_get_context (global_mainloop),
+ NICE_COMPATIBILITY);
+ ragent = nice_agent_new (g_main_loop_get_context (global_mainloop),
+ NICE_COMPATIBILITY);
+#endif
+
+ g_object_set (G_OBJECT (lagent), "ice-tcp", FALSE, NULL);
+ g_object_set (G_OBJECT (ragent), "ice-tcp", FALSE, NULL);
+
+
+ nice_agent_set_software (lagent, "Test-fullmode, Left Agent");
+ nice_agent_set_software (ragent, "Test-fullmode, Right Agent");
+
+ /* step: add a timer to catch state changes triggered by signals */
+#if USE_TURN
+ timer_id = g_timeout_add (300000, timer_cb, NULL);
+#else
+ timer_id = g_timeout_add (30000, timer_cb, NULL);
+#endif
+
+ /* step: specify which local interface to use */
+#if USE_LOOPBACK
+ if (!nice_address_set_from_string (&baseaddr, "127.0.0.1"))
+ g_assert_not_reached ();
+ nice_agent_add_local_address (lagent, &baseaddr);
+ nice_agent_add_local_address (ragent, &baseaddr);
+#endif
+
+ g_signal_connect (G_OBJECT (lagent), "candidate-gathering-done",
+ G_CALLBACK (cb_candidate_gathering_done), GUINT_TO_POINTER(1));
+ g_signal_connect (G_OBJECT (ragent), "candidate-gathering-done",
+ G_CALLBACK (cb_candidate_gathering_done), GUINT_TO_POINTER (2));
+ g_signal_connect (G_OBJECT (lagent), "component-state-changed",
+ G_CALLBACK (cb_component_state_changed), GUINT_TO_POINTER (1));
+ g_signal_connect (G_OBJECT (ragent), "component-state-changed",
+ G_CALLBACK (cb_component_state_changed), GUINT_TO_POINTER (2));
+ g_signal_connect (G_OBJECT (lagent), "new-selected-pair",
+ G_CALLBACK (cb_new_selected_pair), GUINT_TO_POINTER(1));
+ g_signal_connect (G_OBJECT (ragent), "new-selected-pair",
+ G_CALLBACK (cb_new_selected_pair), GUINT_TO_POINTER (2));
+ g_signal_connect (G_OBJECT (lagent), "new-candidate",
+ G_CALLBACK (cb_new_candidate), GUINT_TO_POINTER (1));
+ g_signal_connect (G_OBJECT (ragent), "new-candidate",
+ G_CALLBACK (cb_new_candidate), GUINT_TO_POINTER (2));
+ g_signal_connect (G_OBJECT (lagent), "initial-binding-request-received",
+ G_CALLBACK (cb_initial_binding_request_received),
+ GUINT_TO_POINTER (1));
+ g_signal_connect (G_OBJECT (ragent), "initial-binding-request-received",
+ G_CALLBACK (cb_initial_binding_request_received),
+ GUINT_TO_POINTER (2));
+
+ stun_server = getenv ("NICE_STUN_SERVER");
+ stun_server_port = getenv ("NICE_STUN_SERVER_PORT");
+ if (stun_server) {
+ g_object_set (G_OBJECT (lagent), "stun-server", stun_server, NULL);
+ g_object_set (G_OBJECT (lagent), "stun-server-port", atoi (stun_server_port), NULL);
+ g_object_set (G_OBJECT (ragent), "stun-server", stun_server, NULL);
+ g_object_set (G_OBJECT (ragent), "stun-server-port", atoi (stun_server_port), NULL);
+ }
+
+ g_object_set (G_OBJECT (lagent), "upnp", USE_UPNP, NULL);
+ g_object_set (G_OBJECT (lagent), "proxy-ip", PROXY_IP, NULL);
+ g_object_set (G_OBJECT (lagent), "proxy-port", PROXY_PORT, NULL);
+ g_object_set (G_OBJECT (lagent), "proxy-type", PROXY_TYPE, NULL);
+ g_object_set (G_OBJECT (lagent), "proxy-username", PROXY_USERNAME, NULL);
+ g_object_set (G_OBJECT (lagent), "proxy-password", PROXY_PASSWORD, NULL);
+ g_object_set (G_OBJECT (ragent), "upnp", USE_UPNP, NULL);
+ g_object_set (G_OBJECT (ragent), "proxy-ip", PROXY_IP, NULL);
+ g_object_set (G_OBJECT (ragent), "proxy-port", PROXY_PORT, NULL);
+ g_object_set (G_OBJECT (ragent), "proxy-type", PROXY_TYPE, NULL);
+ g_object_set (G_OBJECT (ragent), "proxy-username", PROXY_USERNAME, NULL);
+ g_object_set (G_OBJECT (ragent), "proxy-password", PROXY_PASSWORD, NULL);
+
+ /* step: test setter/getter functions for properties */
+ {
+ guint max_checks = 0;
+ gchar *string = NULL;
+ guint port = 0;
+ gboolean mode = FALSE;
+ g_object_get (G_OBJECT (lagent), "stun-server", &string, NULL);
+ g_assert (stun_server == NULL || strcmp (string, stun_server) == 0);
+ g_free (string);
+ g_object_get (G_OBJECT (lagent), "stun-server-port", &port, NULL);
+ g_assert (stun_server_port == NULL || port == (guint)atoi (stun_server_port));
+ g_object_get (G_OBJECT (lagent), "proxy-ip", &string, NULL);
+ g_assert (strcmp (string, PROXY_IP) == 0);
+ g_free (string);
+ g_object_get (G_OBJECT (lagent), "proxy-port", &port, NULL);
+ g_assert (port == PROXY_PORT);
+ g_object_get (G_OBJECT (lagent), "controlling-mode", &mode, NULL);
+ g_assert (mode == TRUE);
+ g_object_set (G_OBJECT (lagent), "max-connectivity-checks", 300, NULL);
+ g_object_get (G_OBJECT (lagent), "max-connectivity-checks", &max_checks, NULL);
+ g_assert (max_checks == 300);
+ }
+
+ /* step: run test the first time */
+ g_debug ("test-fullmode: TEST STARTS / running test for the 1st time");
+ result = run_full_test (lagent, ragent, &baseaddr, 4 ,0);
+ priv_print_global_status ();
+ g_assert (result == 0);
+ g_assert (global_lagent_state[0] == NICE_COMPONENT_STATE_READY);
+ g_assert (global_lagent_state[1] == NICE_COMPONENT_STATE_READY);
+ g_assert (global_ragent_state[0] == NICE_COMPONENT_STATE_READY);
+ g_assert (global_ragent_state[1] == NICE_COMPONENT_STATE_READY);
+ /* When using TURN, we get peer reflexive candidates for the host cands
+ that we removed so we can get another new_selected_pair signal later
+ depending on timing/racing, we could double (or not) the amount we expected
+ */
+#if !(USE_TURN)
+ /* note: verify that correct number of local candidates were reported */
+ g_assert (global_lagent_cands == 2);
+ g_assert (global_ragent_cands == 2);
+#endif
+
+
+ /* step: run test again without unref'ing agents */
+ g_debug ("test-fullmode: TEST STARTS / running test for the 2nd time");
+ result = run_full_test (lagent, ragent, &baseaddr, 4, 0);
+ priv_print_global_status ();
+ g_assert (result == 0);
+ g_assert (global_lagent_state[0] == NICE_COMPONENT_STATE_READY);
+ g_assert (global_lagent_state[1] == NICE_COMPONENT_STATE_READY);
+ g_assert (global_ragent_state[0] == NICE_COMPONENT_STATE_READY);
+ g_assert (global_ragent_state[1] == NICE_COMPONENT_STATE_READY);
+ /* When using TURN, we get peer reflexive candidates for the host cands
+ that we removed so we can get another new_selected_pair signal later
+ depending on timing/racing, we could double (or not) the amount we expected
+ */
+#if !(USE_TURN)
+ /* note: verify that correct number of local candidates were reported */
+ g_assert (global_lagent_cands == 2);
+ g_assert (global_ragent_cands == 2);
+#endif
+
+
+ /* step: run test simulating delayed SDP answer */
+ g_debug ("test-fullmode: TEST STARTS / delayed SDP answer");
+ result = run_full_test_delayed_answer (lagent, ragent, &baseaddr, 4, 0);
+ priv_print_global_status ();
+ g_assert (result == 0);
+ g_assert (global_lagent_state[0] == NICE_COMPONENT_STATE_READY);
+ g_assert (global_lagent_state[1] == NICE_COMPONENT_STATE_READY);
+ g_assert (global_ragent_state[0] == NICE_COMPONENT_STATE_READY);
+ g_assert (global_ragent_state[1] == NICE_COMPONENT_STATE_READY);
+ /* note: verify that correct number of local candidates were reported */
+ /* When using TURN, we get peer reflexive candidates for the host cands
+ that we removed so we can get another new_selected_pair signal later
+ depending on timing/racing, we could double (or not) the amount we expected
+ */
+#if !(USE_TURN)
+ g_assert (global_lagent_cands == 2);
+ g_assert (global_ragent_cands == 2);
+#endif
+
+#if TEST_GOOGLE
+ return result;
+#endif
+
+ /* run test with incorrect credentials (make sure process fails) */
+ g_debug ("test-fullmode: TEST STARTS / incorrect credentials");
+ result = run_full_test_wrong_password (lagent, ragent, &baseaddr);
+ priv_print_global_status ();
+ g_assert (result == 0);
+ g_assert (global_lagent_state[0] == NICE_COMPONENT_STATE_FAILED);
+ g_assert (global_lagent_state[1] == NICE_COMPONENT_STATE_LAST);
+ g_assert (global_ragent_state[0] == NICE_COMPONENT_STATE_FAILED);
+ g_assert (global_ragent_state[1] == NICE_COMPONENT_STATE_LAST);
+
+ /* The max connectivity checks test can't be run with TURN because
+ we'll have 3 local candidates instead of 1 and the checks will
+ be random, so we can't predict how many will fail/succeed */
+#if USE_TURN == 0
+
+ /* step: run test with a hard limit for connecitivity checks */
+ g_debug ("test-fullmode: TEST STARTS / max connectivity checks");
+ g_object_set (G_OBJECT (lagent), "max-connectivity-checks", 1, NULL);
+ g_object_set (G_OBJECT (ragent), "max-connectivity-checks", 1, NULL);
+ result = run_full_test (lagent, ragent, &baseaddr, 2, 2);
+ priv_print_global_status ();
+ g_assert (result == 0);
+ /* should FAIL as agent L can't send any checks: */
+ g_assert (global_lagent_state[0] == NICE_COMPONENT_STATE_FAILED ||
+ global_lagent_state[1] == NICE_COMPONENT_STATE_FAILED);
+ g_assert (global_lagent_state[0] == NICE_COMPONENT_STATE_FAILED ||
+ global_lagent_state[1] == NICE_COMPONENT_STATE_FAILED);
+#endif
+
+ g_object_set (G_OBJECT (lagent), "max-connectivity-checks", 100, NULL);
+ g_object_set (G_OBJECT (ragent), "max-connectivity-checks", 100, NULL);
+ result = run_full_test (lagent, ragent, &baseaddr, 4, 0);
+ priv_print_global_status ();
+ /* should SUCCEED as agent L can send the checks: */
+ g_assert (result == 0);
+ g_assert (global_lagent_state[0] == NICE_COMPONENT_STATE_CONNECTED ||
+ global_lagent_state[0] == NICE_COMPONENT_STATE_READY);
+ g_assert (global_lagent_state[1] == NICE_COMPONENT_STATE_CONNECTED ||
+ global_lagent_state[1] == NICE_COMPONENT_STATE_READY);
+ g_assert (global_ragent_state[0] == NICE_COMPONENT_STATE_CONNECTED ||
+ global_ragent_state[0] == NICE_COMPONENT_STATE_READY);
+ g_assert (global_ragent_state[1] == NICE_COMPONENT_STATE_CONNECTED ||
+ global_ragent_state[1] == NICE_COMPONENT_STATE_READY);
+ g_object_set (G_OBJECT (lagent), "max-connectivity-checks", 100, NULL);
+
+ /* run test with a conflict in controlling mode: controlling-controlling */
+ g_debug ("test-fullmode: TEST STARTS / controlling mode conflict case-1");
+ result = run_full_test_control_conflict (lagent, ragent, &baseaddr, TRUE);
+ priv_print_global_status ();
+ g_assert (result == 0);
+
+ g_assert (global_lagent_state[0] == NICE_COMPONENT_STATE_READY);
+ g_assert (global_lagent_state[1] == NICE_COMPONENT_STATE_READY);
+ g_assert (global_ragent_state[0] == NICE_COMPONENT_STATE_READY);
+ g_assert (global_ragent_state[1] == NICE_COMPONENT_STATE_READY);
+
+ /* run test with a conflict in controlling mode: controlled-controlled */
+ g_debug ("test-fullmode: TEST STARTS / controlling mode conflict case-2");
+ result = run_full_test_control_conflict (lagent, ragent, &baseaddr, FALSE);
+ priv_print_global_status ();
+ g_assert (result == 0);
+ g_assert (global_lagent_state[0] == NICE_COMPONENT_STATE_READY);
+ g_assert (global_lagent_state[1] == NICE_COMPONENT_STATE_READY);
+ g_assert (global_ragent_state[0] == NICE_COMPONENT_STATE_READY);
+ g_assert (global_ragent_state[1] == NICE_COMPONENT_STATE_READY);
+
+ nice_agent_close_async (lagent, cb_closed, &lagent_closed);
+ nice_agent_close_async (ragent, cb_closed, &ragent_closed);
+ g_object_unref (lagent);
+ g_object_unref (ragent);
+
+ while (!ragent_closed || !ragent_closed) {
+ g_main_context_iteration (NULL, TRUE);
+ }
+
+
+ g_main_loop_unref (global_mainloop);
+ global_mainloop = NULL;
+
+ g_source_remove (timer_id);
+#ifdef G_OS_WIN32
+ WSACleanup();
+#endif
+ return result;
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2015 Kurento.
+ * Contact: Jose Antonio Santos Cadenas
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Jose Antonio Santos Cadenas, Kurento.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#include <gst/check/gstcheck.h>
+#include "agent.h"
+
+#define RTP_HEADER_SIZE 12
+#define RTP_PAYLOAD_SIZE 1024
+
+static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS_ANY);
+
+static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS_ANY);
+
+GMainLoop *loop;
+gint ready = 0;
+
+static guint bytes_received;
+guint data_size;
+
+static gboolean
+count_bytes (GstBuffer ** buffer, guint idx, gpointer data)
+{
+ gsize size = gst_buffer_get_size (*buffer);
+
+ GST_DEBUG ("received %" G_GSIZE_FORMAT " bytes", size);
+ bytes_received += size;
+
+ return TRUE;
+}
+
+static GstFlowReturn
+sink_chain_list_function (GstPad * pad, GstObject * parent,
+ GstBufferList * list)
+{
+ gst_buffer_list_foreach (list, count_bytes, NULL);
+
+ if (data_size <= bytes_received) {
+ GST_DEBUG ("We received expected data size");
+ g_main_loop_quit (loop);
+ }
+
+ return GST_FLOW_OK;
+}
+
+static GstFlowReturn
+sink_chain_function (GstPad * pad, GstObject * parent, GstBuffer * buffer)
+{
+ gsize size = gst_buffer_get_size (buffer);
+
+ GST_DEBUG ("received %" G_GSIZE_FORMAT " bytes", size);
+ bytes_received += size;
+
+ if (data_size <= bytes_received) {
+ GST_DEBUG ("We received expected data size");
+ g_main_loop_quit (loop);
+ }
+
+ return GST_FLOW_OK;
+}
+
+/*
+ * This function is get from gst-plugins-good tests tests/check/elements/udpsink.c
+ */
+static GstBufferList *
+create_buffer_list (void)
+{
+ GstBufferList *list;
+ GstBuffer *rtp_buffer;
+ GstBuffer *data_buffer;
+
+ list = gst_buffer_list_new ();
+
+ /*** First group, i.e. first packet. **/
+
+ /* Create the RTP header buffer */
+ rtp_buffer = gst_buffer_new_allocate (NULL, RTP_HEADER_SIZE, NULL);
+ gst_buffer_memset (rtp_buffer, 0, 0, RTP_HEADER_SIZE);
+
+ /* Create the buffer that holds the payload */
+ data_buffer = gst_buffer_new_allocate (NULL, RTP_PAYLOAD_SIZE, NULL);
+ gst_buffer_memset (data_buffer, 0, 0, RTP_PAYLOAD_SIZE);
+
+ /* Create a new group to hold the rtp header and the payload */
+ gst_buffer_list_add (list, gst_buffer_append (rtp_buffer, data_buffer));
+
+ /*** Second group, i.e. second packet. ***/
+
+ /* Create the RTP header buffer */
+ rtp_buffer = gst_buffer_new_allocate (NULL, RTP_HEADER_SIZE, NULL);
+ gst_buffer_memset (rtp_buffer, 0, 0, RTP_HEADER_SIZE);
+
+ /* Create the buffer that holds the payload */
+ data_buffer = gst_buffer_new_allocate (NULL, RTP_PAYLOAD_SIZE, NULL);
+ gst_buffer_memset (data_buffer, 0, 0, RTP_PAYLOAD_SIZE);
+
+ /* Create a new group to hold the rtp header and the payload */
+ gst_buffer_list_add (list, gst_buffer_append (rtp_buffer, data_buffer));
+
+ /* Calculate the size of the data */
+ data_size = 2 * RTP_HEADER_SIZE + 2 * RTP_PAYLOAD_SIZE;
+
+ return list;
+}
+
+static void
+recv_cb (NiceAgent * agent,
+ guint stream_id, guint component_id, guint len, gchar * buf, gpointer data)
+{
+ GST_INFO ("Received data on agent %" GST_PTR_FORMAT
+ ", stream: %d, compoment: %d", agent, stream_id, component_id);
+}
+
+static void
+print_candidate (gpointer data, gpointer user_data)
+{
+ NiceCandidate *cand = data;
+ gchar str_addr[INET6_ADDRSTRLEN];
+
+ nice_address_to_string (&cand->addr, str_addr);
+ GST_INFO ("Cadidate: %s:%d", str_addr, nice_address_get_port (&cand->addr));
+}
+
+static void
+cb_candidate_gathering_done (NiceAgent * agent, guint stream_id, gpointer data)
+{
+ GSList *candidates;
+
+ GST_INFO ("Candidates gathered on agent %" GST_PTR_FORMAT ", stream: %d",
+ agent, stream_id);
+
+ candidates = nice_agent_get_local_candidates (agent, stream_id, 1);
+
+ nice_agent_set_remote_candidates (NICE_AGENT (data), stream_id, 1,
+ candidates);
+
+ GST_INFO ("Got %d candidates", g_slist_length (candidates));
+ g_slist_foreach (candidates, print_candidate, NULL);
+
+ g_slist_free_full (candidates, (GDestroyNotify) nice_candidate_free);
+}
+
+static void
+credentials_negotiation (NiceAgent * a_agent, NiceAgent * b_agent,
+ guint a_stream, guint b_stream)
+{
+ gchar *user = NULL;
+ gchar *passwd = NULL;
+
+ nice_agent_get_local_credentials (a_agent, a_stream, &user, &passwd);
+ nice_agent_set_remote_credentials (b_agent, b_stream, user, passwd);
+ GST_DEBUG_OBJECT (a_agent, "User: %s", user);
+ GST_DEBUG_OBJECT (a_agent, "Passwd: %s", passwd);
+
+ g_free (user);
+ g_free (passwd);
+}
+
+static void
+cb_component_state_changed (NiceAgent * agent, guint stream_id,
+ guint component_id, guint state, gpointer user_data)
+{
+ GST_DEBUG ("State changed: %" GST_PTR_FORMAT " to %s", agent,
+ nice_component_state_to_string (state));
+
+ if (state == NICE_COMPONENT_STATE_READY) {
+ ready++;
+ if (ready >= 2) {
+ g_main_loop_quit (loop);
+ }
+ }
+}
+
+GST_START_TEST (buffer_list_test)
+{
+ GstSegment segment;
+ GstElement *nicesink, *nicesrc;
+ GstPad *srcpad, *sinkpad;
+ GstBufferList *list;
+ NiceAgent *sink_agent, *src_agent;
+ guint sink_stream, src_stream;
+ NiceAddress *addr;
+
+ loop = g_main_loop_new (NULL, TRUE);
+
+ /* Initialize nice agents */
+ addr = nice_address_new ();
+ nice_address_set_from_string (addr, "127.0.0.1");
+
+ sink_agent = nice_agent_new (NULL, NICE_COMPATIBILITY_RFC5245);
+ src_agent = nice_agent_new (NULL, NICE_COMPATIBILITY_RFC5245);
+
+ g_object_set (G_OBJECT (sink_agent), "upnp", FALSE, NULL);
+ g_object_set (G_OBJECT (src_agent), "upnp", FALSE, NULL);
+
+ nice_agent_add_local_address (sink_agent, addr);
+ nice_agent_add_local_address (src_agent, addr);
+
+ sink_stream = nice_agent_add_stream (sink_agent, 1);
+ src_stream = nice_agent_add_stream (src_agent, 1);
+
+ nice_agent_attach_recv (sink_agent, sink_stream, NICE_COMPONENT_TYPE_RTP,
+ NULL, recv_cb, NULL);
+ nice_agent_attach_recv (src_agent, src_stream, NICE_COMPONENT_TYPE_RTP,
+ NULL, recv_cb, NULL);
+
+ g_signal_connect (G_OBJECT (sink_agent), "candidate-gathering-done",
+ G_CALLBACK (cb_candidate_gathering_done), src_agent);
+ g_signal_connect (G_OBJECT (src_agent), "candidate-gathering-done",
+ G_CALLBACK (cb_candidate_gathering_done), sink_agent);
+
+ g_signal_connect (G_OBJECT (sink_agent), "component-state-changed",
+ G_CALLBACK (cb_component_state_changed), NULL);
+ g_signal_connect (G_OBJECT (src_agent), "component-state-changed",
+ G_CALLBACK (cb_component_state_changed), NULL);
+
+ credentials_negotiation (sink_agent, src_agent, sink_stream, src_stream);
+ credentials_negotiation (src_agent, sink_agent, src_stream, src_stream);
+
+ nice_agent_gather_candidates (sink_agent, sink_stream);
+ nice_agent_gather_candidates (src_agent, src_stream);
+
+ /* Create gstreamer elements */
+ nicesink = gst_check_setup_element ("nicesink");
+ nicesrc = gst_check_setup_element ("nicesrc");
+
+ g_object_set (nicesink, "agent", sink_agent, "stream", sink_stream,
+ "component", 1, NULL);
+ g_object_set (nicesrc, "agent", src_agent, "stream", src_stream, "component",
+ 1, NULL);
+
+ srcpad = gst_check_setup_src_pad_by_name (nicesink, &srctemplate, "sink");
+ sinkpad = gst_check_setup_sink_pad_by_name (nicesrc, &sinktemplate, "src");
+
+ gst_pad_set_chain_list_function_full (sinkpad, sink_chain_list_function, NULL,
+ NULL);
+ gst_pad_set_chain_function_full (sinkpad, sink_chain_function, NULL, NULL);
+
+ gst_element_set_state (nicesink, GST_STATE_PLAYING);
+ gst_pad_set_active (srcpad, TRUE);
+
+ gst_element_set_state (nicesrc, GST_STATE_PLAYING);
+ gst_pad_set_active (sinkpad, TRUE);
+
+ gst_pad_push_event (srcpad, gst_event_new_stream_start ("test"));
+
+ gst_segment_init (&segment, GST_FORMAT_TIME);
+ gst_pad_push_event (srcpad, gst_event_new_segment (&segment));
+
+ list = create_buffer_list ();
+
+ GST_DEBUG ("Waiting for agents to be ready ready");
+
+ g_main_loop_run (loop);
+
+ fail_unless_equals_int (gst_pad_push_list (srcpad, list), GST_FLOW_OK);
+
+ GST_DEBUG ("Waiting for buffers");
+ g_main_loop_run (loop);
+
+ fail_unless_equals_int (data_size, bytes_received);
+
+ gst_check_teardown_pad_by_name (nicesink, "sink");
+ gst_check_teardown_element (nicesink);
+
+ gst_check_teardown_pad_by_name (nicesrc, "src");
+ gst_check_teardown_element (nicesrc);
+
+ nice_address_free (addr);
+ g_main_loop_unref (loop);
+}
+
+GST_END_TEST;
+
+static Suite *
+udpsink_suite (void)
+{
+ Suite *s = suite_create ("nice_gstreamer_test");
+ TCase *tc_chain = tcase_create ("nice");
+
+ suite_add_tcase (s, tc_chain);
+
+ tcase_add_test (tc_chain, buffer_list_test);
+
+ return s;
+}
+
+GST_CHECK_MAIN (udpsink)
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * Unit test for ICE full-mode related features.
+ *
+ * (C) 2007 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Kai Vehmanen, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "agent.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+static NiceComponentState global_lagent_state[2] = { NICE_COMPONENT_STATE_LAST, NICE_COMPONENT_STATE_LAST };
+static NiceComponentState global_ragent_state[2] = { NICE_COMPONENT_STATE_LAST, NICE_COMPONENT_STATE_LAST };
+static guint global_components_ready = 0;
+static guint global_components_ready_exit = 0;
+static guint global_components_failed = 0;
+static guint global_components_failed_exit = 0;
+static GMainLoop *global_mainloop = NULL;
+static gboolean global_lagent_gathering_done = FALSE;
+static gboolean global_ragent_gathering_done = FALSE;
+static gboolean global_lagent_ibr_received = FALSE;
+static gboolean global_ragent_ibr_received = FALSE;
+static gboolean global_ready_reached = FALSE;
+static int global_lagent_cands = 0;
+static int global_ragent_cands = 0;
+static gint global_ragent_read = 0;
+static guint global_exit_when_ibr_received = 0;
+
+static void priv_print_global_status (void)
+{
+ g_debug ("\tgathering_done=%d", global_lagent_gathering_done && global_ragent_gathering_done);
+ g_debug ("\tlstate[rtp]=%d [rtcp]=%d", global_lagent_state[0], global_lagent_state[1]);
+ g_debug ("\trstate[rtp]=%d [rtcp]=%d", global_ragent_state[0], global_ragent_state[1]);
+ g_debug ("\tL cands=%d R cands=%d", global_lagent_cands, global_ragent_cands);
+}
+
+static gboolean timer_cb (gpointer pointer)
+{
+ g_debug ("test-icetcp:%s: %p", G_STRFUNC, pointer);
+
+ /* signal status via a global variable */
+
+ /* note: should not be reached, abort */
+ g_error ("ERROR: test has got stuck, aborting...");
+
+ return FALSE;
+}
+
+static void cb_writable (NiceAgent*agent, guint stream_id, guint component_id)
+{
+ g_debug ("Transport is now writable, stopping mainloop");
+ g_main_loop_quit (global_mainloop);
+}
+
+static void cb_nice_recv (NiceAgent *agent, guint stream_id, guint component_id, guint len, gchar *buf, gpointer user_data)
+{
+ g_debug ("test-icetcp:%s: %p", G_STRFUNC, user_data);
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent; (void)stream_id; (void)component_id; (void)buf;
+
+ /*
+ * Lets ignore stun packets that got through
+ */
+ if (len < 8)
+ return;
+ if (strncmp ("12345678", buf, 8))
+ return;
+
+ if (GPOINTER_TO_UINT (user_data) == 2) {
+ g_debug ("right agent received %d bytes, stopping mainloop", len);
+ global_ragent_read = len;
+ g_main_loop_quit (global_mainloop);
+ }
+}
+
+static void cb_candidate_gathering_done(NiceAgent *agent, guint stream_id, gpointer data)
+{
+ g_debug ("test-icetcp:%s: %p", G_STRFUNC, data);
+
+ if (GPOINTER_TO_UINT (data) == 1)
+ global_lagent_gathering_done = TRUE;
+ else if (GPOINTER_TO_UINT (data) == 2)
+ global_ragent_gathering_done = TRUE;
+
+ if (global_lagent_gathering_done &&
+ global_ragent_gathering_done)
+ g_main_loop_quit (global_mainloop);
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent;
+}
+
+static void check_loop_quit_condition (void)
+{
+ if (global_ready_reached &&
+ global_lagent_cands >= 2 && global_ragent_cands >= 2) {
+ g_main_loop_quit (global_mainloop);
+ }
+}
+
+static void cb_component_state_changed (NiceAgent *agent, guint stream_id, guint component_id, guint state, gpointer data)
+{
+ gboolean ready_to_connected = FALSE;
+ g_debug ("test-icetcp:%s: %p", G_STRFUNC, data);
+
+ if (GPOINTER_TO_UINT (data) == 1) {
+ if (global_lagent_state[component_id - 1] == NICE_COMPONENT_STATE_READY &&
+ state == NICE_COMPONENT_STATE_CONNECTED)
+ ready_to_connected = TRUE;
+ global_lagent_state[component_id - 1] = state;
+ } else if (GPOINTER_TO_UINT (data) == 2) {
+ if (global_ragent_state[component_id - 1] == NICE_COMPONENT_STATE_READY &&
+ state == NICE_COMPONENT_STATE_CONNECTED)
+ ready_to_connected = TRUE;
+ global_ragent_state[component_id - 1] = state;
+ }
+
+ if (state == NICE_COMPONENT_STATE_READY)
+ global_components_ready++;
+ else if (state == NICE_COMPONENT_STATE_CONNECTED && ready_to_connected)
+ global_components_ready--;
+ if (state == NICE_COMPONENT_STATE_FAILED)
+ global_components_failed++;
+
+ g_debug ("test-icetcp: checks READY/EXIT-AT %u/%u.", global_components_ready, global_components_ready_exit);
+ g_debug ("test-icetcp: checks FAILED/EXIT-AT %u/%u.", global_components_failed, global_components_failed_exit);
+
+ /* signal status via a global variable */
+ if (global_components_ready == global_components_ready_exit &&
+ global_components_failed == global_components_failed_exit &&
+ global_ready_reached == FALSE) {
+ g_debug ("Components ready/failed achieved. Stopping mailoop");
+ global_ready_reached = TRUE;
+ }
+
+ check_loop_quit_condition ();
+
+#if 0
+ /* signal status via a global variable */
+ if (global_components_failed == global_components_failed_exit) {
+ g_main_loop_quit (global_mainloop);
+ return;
+ }
+#endif
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent; (void)stream_id; (void)data; (void)component_id;
+}
+
+static void cb_new_selected_pair(NiceAgent *agent, guint stream_id, guint component_id,
+ gchar *lfoundation, gchar* rfoundation, gpointer data)
+{
+ g_debug ("test-icetcp:%s: %p", G_STRFUNC, data);
+
+ if (GPOINTER_TO_UINT (data) == 1)
+ ++global_lagent_cands;
+ else if (GPOINTER_TO_UINT (data) == 2)
+ ++global_ragent_cands;
+
+ check_loop_quit_condition ();
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent; (void)stream_id; (void)component_id; (void)lfoundation; (void)rfoundation;
+}
+
+static void cb_new_candidate(NiceAgent *agent, guint stream_id, guint component_id,
+ gchar *foundation, gpointer data)
+{
+ g_debug ("test-icetcp:%s: %p", G_STRFUNC, data);
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent; (void)stream_id; (void)data; (void)component_id; (void)foundation;
+}
+
+static void cb_initial_binding_request_received(NiceAgent *agent, guint stream_id, gpointer data)
+{
+ g_debug ("test-icetcp:%s: %p", G_STRFUNC, data);
+
+ if (GPOINTER_TO_UINT (data) == 1)
+ global_lagent_ibr_received = TRUE;
+ else if (GPOINTER_TO_UINT (data) == 2)
+ global_ragent_ibr_received = TRUE;
+
+ if (global_exit_when_ibr_received) {
+ g_debug ("Received initial binding request. Stopping mailoop");
+ g_main_loop_quit (global_mainloop);
+ }
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent; (void)stream_id; (void)data;
+}
+
+static void set_candidates (NiceAgent *from, guint from_stream,
+ NiceAgent *to, guint to_stream, guint component)
+{
+ GSList *cands = NULL, *i;
+
+ cands = nice_agent_get_local_candidates (from, from_stream, component);
+
+ restart:
+ for (i = cands; i; i = i->next) {
+ NiceCandidate *cand = i->data;
+ if (cand->transport == NICE_CANDIDATE_TRANSPORT_UDP) {
+ cands = g_slist_remove (cands, cand);
+ nice_candidate_free (cand);
+ goto restart;
+ }
+ }
+
+
+ nice_agent_set_remote_candidates (to, to_stream, component, cands);
+
+ for (i = cands; i; i = i->next)
+ nice_candidate_free ((NiceCandidate *) i->data);
+ g_slist_free (cands);
+}
+
+static void set_credentials (NiceAgent *lagent, guint lstream,
+ NiceAgent *ragent, guint rstream)
+{
+ gchar *ufrag = NULL, *password = NULL;
+
+ nice_agent_get_local_credentials(lagent, lstream, &ufrag, &password);
+ nice_agent_set_remote_credentials (ragent, rstream, ufrag, password);
+ g_free (ufrag);
+ g_free (password);
+ nice_agent_get_local_credentials(ragent, rstream, &ufrag, &password);
+ nice_agent_set_remote_credentials (lagent, lstream, ufrag, password);
+ g_free (ufrag);
+ g_free (password);
+}
+
+static int run_full_test (NiceAgent *lagent, NiceAgent *ragent, NiceAddress *baseaddr, guint ready, guint failed)
+{
+ guint ls_id, rs_id;
+ gint ret;
+
+ /* XXX: dear compiler, this is for you */
+ (void)baseaddr;
+
+ /* step: initialize variables modified by the callbacks */
+ global_components_ready = 0;
+ global_components_ready_exit = ready;
+ global_components_failed = 0;
+ global_components_failed_exit = failed;
+ global_lagent_gathering_done = FALSE;
+ global_ragent_gathering_done = FALSE;
+ global_lagent_ibr_received =
+ global_ragent_ibr_received = FALSE;
+ global_lagent_cands =
+ global_ragent_cands = 0;
+ global_ready_reached = FALSE;
+
+ g_object_set (G_OBJECT (lagent), "controlling-mode", TRUE, NULL);
+ g_object_set (G_OBJECT (ragent), "controlling-mode", FALSE, NULL);
+
+ /* step: add one stream, with RTP+RTCP components, to each agent */
+ ls_id = nice_agent_add_stream (lagent, 2);
+
+ rs_id = nice_agent_add_stream (ragent, 2);
+ g_assert (ls_id > 0);
+ g_assert (rs_id > 0);
+
+ /* Gather candidates */
+ g_assert (nice_agent_gather_candidates (lagent, ls_id) == TRUE);
+ g_assert (nice_agent_gather_candidates (ragent, rs_id) == TRUE);
+
+ {
+ GSList *cands = NULL, *i;
+ NiceCandidate *cand = NULL;
+
+ cands = nice_agent_get_local_candidates (lagent, ls_id, 1);
+ g_assert (g_slist_length (cands) == 2);
+ cand = cands->data;
+ g_assert (cand->type == NICE_CANDIDATE_TYPE_HOST);
+ g_assert (cand->transport == NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE ||
+ cand->transport == NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE);
+ cand = cands->next->data;
+ g_assert (cand->type == NICE_CANDIDATE_TYPE_HOST);
+ g_assert (cand->transport == NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE ||
+ cand->transport == NICE_CANDIDATE_TRANSPORT_TCP_PASSIVE);
+ for (i = cands; i; i = i->next)
+ nice_candidate_free ((NiceCandidate *) i->data);
+ g_slist_free (cands);
+ }
+
+ /* step: attach to mainloop (needed to register the fds) */
+ nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv,
+ GUINT_TO_POINTER (1));
+ nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTCP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv,
+ GUINT_TO_POINTER (1));
+ nice_agent_attach_recv (ragent, rs_id, NICE_COMPONENT_TYPE_RTP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv,
+ GUINT_TO_POINTER (2));
+ nice_agent_attach_recv (ragent, rs_id, NICE_COMPONENT_TYPE_RTCP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv,
+ GUINT_TO_POINTER (2));
+
+ /* step: run mainloop until local candidates are ready
+ * (see timer_cb() above) */
+ if (global_lagent_gathering_done != TRUE ||
+ global_ragent_gathering_done != TRUE) {
+ g_debug ("test-icetcp: Added streams, running mainloop until 'candidate-gathering-done'...");
+ g_main_loop_run (global_mainloop);
+ g_assert (global_lagent_gathering_done == TRUE);
+ g_assert (global_ragent_gathering_done == TRUE);
+ }
+
+ set_credentials (lagent, ls_id, ragent, rs_id);
+
+ /* step: pass the remote candidates to agents */
+ set_candidates (ragent, rs_id, lagent, ls_id, NICE_COMPONENT_TYPE_RTP);
+ set_candidates (ragent, rs_id, lagent, ls_id, NICE_COMPONENT_TYPE_RTCP);
+ set_candidates (lagent, ls_id, ragent, rs_id, NICE_COMPONENT_TYPE_RTP);
+ set_candidates (lagent, ls_id, ragent, rs_id, NICE_COMPONENT_TYPE_RTCP);
+
+ g_debug ("test-icetcp: Set properties, next running mainloop until connectivity checks succeed...");
+
+ /* step: run the mainloop until connectivity checks succeed
+ * (see timer_cb() above) */
+ g_main_loop_run (global_mainloop);
+
+ /* note: verify that STUN binding requests were sent */
+ g_assert (global_lagent_ibr_received == TRUE);
+ g_assert (global_ragent_ibr_received == TRUE);
+
+ /* note: test payload send and receive */
+ global_ragent_read = 0;
+ ret = nice_agent_send (lagent, ls_id, 1, 16, "1234567812345678");
+ if (ret == -1)
+ {
+ gboolean reliable = FALSE;
+ g_object_get (G_OBJECT (lagent), "reliable", &reliable, NULL);
+ g_debug ("Sending data returned -1 in %s mode", reliable?"Reliable":"Non-reliable");
+ if (reliable) {
+ gulong signal_handler;
+ signal_handler = g_signal_connect (G_OBJECT (lagent),
+ "reliable-transport-writable", G_CALLBACK (cb_writable), NULL);
+ g_debug ("Running mainloop until transport is writable");
+ g_main_loop_run (global_mainloop);
+ g_signal_handler_disconnect(G_OBJECT (lagent), signal_handler);
+
+ ret = nice_agent_send (lagent, ls_id, 1, 16, "1234567812345678");
+ }
+ }
+ g_debug ("Sent %d bytes", ret);
+ g_assert (ret == 16);
+ g_main_loop_run (global_mainloop);
+ g_assert (global_ragent_read == 16);
+
+ g_debug ("test-icetcp: Ran mainloop, removing streams...");
+
+ /* step: clean up resources and exit */
+
+ nice_agent_remove_stream (lagent, ls_id);
+ nice_agent_remove_stream (ragent, rs_id);
+
+ return 0;
+}
+
+int main (void)
+{
+ NiceAgent *lagent, *ragent; /* agent's L and R */
+ NiceAddress baseaddr;
+ int result;
+ guint timer_id;
+
+#ifdef G_OS_WIN32
+ WSADATA w;
+
+ WSAStartup(0x0202, &w);
+#endif
+
+ global_mainloop = g_main_loop_new (NULL, FALSE);
+
+ /* step: create the agents L and R */
+ lagent = nice_agent_new (g_main_loop_get_context (global_mainloop),
+ NICE_COMPATIBILITY_RFC5245);
+ ragent = nice_agent_new (g_main_loop_get_context (global_mainloop),
+ NICE_COMPATIBILITY_RFC5245);
+
+ g_object_set (G_OBJECT (lagent), "ice-udp", FALSE, NULL);
+ g_object_set (G_OBJECT (ragent), "ice-udp", FALSE, NULL);
+ g_object_set (G_OBJECT (lagent), "upnp", FALSE, NULL);
+ g_object_set (G_OBJECT (ragent), "upnp", FALSE, NULL);
+ nice_agent_set_software (lagent, "Test-icetcp, Left Agent");
+ nice_agent_set_software (ragent, "Test-icetcp, Right Agent");
+
+ /* step: add a timer to catch state changes triggered by signals */
+ timer_id = g_timeout_add (30000, timer_cb, NULL);
+
+ /* step: specify which local interface to use */
+ if (!nice_address_set_from_string (&baseaddr, "127.0.0.1"))
+ g_assert_not_reached ();
+ nice_agent_add_local_address (lagent, &baseaddr);
+ nice_agent_add_local_address (ragent, &baseaddr);
+
+ g_signal_connect (G_OBJECT (lagent), "candidate-gathering-done",
+ G_CALLBACK (cb_candidate_gathering_done), GUINT_TO_POINTER(1));
+ g_signal_connect (G_OBJECT (ragent), "candidate-gathering-done",
+ G_CALLBACK (cb_candidate_gathering_done), GUINT_TO_POINTER (2));
+ g_signal_connect (G_OBJECT (lagent), "component-state-changed",
+ G_CALLBACK (cb_component_state_changed), GUINT_TO_POINTER (1));
+ g_signal_connect (G_OBJECT (ragent), "component-state-changed",
+ G_CALLBACK (cb_component_state_changed), GUINT_TO_POINTER (2));
+ g_signal_connect (G_OBJECT (lagent), "new-selected-pair",
+ G_CALLBACK (cb_new_selected_pair), GUINT_TO_POINTER(1));
+ g_signal_connect (G_OBJECT (ragent), "new-selected-pair",
+ G_CALLBACK (cb_new_selected_pair), GUINT_TO_POINTER (2));
+ g_signal_connect (G_OBJECT (lagent), "new-candidate",
+ G_CALLBACK (cb_new_candidate), GUINT_TO_POINTER (1));
+ g_signal_connect (G_OBJECT (ragent), "new-candidate",
+ G_CALLBACK (cb_new_candidate), GUINT_TO_POINTER (2));
+ g_signal_connect (G_OBJECT (lagent), "initial-binding-request-received",
+ G_CALLBACK (cb_initial_binding_request_received),
+ GUINT_TO_POINTER (1));
+ g_signal_connect (G_OBJECT (ragent), "initial-binding-request-received",
+ G_CALLBACK (cb_initial_binding_request_received),
+ GUINT_TO_POINTER (2));
+
+ /* step: run test the first time */
+ g_debug ("test-icetcp: TEST STARTS / running test for the 1st time");
+ result = run_full_test (lagent, ragent, &baseaddr, 4 ,0);
+ priv_print_global_status ();
+ g_assert (result == 0);
+ g_assert (global_lagent_state[0] == NICE_COMPONENT_STATE_READY);
+ g_assert (global_lagent_state[1] == NICE_COMPONENT_STATE_READY);
+ g_assert (global_ragent_state[0] == NICE_COMPONENT_STATE_READY);
+ g_assert (global_ragent_state[1] == NICE_COMPONENT_STATE_READY);
+ /* note: verify that correct number of local candidates were reported */
+ g_assert (global_lagent_cands >= 2);
+ g_assert (global_ragent_cands >= 2);
+
+
+ /* step: run test again without unref'ing agents */
+ g_debug ("test-icetcp: TEST STARTS / running test for the 2nd time");
+ result = run_full_test (lagent, ragent, &baseaddr, 4, 0);
+ priv_print_global_status ();
+ g_assert (result == 0);
+ g_assert (global_lagent_state[0] == NICE_COMPONENT_STATE_READY);
+ g_assert (global_lagent_state[1] == NICE_COMPONENT_STATE_READY);
+ g_assert (global_ragent_state[0] == NICE_COMPONENT_STATE_READY);
+ g_assert (global_ragent_state[1] == NICE_COMPONENT_STATE_READY);
+ /* note: verify that correct number of local candidates were reported */
+ g_assert (global_lagent_cands >= 2);
+ g_assert (global_ragent_cands >= 2);
+
+ g_object_unref (lagent);
+ g_object_unref (ragent);
+
+ g_main_loop_unref (global_mainloop);
+ global_mainloop = NULL;
+
+ g_source_remove (timer_id);
+#ifdef G_OS_WIN32
+ WSACleanup();
+#endif
+ return result;
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2014 Collabora Ltd.
+ * Contact: Philip Withnall
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Philip Withnall, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "agent.h"
+#include "test-io-stream-common.h"
+
+#include <stdlib.h>
+#include <string.h>
+#ifndef G_OS_WIN32
+#include <unistd.h>
+#endif
+
+typedef struct {
+ GCancellable *cancellable; /* owned */
+
+ GCond cond;
+ GMutex mutex;
+ gboolean blocking; /* protected by @mutex */
+} CancellationData;
+
+static gpointer
+cancellation_thread_cb (gpointer user_data)
+{
+ CancellationData *data = user_data;
+
+ /* Wait to be signalled from read_thread_cb(). */
+ g_mutex_lock (&data->mutex);
+ while (!data->blocking)
+ g_cond_wait (&data->cond, &data->mutex);
+ g_mutex_unlock (&data->mutex);
+
+ /* Try and ensure we cancel part-way through the read, rather than before the
+ * read function is called. */
+ g_usleep (100000);
+
+ g_cancellable_cancel (data->cancellable);
+
+ return NULL;
+}
+
+static void
+read_thread_cb (GInputStream *input_stream, TestIOStreamThreadData *data)
+{
+ CancellationData *user_data = data->user_data;
+ GError *error = NULL;
+ guint8 buf[MESSAGE_SIZE];
+ gssize len;
+
+ /* Block on receiving some data or cancellation. */
+ g_mutex_lock (&user_data->mutex);
+ user_data->blocking = TRUE;
+ g_cond_signal (&user_data->cond);
+ g_mutex_unlock (&user_data->mutex);
+
+ len = g_input_stream_read (input_stream, buf, sizeof (buf),
+ user_data->cancellable, &error);
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
+ g_error_free (error);
+ g_assert (len == -1);
+
+ g_main_loop_quit (data->error_loop);
+}
+
+int main (void)
+{
+ GThread *l_cancellation_thread, *r_cancellation_thread;
+ CancellationData l_data, r_data;
+
+ const TestIOStreamCallbacks callbacks = {
+ read_thread_cb,
+ NULL,
+ NULL,
+ NULL,
+ };
+
+#ifdef G_OS_WIN32
+ WSADATA w;
+ WSAStartup (0x0202, &w);
+#endif
+
+ l_data.cancellable = g_cancellable_new ();
+ l_data.blocking = FALSE;
+ g_cond_init (&l_data.cond);
+ g_mutex_init (&l_data.mutex);
+
+ r_data.cancellable = g_cancellable_new ();
+ r_data.blocking = FALSE;
+ g_cond_init (&r_data.cond);
+ g_mutex_init (&r_data.mutex);
+
+ l_cancellation_thread = spawn_thread ("libnice L cancel",
+ cancellation_thread_cb, &l_data);
+ r_cancellation_thread = spawn_thread ("libnice R cancel",
+ cancellation_thread_cb, &r_data);
+
+ run_io_stream_test (30, TRUE, &callbacks, &l_data, NULL, &r_data, NULL);
+
+ g_thread_join (l_cancellation_thread);
+ g_thread_join (r_cancellation_thread);
+
+ /* Free things. */
+ g_object_unref (r_data.cancellable);
+ g_object_unref (l_data.cancellable);
+ g_cond_clear (&l_data.cond);
+ g_cond_clear (&r_data.cond);
+ g_mutex_clear (&l_data.mutex);
+ g_mutex_clear (&r_data.mutex);
+
+#ifdef G_OS_WIN32
+ WSACleanup ();
+#endif
+
+ return 0;
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2014 Collabora Ltd.
+ * Contact: Philip Withnall
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Philip Withnall, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "agent.h"
+#include "test-io-stream-common.h"
+
+#include <stdlib.h>
+#include <string.h>
+#ifndef G_OS_WIN32
+#include <unistd.h>
+#endif
+
+#define NUM_MESSAGES 10
+
+guint count = 0;
+GMutex count_lock;
+GCond count_cond;
+
+static void
+read_thread_cb (GInputStream *input_stream, TestIOStreamThreadData *data)
+{
+ GError *error = NULL;
+ gssize len;
+ guint8 buf[MESSAGE_SIZE];
+
+
+ g_mutex_lock (&count_lock);
+ count++;
+ g_cond_broadcast (&count_cond);
+ g_mutex_unlock (&count_lock);
+
+ /* Block on receiving some data. */
+ do {
+ len = g_input_stream_read (input_stream, buf, sizeof (buf), NULL, &error);
+ if (!data->user_data) {
+ g_assert_cmpint (len, ==, sizeof(buf));
+ return;
+ }
+ } while (len > 0);
+ g_assert_cmpint (len, ==, -1);
+
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_BROKEN_PIPE);
+ g_clear_error (&error);
+
+ stop_main_loop (data->error_loop);
+}
+
+static void
+write_thread_cb (GOutputStream *output_stream, TestIOStreamThreadData *data)
+{
+ gchar buf[MESSAGE_SIZE] = {0};
+ gssize ret;
+ GError *error = NULL;
+ gpointer tmp;
+ guint stream_id;
+
+ ret = g_output_stream_write (output_stream, buf, sizeof (buf), NULL,
+ &error);
+
+ g_mutex_lock (&count_lock);
+ count++;
+ g_cond_broadcast (&count_cond);
+ if (data->user_data) {
+ g_assert_cmpint (ret, ==, sizeof(buf));
+ g_mutex_unlock (&count_lock);
+ return;
+ }
+
+ while (count != 4)
+ g_cond_wait (&count_cond, &count_lock);
+ g_mutex_unlock (&count_lock);
+
+
+ /* Now we remove the stream, lets see how the writer handles that */
+
+ tmp = g_object_get_data (G_OBJECT (data->other->agent), "stream-id");
+ stream_id = GPOINTER_TO_UINT (tmp);
+
+ nice_agent_remove_stream (data->other->agent, stream_id);
+}
+
+int main (void)
+{
+ const TestIOStreamCallbacks callbacks = {
+ read_thread_cb,
+ write_thread_cb,
+ NULL,
+ NULL,
+ };
+
+#ifdef G_OS_WIN32
+ WSADATA w;
+ WSAStartup (0x0202, &w);
+#endif
+
+ run_io_stream_test (30, TRUE, &callbacks, (gpointer) TRUE, NULL, NULL, NULL);
+
+#ifdef G_OS_WIN32
+ WSACleanup ();
+#endif
+
+ return 0;
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2014 Collabora Ltd.
+ * Contact: Philip Withnall
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Philip Withnall, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "agent.h"
+#include "test-io-stream-common.h"
+
+#include <stdlib.h>
+#include <string.h>
+#ifndef G_OS_WIN32
+#include <unistd.h>
+#endif
+
+#define NUM_MESSAGES 10
+
+guint count = 0;
+GMutex count_lock;
+GCond count_cond;
+
+static void
+read_thread_cb (GInputStream *input_stream, TestIOStreamThreadData *data)
+{
+ gpointer tmp;
+ guint stream_id;
+ GError *error = NULL;
+ gssize len;
+ guint8 buf[MESSAGE_SIZE];
+
+ /* Block on receiving some data. */
+ len = g_input_stream_read (input_stream, buf, sizeof (buf), NULL, &error);
+ g_assert_cmpint (len, ==, sizeof(buf));
+
+ g_mutex_lock (&count_lock);
+ count++;
+ g_cond_broadcast (&count_cond);
+ if (data->user_data) {
+ g_mutex_unlock (&count_lock);
+ return;
+ }
+
+ while (count != 4)
+ g_cond_wait (&count_cond, &count_lock);
+ g_mutex_unlock (&count_lock);
+
+ /* Now we remove the stream, lets see how the writer handles that */
+
+ tmp = g_object_get_data (G_OBJECT (data->other->agent), "stream-id");
+ stream_id = GPOINTER_TO_UINT (tmp);
+
+ nice_agent_remove_stream (data->other->agent, stream_id);
+}
+
+static void
+write_thread_cb (GOutputStream *output_stream, TestIOStreamThreadData *data)
+{
+ gchar buf[MESSAGE_SIZE] = {0};
+ gssize ret;
+ GError *error = NULL;
+
+ g_mutex_lock (&count_lock);
+ count++;
+ g_cond_broadcast (&count_cond);
+ g_mutex_unlock (&count_lock);
+
+ do {
+ g_assert_no_error (error);
+ ret = g_output_stream_write (output_stream, buf, sizeof (buf), NULL,
+ &error);
+
+ if (!data->user_data) {
+ g_assert_cmpint (ret, ==, sizeof (buf));
+ return;
+ }
+ } while (ret > 0);
+ g_assert_cmpint (ret, ==, -1);
+
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED);
+ g_clear_error (&error);
+
+ stop_main_loop (data->error_loop);
+}
+
+int main (void)
+{
+ const TestIOStreamCallbacks callbacks = {
+ read_thread_cb,
+ write_thread_cb,
+ NULL,
+ NULL,
+ };
+
+#ifdef G_OS_WIN32
+ WSADATA w;
+ WSAStartup (0x0202, &w);
+#endif
+
+ run_io_stream_test (30, TRUE, &callbacks, (gpointer) TRUE, NULL, NULL, NULL);
+
+#ifdef G_OS_WIN32
+ WSACleanup ();
+#endif
+
+ return 0;
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2014 Collabora Ltd.
+ * Contact: Philip Withnall
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Philip Withnall, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "agent.h"
+#include "test-io-stream-common.h"
+
+#include <stdlib.h>
+#include <string.h>
+#ifndef G_OS_WIN32
+#include <unistd.h>
+#endif
+
+GMutex start_mutex;
+GCond start_cond;
+gboolean started;
+
+/* Waits about 10 seconds for @var to be NULL/FALSE */
+#define WAIT_UNTIL_UNSET(var, context) \
+ if (var) \
+ { \
+ int i; \
+ \
+ for (i = 0; i < 13 && (var); i++) \
+ { \
+ g_usleep (1000 * (1 << i)); \
+ g_main_context_iteration (context, FALSE); \
+ } \
+ \
+ g_assert (!(var)); \
+ }
+
+static gboolean timer_cb (gpointer pointer)
+{
+ g_debug ("test-thread:%s: %p", G_STRFUNC, pointer);
+
+ /* note: should not be reached, abort */
+ g_debug ("ERROR: test has got stuck, aborting...");
+ exit (-1);
+}
+
+static void
+wait_for_start (TestIOStreamThreadData *data)
+{
+ g_mutex_lock (data->start_mutex);
+ (*data->start_count)--;
+ g_cond_broadcast (data->start_cond);
+ while (*data->start_count > 0)
+ g_cond_wait (data->start_cond, data->start_mutex);
+ g_mutex_unlock (data->start_mutex);
+}
+
+static gpointer
+write_thread_cb (gpointer user_data)
+{
+ TestIOStreamThreadData *data = user_data;
+ GMainContext *main_context;
+ GOutputStream *output_stream = NULL;
+
+ main_context = g_main_context_new ();
+ g_main_context_push_thread_default (main_context);
+
+ /* Synchronise thread starting. */
+ wait_for_start (data);
+
+ /* Wait for the stream to be writeable. */
+ g_mutex_lock (&data->write_mutex);
+ while (!(data->stream_open && data->stream_ready))
+ g_cond_wait (&data->write_cond, &data->write_mutex);
+ g_mutex_unlock (&data->write_mutex);
+
+ if (data->reliable)
+ output_stream = g_io_stream_get_output_stream (data->io_stream);
+ data->callbacks->write_thread (output_stream, data);
+
+ g_main_context_pop_thread_default (main_context);
+ g_main_context_unref (main_context);
+
+ return NULL;
+}
+
+static gpointer
+read_thread_cb (gpointer user_data)
+{
+ TestIOStreamThreadData *data = user_data;
+ GMainContext *main_context;
+ GInputStream *input_stream = NULL;
+
+ main_context = g_main_context_new ();
+ g_main_context_push_thread_default (main_context);
+
+ /* Synchronise thread starting. */
+ wait_for_start (data);
+
+ if (data->reliable)
+ input_stream = g_io_stream_get_input_stream (data->io_stream);
+ data->callbacks->read_thread (input_stream, data);
+
+ g_main_context_pop_thread_default (main_context);
+ g_main_context_unref (main_context);
+
+ return NULL;
+}
+
+static gpointer
+main_thread_cb (gpointer user_data)
+{
+ TestIOStreamThreadData *data = user_data;
+
+ g_main_context_push_thread_default (data->main_context);
+
+ /* Synchronise thread starting. */
+ wait_for_start (data);
+
+ /* Run the main context. */
+ g_main_loop_run (data->main_loop);
+
+ g_main_context_pop_thread_default (data->main_context);
+
+ return NULL;
+}
+
+static void
+candidate_gathering_done_cb (NiceAgent *agent, guint stream_id,
+ gpointer user_data)
+{
+ NiceAgent *other = g_object_get_data (G_OBJECT (agent), "other-agent");
+ gchar *ufrag = NULL, *password = NULL;
+ GSList *cands, *i;
+ guint id, other_id;
+ gpointer tmp;
+
+ tmp = g_object_get_data (G_OBJECT (agent), "stream-id");
+ id = GPOINTER_TO_UINT (tmp);
+ tmp = g_object_get_data (G_OBJECT (other), "stream-id");
+ other_id = GPOINTER_TO_UINT (tmp);
+
+ nice_agent_get_local_credentials (agent, id, &ufrag, &password);
+ nice_agent_set_remote_credentials (other,
+ other_id, ufrag, password);
+ g_free (ufrag);
+ g_free (password);
+
+ cands = nice_agent_get_local_candidates (agent, id, 1);
+ g_assert (cands != NULL);
+
+ nice_agent_set_remote_candidates (other, other_id, 1, cands);
+
+ for (i = cands; i; i = i->next)
+ nice_candidate_free ((NiceCandidate *) i->data);
+ g_slist_free (cands);
+}
+
+static void
+reliable_transport_writable_cb (NiceAgent *agent, guint stream_id,
+ guint component_id, gpointer user_data)
+{
+ TestIOStreamThreadData *data = user_data;
+
+ g_assert (data->reliable);
+
+ /* Signal writeability. */
+ g_mutex_lock (&data->write_mutex);
+ data->stream_open = TRUE;
+ g_cond_broadcast (&data->write_cond);
+ g_mutex_unlock (&data->write_mutex);
+
+ if (data->callbacks->reliable_transport_writable != NULL) {
+ GIOStream *io_stream;
+ GOutputStream *output_stream;
+
+ io_stream = g_object_get_data (G_OBJECT (agent), "io-stream");
+ g_assert (io_stream != NULL);
+ output_stream = g_io_stream_get_output_stream (io_stream);
+
+ data->callbacks->reliable_transport_writable (output_stream, agent,
+ stream_id, component_id, data);
+ }
+}
+
+static void
+component_state_changed_cb (NiceAgent *agent, guint stream_id,
+ guint component_id, guint state, gpointer user_data)
+{
+ TestIOStreamThreadData *data = user_data;
+
+ if (state != NICE_COMPONENT_STATE_READY)
+ return;
+
+ /* Signal stream state. */
+ g_mutex_lock (&data->write_mutex);
+ data->stream_ready = TRUE;
+ g_cond_broadcast (&data->write_cond);
+ g_mutex_unlock (&data->write_mutex);
+}
+
+static void
+new_selected_pair_cb (NiceAgent *agent, guint stream_id, guint component_id,
+ gchar *lfoundation, gchar *rfoundation, gpointer user_data)
+{
+ TestIOStreamThreadData *data = user_data;
+
+ if (data->callbacks->new_selected_pair != NULL) {
+ data->callbacks->new_selected_pair (agent, stream_id, component_id,
+ lfoundation, rfoundation, data);
+ }
+}
+
+static NiceAgent *
+create_agent (gboolean controlling_mode, TestIOStreamThreadData *data,
+ GMainContext **main_context, GMainLoop **main_loop)
+{
+ NiceAgent *agent;
+ NiceAddress base_addr;
+ const gchar *stun_server, *stun_server_port;
+
+ /* Create main contexts. */
+ *main_context = g_main_context_new ();
+ *main_loop = g_main_loop_new (*main_context, FALSE);
+
+ /* Use Google compatibility to ignore credentials. */
+ if (data->reliable)
+ agent = nice_agent_new_reliable (*main_context, NICE_COMPATIBILITY_GOOGLE);
+ else
+ agent = nice_agent_new (*main_context, NICE_COMPATIBILITY_GOOGLE);
+
+ g_object_set (G_OBJECT (agent),
+ "controlling-mode", controlling_mode,
+ "upnp", FALSE,
+ NULL);
+
+ /* Specify which local interface to use. */
+ g_assert (nice_address_set_from_string (&base_addr, "127.0.0.1"));
+ nice_agent_add_local_address (agent, &base_addr);
+
+ /* Hook up signals. */
+ g_signal_connect (G_OBJECT (agent), "candidate-gathering-done",
+ (GCallback) candidate_gathering_done_cb,
+ GUINT_TO_POINTER (controlling_mode));
+ g_signal_connect (G_OBJECT (agent), "new-selected-pair",
+ (GCallback) new_selected_pair_cb, data);
+ g_signal_connect (G_OBJECT (agent), "component-state-changed",
+ (GCallback) component_state_changed_cb, data);
+
+ if (data->reliable) {
+ g_signal_connect (G_OBJECT (agent), "reliable-transport-writable",
+ (GCallback) reliable_transport_writable_cb, data);
+ } else {
+ data->stream_open = TRUE;
+ }
+
+ /* Configure the STUN server. */
+ stun_server = g_getenv ("NICE_STUN_SERVER");
+ stun_server_port = g_getenv ("NICE_STUN_SERVER_PORT");
+
+ if (stun_server != NULL) {
+ g_object_set (G_OBJECT (agent),
+ "stun-server", stun_server,
+ "stun-server-port", atoi (stun_server_port),
+ NULL);
+ }
+
+ return agent;
+}
+
+static void
+add_stream (NiceAgent *agent)
+{
+ guint stream_id;
+
+ stream_id = nice_agent_add_stream (agent, 2);
+ g_assert (stream_id > 0);
+
+ g_object_set_data (G_OBJECT (agent), "stream-id",
+ GUINT_TO_POINTER (stream_id));
+}
+
+static void
+run_agent (TestIOStreamThreadData *data, NiceAgent *agent)
+{
+ guint stream_id;
+ gpointer tmp;
+
+ tmp = g_object_get_data (G_OBJECT (agent), "stream-id");
+ stream_id = GPOINTER_TO_UINT (tmp);
+
+ nice_agent_gather_candidates (agent, stream_id);
+
+ if (data->reliable) {
+ data->io_stream =
+ G_IO_STREAM (nice_agent_get_io_stream (agent, stream_id, 1));
+ g_object_set_data (G_OBJECT (agent), "io-stream", data->io_stream);
+ } else {
+ data->io_stream = NULL;
+ }
+}
+
+GThread *
+spawn_thread (const gchar *thread_name, GThreadFunc thread_func,
+ gpointer user_data)
+{
+ GThread *thread;
+
+ thread = g_thread_new (thread_name, thread_func, user_data);
+ g_assert (thread);
+
+ return thread;
+}
+
+void
+run_io_stream_test (guint deadlock_timeout, gboolean reliable,
+ const TestIOStreamCallbacks *callbacks,
+ gpointer l_user_data, GDestroyNotify l_user_data_free,
+ gpointer r_user_data, GDestroyNotify r_user_data_free)
+{
+ GMainLoop *error_loop;
+ GThread *l_main_thread, *r_main_thread;
+ GThread *l_write_thread, *l_read_thread, *r_write_thread, *r_read_thread;
+ TestIOStreamThreadData l_data, r_data;
+ GMutex mutex;
+ GCond cond;
+ guint start_count = 6;
+ guint stream_id;
+
+ g_mutex_init (&mutex);
+ g_cond_init (&cond);
+
+ error_loop = g_main_loop_new (NULL, FALSE);
+
+ /* Set up data structures. */
+ l_data.reliable = reliable;
+ l_data.error_loop = error_loop;
+ l_data.callbacks = callbacks;
+ l_data.user_data = l_user_data;
+ l_data.user_data_free = l_user_data_free;
+
+ g_cond_init (&l_data.write_cond);
+ g_mutex_init (&l_data.write_mutex);
+ l_data.stream_open = FALSE;
+ l_data.stream_ready = FALSE;
+ l_data.start_mutex = &mutex;
+ l_data.start_cond = &cond;
+ l_data.start_count = &start_count;
+
+ r_data.reliable = reliable;
+ r_data.error_loop = error_loop;
+ r_data.callbacks = callbacks;
+ r_data.user_data = r_user_data;
+ r_data.user_data_free = r_user_data_free;
+
+ g_cond_init (&r_data.write_cond);
+ g_mutex_init (&r_data.write_mutex);
+ r_data.stream_open = FALSE;
+ r_data.stream_ready = FALSE;
+ r_data.start_mutex = &mutex;
+ r_data.start_cond = &cond;
+ r_data.start_count = &start_count;
+
+ l_data.other = &r_data;
+ r_data.other = &l_data;
+
+ /* Create the L and R agents. */
+ l_data.agent = create_agent (TRUE, &l_data,
+ &l_data.main_context, &l_data.main_loop);
+ r_data.agent = create_agent (FALSE, &r_data,
+ &r_data.main_context, &r_data.main_loop);
+
+ g_object_set_data (G_OBJECT (l_data.agent), "other-agent", r_data.agent);
+ g_object_set_data (G_OBJECT (r_data.agent), "other-agent", l_data.agent);
+
+ /* Add a timer to catch deadlocks. */
+ g_timeout_add_seconds (deadlock_timeout, timer_cb, NULL);
+
+ l_main_thread = spawn_thread ("libnice L main", main_thread_cb, &l_data);
+ r_main_thread = spawn_thread ("libnice R main", main_thread_cb, &r_data);
+
+ add_stream (l_data.agent);
+ add_stream (r_data.agent);
+ run_agent (&l_data, l_data.agent);
+ run_agent (&r_data, r_data.agent);
+
+ l_read_thread = spawn_thread ("libnice L read", read_thread_cb, &l_data);
+ r_read_thread = spawn_thread ("libnice R read", read_thread_cb, &r_data);
+
+ if (callbacks->write_thread != NULL) {
+ l_write_thread = spawn_thread ("libnice L write", write_thread_cb, &l_data);
+ r_write_thread = spawn_thread ("libnice R write", write_thread_cb, &r_data);
+ } else {
+ g_mutex_lock (&mutex);
+ start_count -= 2;
+ g_cond_broadcast (&cond);
+ g_mutex_unlock (&mutex);
+
+ l_write_thread = NULL;
+ r_write_thread = NULL;
+ }
+
+ /* Run loop for error timer */
+ g_main_loop_run (error_loop);
+
+ /* Clean up the main loops and threads. */
+ stop_main_loop (l_data.main_loop);
+ stop_main_loop (r_data.main_loop);
+
+ g_thread_join (l_read_thread);
+ g_thread_join (r_read_thread);
+ if (l_write_thread != NULL)
+ g_thread_join (l_write_thread);
+ if (r_write_thread != NULL)
+ g_thread_join (r_write_thread);
+ g_thread_join (l_main_thread);
+ g_thread_join (r_main_thread);
+
+ /* Free things. */
+ if (r_data.user_data_free != NULL)
+ r_data.user_data_free (r_data.user_data);
+
+ if (l_data.user_data_free != NULL)
+ l_data.user_data_free (l_data.user_data);
+
+ g_cond_clear (&r_data.write_cond);
+ g_mutex_clear (&r_data.write_mutex);
+ g_cond_clear (&l_data.write_cond);
+ g_mutex_clear (&l_data.write_mutex);
+
+ if (r_data.io_stream != NULL)
+ g_object_unref (r_data.io_stream);
+ if (l_data.io_stream != NULL)
+ g_object_unref (l_data.io_stream);
+
+ stream_id =
+ GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (r_data.agent), "stream-id"));
+ if (stream_id != 0)
+ nice_agent_remove_stream (r_data.agent, stream_id);
+ stream_id =
+ GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (l_data.agent), "stream-id"));
+ if (stream_id != 0)
+ nice_agent_remove_stream (l_data.agent, stream_id);
+
+ g_object_add_weak_pointer (G_OBJECT (r_data.agent),
+ (gpointer *) &r_data.agent);
+ g_object_add_weak_pointer (G_OBJECT (l_data.agent),
+ (gpointer *) &l_data.agent);
+
+ g_object_unref (r_data.agent);
+ g_object_unref (l_data.agent);
+
+ WAIT_UNTIL_UNSET (r_data.agent, r_data.main_context);
+ WAIT_UNTIL_UNSET (l_data.agent, l_data.main_context);
+
+ g_main_loop_unref (r_data.main_loop);
+ g_main_loop_unref (l_data.main_loop);
+
+ g_main_context_unref (r_data.main_context);
+ g_main_context_unref (l_data.main_context);
+
+ g_main_loop_unref (error_loop);
+
+ g_mutex_clear (&mutex);
+ g_cond_clear (&cond);
+}
+
+/* Once we’ve received all the expected bytes, wait to finish sending all bytes,
+ * then send and wait for the close message. Finally, remove the stream.
+ *
+ * This must only be called from the read thread implementation. */
+void
+check_for_termination (TestIOStreamThreadData *data, gsize *recv_count,
+ gsize *other_recv_count, volatile gsize *send_count, gsize expected_recv_count)
+{
+ guint stream_id;
+ gpointer tmp;
+
+ /* Wait for transmission to complete. */
+ while (*send_count < expected_recv_count) {
+ if (data->callbacks->wait_transmission_cb) {
+ data->callbacks->wait_transmission_cb (data->agent);
+ }
+ }
+
+ /* Send a close message. */
+ tmp = g_object_get_data (G_OBJECT (data->agent), "stream-id");
+ stream_id = GPOINTER_TO_UINT (tmp);
+
+ /* Can't be certain enough to test for termination on non-reliable streams.
+ * There may be packet losses, etc
+ */
+ if (data->reliable) {
+ guint8 buf[65536];
+ gsize buf_len;
+ gssize len;
+ GError *error = NULL;
+
+ g_assert_cmpuint (*recv_count, >=, expected_recv_count);
+
+ buf_len = strlen ("Done");
+ memcpy (buf, "Done", buf_len);
+ len = nice_agent_send (data->agent, stream_id, 1, buf_len, (gchar *) buf);
+ g_assert_cmpint (len, ==, buf_len);
+
+ /* Wait for a done packet. */
+ len = nice_agent_recv (data->agent, stream_id, 1, buf, buf_len, NULL,
+ &error);
+ g_assert_no_error (error);
+
+ g_assert_cmpint (len, ==, strlen ("Done"));
+ g_assert_cmpint (memcmp (buf, "Done", strlen ("Done")), ==, 0);
+
+ *recv_count = *recv_count + 1;
+ }
+
+ /* Remove the stream and run away. */
+ nice_agent_remove_stream (data->agent, stream_id);
+ g_object_set_data (G_OBJECT (data->agent), "stream-id", GUINT_TO_POINTER (0));
+
+ /* If both sides have finished, quit the test main loop. */
+ if (*recv_count > expected_recv_count &&
+ *other_recv_count > expected_recv_count) {
+ g_main_loop_quit (data->error_loop);
+ }
+}
+
+void
+stop_main_loop (GMainLoop *loop)
+{
+ GSource *src = g_idle_source_new ();
+ g_source_set_callback (src, G_SOURCE_FUNC (g_main_loop_quit),
+ g_main_loop_ref (loop), (GDestroyNotify) g_main_loop_unref);
+ g_source_attach (src, g_main_loop_get_context (loop));
+ g_source_unref (src);
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2014 Collabora Ltd.
+ * Contact: Philip Withnall
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Philip Withnall, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "agent.h"
+
+#include <stdlib.h>
+#include <string.h>
+#ifndef G_OS_WIN32
+#include <unistd.h>
+#endif
+
+#if !GLIB_CHECK_VERSION(2, 58, 0)
+#define G_SOURCE_FUNC(f) ((GSourceFunc) (void (*)(void)) (f))
+#endif
+
+/* Make the message sufficiently large to not hit Nagle’s algorithm in the
+ * pseudo-TCP implementation, and hence run really slowly. */
+#define MESSAGE_SIZE 1284 /* bytes */
+
+typedef struct _TestIOStreamThreadData TestIOStreamThreadData;
+
+typedef struct {
+ void (*read_thread) (GInputStream *input_stream,
+ TestIOStreamThreadData *data);
+ void (*write_thread) (GOutputStream *output_stream,
+ TestIOStreamThreadData *data);
+ void (*reliable_transport_writable) (GOutputStream *output_stream,
+ NiceAgent *agent, guint stream_id, guint component_id,
+ TestIOStreamThreadData *data);
+ void (*new_selected_pair) (NiceAgent *agent, guint stream_id,
+ guint component_id, gchar *lfoundation, gchar *rfoundation,
+ TestIOStreamThreadData *data);
+ void (*wait_transmission_cb) (NiceAgent *agent);
+} TestIOStreamCallbacks;
+
+struct _TestIOStreamThreadData {
+ NiceAgent *agent;
+ GIOStream *io_stream;
+
+ gboolean reliable;
+
+ GMainLoop *main_loop;
+ GMainLoop *error_loop;
+
+ GMainContext *main_context;
+ GMainContext *write_context;
+ GMainContext *read_context;
+
+ gpointer user_data;
+ GDestroyNotify user_data_free;
+
+ TestIOStreamThreadData *other;
+
+ /*< private >*/
+ const TestIOStreamCallbacks *callbacks;
+
+ /* Condition signalling for the stream being open/writeable. */
+ gboolean stream_open;
+ gboolean stream_ready;
+ GCond write_cond;
+ GMutex write_mutex;
+
+ GMutex *start_mutex;
+ GCond *start_cond;
+ guint *start_count;
+};
+
+GThread *spawn_thread (const gchar *thread_name, GThreadFunc thread_func,
+ gpointer user_data);
+void run_io_stream_test (guint deadlock_timeout, gboolean reliable,
+ const TestIOStreamCallbacks *callbacks,
+ gpointer l_user_data, GDestroyNotify l_user_data_free,
+ gpointer r_user_data, GDestroyNotify r_user_data_free);
+void check_for_termination (TestIOStreamThreadData *data, gsize *recv_count,
+ gsize *other_recv_count, volatile gsize *send_count, gsize expected_recv_count);
+
+void stop_main_loop (GMainLoop *loop);
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2014 Collabora Ltd.
+ * Contact: Philip Withnall
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Philip Withnall, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "agent.h"
+#include "test-io-stream-common.h"
+
+#include <stdlib.h>
+#include <string.h>
+#ifndef G_OS_WIN32
+#include <unistd.h>
+#endif
+
+typedef struct {
+ GMainLoop *read_loop; /* unowned */
+
+ gsize recv_count;
+ gsize *other_recv_count;
+
+ gsize send_count;
+ gsize *other_send_count;
+} ThreadData;
+
+static gboolean
+read_stream_cb (GObject *pollable_stream, gpointer _user_data)
+{
+ TestIOStreamThreadData *data = _user_data;
+ ThreadData *user_data = data->user_data;
+ gchar expected_data[MESSAGE_SIZE];
+ GError *error = NULL;
+ guint8 buf[MESSAGE_SIZE];
+ gssize len;
+
+ /* Try to receive some data. */
+ len = g_pollable_input_stream_read_nonblocking (
+ G_POLLABLE_INPUT_STREAM (pollable_stream), buf, sizeof (buf), NULL,
+ &error);
+
+ if (len == -1) {
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK);
+ g_error_free (error);
+ return TRUE;
+ }
+
+ g_assert_cmpint (len, ==, MESSAGE_SIZE);
+
+ memset (expected_data, user_data->recv_count + '1', sizeof (expected_data));
+ g_assert (memcmp (buf, expected_data, sizeof (expected_data)) == 0);
+
+ user_data->recv_count++;
+
+ if (user_data->recv_count == 10) {
+ g_main_loop_quit (user_data->read_loop);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+read_thread_cb (GInputStream *input_stream, TestIOStreamThreadData *data)
+{
+ GMainContext *main_context;
+ GMainLoop *main_loop;
+ GSource *stream_source;
+ ThreadData *user_data = data->user_data;
+
+ main_context = g_main_context_new ();
+ main_loop = g_main_loop_new (main_context, FALSE);
+ g_main_context_push_thread_default (main_context);
+
+ stream_source =
+ g_pollable_input_stream_create_source (
+ G_POLLABLE_INPUT_STREAM (input_stream), NULL);
+
+ g_source_set_callback (stream_source, G_SOURCE_FUNC (read_stream_cb),
+ data, NULL);
+ g_source_attach (stream_source, main_context);
+ g_source_unref (stream_source);
+
+ /* Run the main loop. */
+ user_data->read_loop = main_loop;
+ g_main_loop_run (main_loop);
+
+ g_main_context_pop_thread_default (main_context);
+ g_main_loop_unref (main_loop);
+ g_main_context_unref (main_context);
+
+ check_for_termination (data, &user_data->recv_count,
+ user_data->other_recv_count, &user_data->send_count, 10);
+}
+
+static void
+write_thread_cb (GOutputStream *output_stream, TestIOStreamThreadData *data)
+{
+ ThreadData *user_data = data->user_data;
+ guint8 buf[MESSAGE_SIZE];
+
+ for (user_data->send_count = 0;
+ user_data->send_count < 10;
+ user_data->send_count++) {
+ GError *error = NULL;
+
+ memset (buf, user_data->send_count + '1', MESSAGE_SIZE);
+
+ g_pollable_output_stream_write_nonblocking (
+ G_POLLABLE_OUTPUT_STREAM (output_stream), buf, sizeof (buf), NULL,
+ &error);
+ g_assert_no_error (error);
+ }
+}
+
+int main (void)
+{
+ ThreadData *l_data, *r_data;
+
+ const TestIOStreamCallbacks callbacks = {
+ read_thread_cb,
+ write_thread_cb,
+ NULL,
+ NULL,
+ };
+
+#ifdef G_OS_WIN32
+ WSADATA w;
+ WSAStartup (0x0202, &w);
+#endif
+
+ l_data = g_malloc0 (sizeof (ThreadData));
+ r_data = g_malloc0 (sizeof (ThreadData));
+
+ l_data->recv_count = 0;
+ l_data->send_count = 0;
+ l_data->other_recv_count = &r_data->recv_count;
+ l_data->other_send_count = &r_data->send_count;
+
+ r_data->recv_count = 0;
+ r_data->send_count = 0;
+ r_data->other_recv_count = &l_data->recv_count;
+ r_data->other_send_count = &l_data->send_count;
+
+ run_io_stream_test (30, TRUE, &callbacks, l_data, NULL, r_data, NULL);
+
+ g_free (r_data);
+ g_free (l_data);
+
+#ifdef G_OS_WIN32
+ WSACleanup ();
+#endif
+ return 0;
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2013 Collabora Ltd.
+ * Contact: Philip Withnall
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Philip Withnall, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "agent.h"
+#include "test-io-stream-common.h"
+
+#include <stdlib.h>
+#include <string.h>
+#ifndef G_OS_WIN32
+#include <unistd.h>
+#endif
+
+typedef struct {
+ guint cand_count;
+ guint *other_cand_count;
+
+ gsize recv_count;
+ gsize *other_recv_count;
+
+ gsize send_count;
+ gsize *other_send_count;
+} ThreadData;
+
+static void
+read_thread_cb (GInputStream *input_stream, TestIOStreamThreadData *data)
+{
+ ThreadData *user_data = data->user_data;
+
+ for (user_data->recv_count = 0;
+ user_data->recv_count < 10;
+ user_data->recv_count++) {
+ guint8 expected_data[MESSAGE_SIZE];
+ GError *error = NULL;
+ guint8 buf[MESSAGE_SIZE];
+ gssize len;
+
+ /* Block on receiving some data. */
+ len = g_input_stream_read (input_stream, buf, sizeof (buf), NULL, &error);
+ g_assert_no_error (error);
+ g_assert_cmpint (len, ==, sizeof (buf));
+
+ memset (expected_data, user_data->recv_count + '1', sizeof (expected_data));
+ g_assert (memcmp (buf, expected_data, sizeof (expected_data)) == 0);
+ }
+
+ check_for_termination (data, &user_data->recv_count,
+ user_data->other_recv_count, &user_data->send_count, 10);
+}
+
+static void
+new_selected_pair_cb (NiceAgent *agent, guint stream_id, guint component_id,
+ gchar *lfoundation, gchar *rfoundation, TestIOStreamThreadData *data)
+{
+ ThreadData *user_data = data->user_data;
+
+ g_atomic_int_inc (&user_data->cand_count);
+}
+
+static void
+write_thread_cb (GOutputStream *output_stream, TestIOStreamThreadData *data)
+{
+ ThreadData *user_data = data->user_data;
+ guint8 buf[MESSAGE_SIZE];
+
+ for (user_data->send_count = 0;
+ user_data->send_count < 10;
+ user_data->send_count++) {
+ GError *error = NULL;
+
+ memset (buf, user_data->send_count + '1', MESSAGE_SIZE);
+
+ g_output_stream_write (output_stream, buf, sizeof (buf), NULL, &error);
+ g_assert_no_error (error);
+ }
+}
+
+int main (void)
+{
+ ThreadData *l_data, *r_data;
+
+ const TestIOStreamCallbacks callbacks = {
+ read_thread_cb,
+ write_thread_cb,
+ NULL,
+ new_selected_pair_cb,
+ };
+
+#ifdef G_OS_WIN32
+ WSADATA w;
+ WSAStartup (0x0202, &w);
+#endif
+
+ l_data = g_malloc0 (sizeof (ThreadData));
+ r_data = g_malloc0 (sizeof (ThreadData));
+
+ l_data->cand_count = 0;
+ l_data->other_cand_count = &r_data->cand_count;
+ l_data->recv_count = 0;
+ l_data->other_recv_count = &r_data->recv_count;
+ l_data->send_count = 0;
+ l_data->other_send_count = &r_data->send_count;
+
+ r_data->cand_count = 0;
+ r_data->other_cand_count = &l_data->cand_count;
+ r_data->recv_count = 0;
+ r_data->other_recv_count = &l_data->recv_count;
+ r_data->send_count = 0;
+ r_data->other_send_count = &l_data->send_count;
+
+ run_io_stream_test (30, TRUE, &callbacks, l_data, NULL, r_data, NULL);
+
+ /* Verify that correct number of local candidates were reported. */
+ g_assert (l_data->cand_count == 1);
+ g_assert (r_data->cand_count == 1);
+
+ g_free (r_data);
+ g_free (l_data);
+
+#ifdef G_OS_WIN32
+ WSACleanup ();
+#endif
+ return 0;
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * Unit test for ICE in trickle mode (adding remote candidates while gathering
+ * local candidates).
+ *
+ * (C) 2012 Collabora Ltd.
+ * Contact: Rohan Garg
+ * Youness Alaoui
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation.
+ *
+ * Contributors:
+ * Rohan Garg
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#include <glib.h>
+#include <glib-object.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+
+#include "stunagent.h"
+#include "agent-priv.h"
+#include "agent.h"
+
+#define USE_UPNP 0
+#define LEFT_AGENT GINT_TO_POINTER(1)
+#define RIGHT_AGENT GINT_TO_POINTER(2)
+
+static GMutex stun_mutex;
+static GMutex *stun_mutex_ptr = &stun_mutex;
+static GCond stun_signal;
+static GCond *stun_signal_ptr = &stun_signal;
+static GMutex stun_thread_mutex;
+static GMutex *stun_thread_mutex_ptr = &stun_thread_mutex;
+static GCond stun_thread_signal;
+static GCond *stun_thread_signal_ptr = &stun_thread_signal;
+
+static NiceComponentState global_lagent_state = NICE_COMPONENT_STATE_LAST;
+static NiceComponentState global_ragent_state = NICE_COMPONENT_STATE_LAST;
+static GCancellable *global_cancellable;
+static gboolean exit_stun_thread = FALSE;
+static gboolean lagent_candidate_gathering_done = FALSE;
+static gboolean ragent_candidate_gathering_done = FALSE;
+static guint global_ls_id, global_rs_id;
+static gboolean data_received = FALSE;
+static gboolean drop_stun_packets = FALSE;
+static gboolean got_stun_packet = FALSE;
+static gboolean send_stun = FALSE;
+static guint stun_port;
+
+static const uint16_t known_attributes[] = {
+ 0
+};
+
+/* Waits about 10 seconds for @var to be NULL/FALSE */
+#define WAIT_UNTIL_UNSET(var, context) \
+ if (var) \
+ { \
+ int _i; \
+ \
+ for (_i = 0; _i < 13 && (var); _i++) \
+ { \
+ g_usleep (1000 * (1 << _i)); \
+ g_main_context_iteration (context, FALSE); \
+ } \
+ \
+ g_assert (!(var)); \
+ }
+
+/*
+ * Creates a listening socket
+ */
+static int listen_socket (unsigned int *port)
+{
+ union {
+ struct sockaddr_in in;
+ struct sockaddr addr;
+ } addr;
+ int fd = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+
+ if (fd == -1) {
+ perror ("Error opening IP port");
+ return -1;
+ }
+
+ memset (&addr, 0, sizeof (addr));
+ addr.in.sin_family = AF_INET;
+ inet_pton(AF_INET, "127.0.0.1", &addr.in.sin_addr);
+ addr.in.sin_port = 0;
+
+ if (bind (fd, &addr.addr, sizeof (struct sockaddr_in))) {
+ perror ("Error opening IP port");
+ goto error;
+ }
+
+ if (port) {
+ socklen_t socklen = sizeof(addr);
+
+ if (getsockname (fd, &addr.addr, &socklen) < 0)
+ g_error ("getsockname failed: %s", strerror (errno));
+
+ g_assert (socklen == sizeof(struct sockaddr_in));
+ *port = ntohs (addr.in.sin_port);
+ g_assert (*port != 0);
+ }
+
+ return fd;
+
+error:
+ close (fd);
+ return -1;
+}
+
+static int dgram_process (int sock, StunAgent *oldagent, StunAgent *newagent)
+{
+ union {
+ struct sockaddr_storage storage;
+ struct sockaddr addr;
+ } addr;
+ socklen_t addr_len;
+ uint8_t buf[STUN_MAX_MESSAGE_SIZE];
+ size_t buf_len = 0;
+ size_t len = 0;
+ StunMessage request;
+ StunMessage response;
+ StunValidationStatus validation;
+ StunAgent *agent = NULL;
+ gint ret;
+
+ addr_len = sizeof (struct sockaddr_in);
+
+recv_packet:
+ len = recvfrom (sock, buf, sizeof(buf), 0,
+ &addr.addr, &addr_len);
+
+ if (drop_stun_packets) {
+ g_debug ("Dropping STUN packet as requested");
+ return -1;
+ }
+
+ if (len == (size_t)-1) {
+ return -1;
+ }
+
+ validation = stun_agent_validate (newagent, &request, buf, len, NULL, 0);
+
+ if (validation == STUN_VALIDATION_SUCCESS) {
+ agent = newagent;
+ } else {
+ validation = stun_agent_validate (oldagent, &request, buf, len, NULL, 0);
+ agent = oldagent;
+ }
+
+ /* Unknown attributes */
+ if (validation == STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE) {
+ buf_len = stun_agent_build_unknown_attributes_error (agent, &response, buf,
+ sizeof (buf), &request);
+ goto send_buf;
+ }
+
+ /* Mal-formatted packets */
+ if (validation != STUN_VALIDATION_SUCCESS ||
+ stun_message_get_class (&request) != STUN_REQUEST) {
+ goto recv_packet;
+ }
+
+ switch (stun_message_get_method (&request)) {
+ case STUN_BINDING:
+ stun_agent_init_response (agent, &response, buf, sizeof (buf), &request);
+ if (stun_message_has_cookie (&request))
+ stun_message_append_xor_addr (&response,
+ STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
+ &addr.storage, addr_len);
+ else
+ stun_message_append_addr (&response, STUN_ATTRIBUTE_MAPPED_ADDRESS,
+ &addr.addr, addr_len);
+ break;
+
+ case STUN_SHARED_SECRET:
+ case STUN_ALLOCATE:
+ case STUN_SET_ACTIVE_DST:
+ case STUN_CONNECT:
+ case STUN_OLD_SET_ACTIVE_DST:
+ case STUN_IND_DATA:
+ case STUN_IND_CONNECT_STATUS:
+ case STUN_CHANNELBIND:
+ default:
+ if (!stun_agent_init_error (agent, &response, buf, sizeof (buf),
+ &request, STUN_ERROR_BAD_REQUEST)) {
+ g_debug ("STUN error message not initialized properly");
+ g_assert_not_reached();
+ }
+ }
+
+ buf_len = stun_agent_finish_message (agent, &response, NULL, 0);
+
+send_buf:
+ g_cancellable_cancel (global_cancellable);
+ g_debug ("Ready to send a STUN response");
+ g_assert (g_mutex_trylock (stun_mutex_ptr));
+ got_stun_packet = TRUE;
+ while (send_stun) {
+ g_debug ("Waiting for signal. State is %d", global_lagent_state);
+ g_cond_wait (stun_signal_ptr, stun_mutex_ptr);
+ }
+ g_mutex_unlock (stun_mutex_ptr);
+ len = sendto (sock, buf, buf_len, 0,
+ &addr.addr, addr_len);
+ g_debug ("STUN response sent");
+ drop_stun_packets = TRUE;
+ ret = (len < buf_len) ? -1 : 0;
+ return ret;
+}
+
+
+static gpointer stun_thread_func (const gpointer user_data)
+{
+ StunAgent oldagent;
+ StunAgent newagent;
+ int sock = GPOINTER_TO_INT (user_data);
+ int exit_code = -1;
+
+ g_mutex_lock (stun_thread_mutex_ptr);
+ g_cond_signal (stun_thread_signal_ptr);
+ g_mutex_unlock (stun_thread_mutex_ptr);
+
+ stun_agent_init (&oldagent, known_attributes,
+ STUN_COMPATIBILITY_RFC3489, 0);
+ stun_agent_init (&newagent, known_attributes,
+ STUN_COMPATIBILITY_RFC5389, STUN_AGENT_USAGE_USE_FINGERPRINT);
+
+ while (!exit_stun_thread) {
+ g_debug ("Ready to process next datagram");
+ dgram_process (sock, &oldagent, &newagent);
+ }
+
+ exit_code = close (sock);
+ g_thread_exit (GINT_TO_POINTER (exit_code));
+ return NULL;
+}
+
+static void swap_credentials (NiceAgent *lagent, guint lstream,
+ NiceAgent *ragent, guint rstream)
+{
+ gchar *ufrag = NULL, *password = NULL;
+
+ nice_agent_get_local_credentials (lagent, lstream, &ufrag, &password);
+ nice_agent_set_remote_credentials (ragent, rstream, ufrag, password);
+
+ g_free (ufrag);
+ g_free (password);
+}
+
+static void cb_candidate_gathering_done(NiceAgent *agent, guint stream_id, gpointer data)
+{
+ g_debug ("test-tricklemode:%s: %p", G_STRFUNC, data);
+
+ if (GPOINTER_TO_UINT(data) == 1) {
+ g_debug ("lagent finished gathering candidates");
+ lagent_candidate_gathering_done = TRUE;
+ } else if (GPOINTER_TO_UINT(data) == 2) {
+ g_debug ("ragent finished gathering candidates");
+ ragent_candidate_gathering_done = TRUE;
+ }
+ g_cancellable_cancel (global_cancellable);
+}
+
+static void cb_nice_recv (NiceAgent *agent, guint stream_id, guint component_id, guint len, gchar *buf, gpointer user_data)
+{
+ gint ret;
+
+ g_debug ("test-tricklemode:%s: %p", G_STRFUNC, user_data);
+
+ ret = strncmp ("0000", buf, 4);
+ if (ret == 0) {
+ ret = strncmp ("00001234567812345678", buf, 16);
+ g_assert (ret == 0);
+
+ g_debug ("test-tricklemode:%s: ragent recieved %d bytes : quit mainloop",
+ G_STRFUNC, len);
+ data_received = TRUE;
+ g_cancellable_cancel (global_cancellable);
+ }
+}
+
+static void cb_component_state_changed (NiceAgent *agent, guint stream_id, guint component_id, guint state, gpointer data)
+{
+ gint ret;
+
+ g_debug ("test-tricklemode:%s: %p", G_STRFUNC, data);
+
+ if(GPOINTER_TO_UINT(data) == 1) {
+ global_lagent_state = state;
+ g_debug ("lagent state is %d", state);
+ } else if (GPOINTER_TO_UINT(data) == 2) {
+ g_debug ("ragent state is %d", state);
+ global_ragent_state = state;
+ }
+
+ if (GPOINTER_TO_UINT(data) == 1 && state == NICE_COMPONENT_STATE_FAILED) {
+ g_debug ("Signalling STUN response since connchecks failed");
+ g_mutex_lock (stun_mutex_ptr);
+ send_stun = TRUE;
+ g_cond_signal (stun_signal_ptr);
+ g_mutex_unlock (stun_mutex_ptr);
+ g_cancellable_cancel (global_cancellable);
+ }
+
+ if(GPOINTER_TO_UINT(data) == 1 && state == NICE_COMPONENT_STATE_READY) {
+ /* note: test payload send and receive */
+ ret = nice_agent_send (agent, stream_id, component_id,
+ 20, "00001234567812345678");
+ g_debug ("Sent %d bytes", ret);
+ g_assert (ret == 20);
+ }
+}
+
+static void swap_candidates(NiceAgent *local, guint local_id, NiceAgent *remote, guint remote_id, gboolean signal_stun_reply)
+{
+ GSList *cands = NULL;
+
+ g_debug ("test-tricklemode:%s", G_STRFUNC);
+ cands = nice_agent_get_local_candidates(local, local_id,
+ NICE_COMPONENT_TYPE_RTP);
+ g_assert(nice_agent_set_remote_candidates(remote, remote_id,
+ NICE_COMPONENT_TYPE_RTP, cands));
+
+ if (signal_stun_reply) {
+ g_mutex_lock (stun_mutex_ptr);
+ send_stun = TRUE;
+ g_cond_signal (stun_signal_ptr);
+ g_mutex_unlock (stun_mutex_ptr);
+ }
+
+ g_slist_free_full (cands, (GDestroyNotify) nice_candidate_free);
+}
+
+static void cb_agent_new_candidate(NiceAgent *agent, guint stream_id, guint component_id, gchar *foundation, gpointer user_data)
+{
+ NiceAgent *other = g_object_get_data (G_OBJECT (agent), "other-agent");
+ GSList *cands = nice_agent_get_local_candidates (agent, stream_id,
+ component_id);
+ GSList *i = NULL;
+ GSList *remote_cands = NULL;
+ NiceCandidate* temp;
+ gpointer tmp;
+ guint id;
+
+ g_debug ("test-tricklemode:%s: %p", G_STRFUNC, user_data);
+
+ tmp = g_object_get_data (G_OBJECT (other), "id");
+ id = GPOINTER_TO_UINT (tmp);
+
+ for (i = cands; i; i = i->next) {
+ temp = (NiceCandidate*) i->data;
+ if (g_strcmp0(temp->foundation, foundation) == 0) {
+ g_debug ("Adding new local candidate to other agent's connchecks");
+ remote_cands = g_slist_prepend (remote_cands, nice_candidate_copy(temp));
+ g_assert (nice_agent_set_remote_candidates (other, id,
+ NICE_COMPONENT_TYPE_RTP,
+ remote_cands));
+ }
+ }
+
+ g_slist_free_full (remote_cands, (GDestroyNotify) nice_candidate_free);
+ g_slist_free_full (cands, (GDestroyNotify) nice_candidate_free);
+
+}
+
+static void add_bad_candidate (NiceAgent *agent, guint stream_id, NiceCandidate *cand)
+{
+ NiceAddress bad_addr;
+ GSList *cand_list = NULL;
+
+ g_assert (nice_address_set_from_string (&bad_addr, "172.1.0.1"));
+
+ cand = nice_candidate_new (NICE_CANDIDATE_TYPE_HOST);
+ cand->stream_id = stream_id;
+ cand->component_id = NICE_COMPONENT_TYPE_RTP;
+ cand->addr = bad_addr;
+
+ nice_agent_get_local_credentials (agent, stream_id,
+ &cand->username, &cand->password);
+ cand_list = g_slist_prepend (cand_list, cand);
+
+ g_debug ("Adding buggy candidate to the agent %p", agent);
+ g_assert (nice_agent_set_remote_candidates (agent, stream_id,
+ NICE_COMPONENT_TYPE_RTP,
+ cand_list));
+
+ g_slist_free_full (cand_list, (GDestroyNotify) nice_candidate_free);
+
+}
+
+static void init_test(NiceAgent *lagent, NiceAgent *ragent, gboolean connect_new_candidate_signal)
+{
+ global_lagent_state = NICE_COMPONENT_STATE_DISCONNECTED;
+ global_ragent_state = NICE_COMPONENT_STATE_DISCONNECTED;
+
+ lagent_candidate_gathering_done = FALSE;
+ ragent_candidate_gathering_done = FALSE;
+
+ global_ls_id = nice_agent_add_stream (lagent, 1);
+ global_rs_id = nice_agent_add_stream (ragent, 1);
+
+ g_assert (global_ls_id > 0);
+ g_assert (global_rs_id > 0);
+
+ g_debug ("lagent stream is : %d and ragent stream is %d",
+ global_ls_id,
+ global_rs_id);
+
+ g_object_set_data (G_OBJECT (lagent), "id", GUINT_TO_POINTER (global_ls_id));
+ g_object_set_data (G_OBJECT (ragent), "id", GUINT_TO_POINTER (global_rs_id));
+
+ if (connect_new_candidate_signal) {
+ g_signal_connect (G_OBJECT(lagent), "new-candidate",
+ G_CALLBACK(cb_agent_new_candidate), LEFT_AGENT);
+ g_signal_connect (G_OBJECT(ragent), "new-candidate",
+ G_CALLBACK(cb_agent_new_candidate), RIGHT_AGENT);
+ } else {
+ g_signal_handlers_disconnect_by_func (G_OBJECT(lagent), cb_agent_new_candidate,
+ LEFT_AGENT);
+ g_signal_handlers_disconnect_by_func (G_OBJECT(ragent), cb_agent_new_candidate,
+ RIGHT_AGENT);
+ }
+
+ data_received = FALSE;
+ got_stun_packet = FALSE;
+ send_stun = FALSE;
+
+ nice_agent_attach_recv (lagent, global_ls_id, NICE_COMPONENT_TYPE_RTP,
+ g_main_context_default (),
+ cb_nice_recv, LEFT_AGENT);
+ nice_agent_attach_recv (ragent, global_rs_id, NICE_COMPONENT_TYPE_RTP,
+ g_main_context_default (),
+ cb_nice_recv, RIGHT_AGENT);
+}
+
+static void cleanup(NiceAgent *lagent, NiceAgent *ragent)
+{
+ g_debug ("Cleaning up");
+ drop_stun_packets = FALSE;
+ nice_agent_remove_stream (lagent, global_ls_id);
+ nice_agent_remove_stream (ragent, global_rs_id);
+}
+
+static void standard_test(NiceAgent *lagent, NiceAgent *ragent)
+{
+ g_debug ("test-tricklemode:%s", G_STRFUNC);
+
+ got_stun_packet = FALSE;
+ init_test (lagent, ragent, FALSE);
+
+ nice_agent_gather_candidates (lagent, global_ls_id);
+ while (!got_stun_packet)
+ g_main_context_iteration (NULL, TRUE);
+ g_assert (global_lagent_state == NICE_COMPONENT_STATE_GATHERING &&
+ !lagent_candidate_gathering_done);
+
+ nice_agent_gather_candidates (ragent, global_rs_id);
+ while (!ragent_candidate_gathering_done)
+ g_main_context_iteration (NULL, TRUE);
+ g_cancellable_reset (global_cancellable);
+ g_assert (ragent_candidate_gathering_done);
+ g_assert (nice_agent_peer_candidate_gathering_done (lagent, global_ls_id));
+
+
+ g_debug ("Setting local candidates of ragent as remote candidates of lagent");
+ swap_candidates (ragent, global_rs_id, lagent, global_ls_id, TRUE);
+ swap_credentials (ragent, global_rs_id, lagent, global_ls_id);
+
+ while (!data_received)
+ g_main_context_iteration (NULL, TRUE);
+ g_cancellable_reset (global_cancellable);
+ g_assert (global_lagent_state >= NICE_COMPONENT_STATE_CONNECTED &&
+ data_received);
+
+ g_debug ("Setting local candidates of lagent as remote candidates of ragent");
+ swap_candidates (lagent, global_ls_id, ragent, global_rs_id, FALSE);
+ swap_credentials (lagent, global_ls_id, ragent, global_rs_id);
+
+ while (!lagent_candidate_gathering_done)
+ g_main_context_iteration (NULL, TRUE);
+ g_cancellable_reset (global_cancellable);
+
+ g_assert (lagent_candidate_gathering_done);
+ g_assert (nice_agent_peer_candidate_gathering_done (ragent, global_rs_id));
+
+ while (global_ragent_state < NICE_COMPONENT_STATE_CONNECTED)
+ g_main_context_iteration (NULL, TRUE);
+ g_cancellable_reset (global_cancellable);
+
+ g_assert (global_lagent_state == NICE_COMPONENT_STATE_READY);
+ g_assert (global_ragent_state >= NICE_COMPONENT_STATE_CONNECTED);
+
+ cleanup (lagent, ragent);
+}
+
+static void bad_credentials_test(NiceAgent *lagent, NiceAgent *ragent)
+{
+ g_debug ("test-tricklemode:%s", G_STRFUNC);
+
+ init_test (lagent, ragent, FALSE);
+
+ nice_agent_set_remote_credentials (lagent, global_ls_id,
+ "wrong", "wrong");
+ nice_agent_set_remote_credentials (ragent, global_rs_id,
+ "wrong2", "wrong2");
+
+ nice_agent_gather_candidates (lagent, global_ls_id);
+ while (!got_stun_packet)
+ g_main_context_iteration (NULL, TRUE);
+ g_cancellable_reset (global_cancellable);
+ g_assert (global_lagent_state == NICE_COMPONENT_STATE_GATHERING &&
+ !lagent_candidate_gathering_done);
+
+ nice_agent_gather_candidates (ragent, global_rs_id);
+ while (!ragent_candidate_gathering_done)
+ g_main_context_iteration (NULL, TRUE);
+ g_cancellable_reset (global_cancellable);
+ g_assert (ragent_candidate_gathering_done);
+ g_assert (nice_agent_peer_candidate_gathering_done (lagent, global_ls_id));
+
+ g_debug ("Setting local candidates of ragent as remote candidates of lagent");
+ swap_candidates (ragent, global_rs_id, lagent, global_ls_id, FALSE);
+
+ while (global_lagent_state != NICE_COMPONENT_STATE_FAILED)
+ g_main_context_iteration (NULL, TRUE);
+ g_cancellable_reset (global_cancellable);
+
+ // Set the correct credentials and swap candidates
+ g_debug ("Setting local candidates of ragent as remote candidates of lagent");
+ swap_candidates (ragent, global_rs_id, lagent, global_ls_id, FALSE);
+ swap_credentials (lagent, global_ls_id, ragent, global_rs_id);
+
+ g_debug ("Setting local candidates of lagent as remote candidates of ragent");
+ swap_candidates (lagent, global_ls_id, ragent, global_rs_id, FALSE);
+ swap_credentials (ragent, global_rs_id, lagent, global_ls_id);
+
+ while (!data_received)
+ g_main_context_iteration (NULL, TRUE);
+ g_cancellable_reset (global_cancellable);
+
+ g_assert (data_received);
+ g_assert (global_lagent_state == NICE_COMPONENT_STATE_READY);
+ g_assert (global_ragent_state >= NICE_COMPONENT_STATE_CONNECTED);
+
+ // Wait for lagent to finish gathering candidates
+ while (!lagent_candidate_gathering_done)
+ g_main_context_iteration (NULL, TRUE);
+ g_cancellable_reset (global_cancellable);
+
+ g_assert (lagent_candidate_gathering_done);
+ g_assert (nice_agent_peer_candidate_gathering_done (ragent, global_rs_id));
+
+ cleanup (lagent, ragent);
+}
+
+static void bad_candidate_test(NiceAgent *lagent,NiceAgent *ragent)
+{
+ NiceCandidate *cand = NULL;
+
+ g_debug ("test-tricklemode:%s", G_STRFUNC);
+
+ init_test (lagent, ragent, FALSE);
+
+ nice_agent_gather_candidates (lagent, global_ls_id);
+ while (!got_stun_packet)
+ g_main_context_iteration (NULL, TRUE);
+ g_cancellable_reset (global_cancellable);
+ g_assert (global_lagent_state == NICE_COMPONENT_STATE_GATHERING &&
+ !lagent_candidate_gathering_done);
+
+ nice_agent_gather_candidates (ragent, global_rs_id);
+ while (!ragent_candidate_gathering_done)
+ g_main_context_iteration (NULL, TRUE);
+ g_cancellable_reset (global_cancellable);
+
+ g_assert (ragent_candidate_gathering_done);
+ g_assert (nice_agent_peer_candidate_gathering_done (lagent, global_ls_id));
+
+ add_bad_candidate (lagent, global_ls_id, cand);
+
+ // lagent will finish candidate gathering causing this mainloop to quit
+ while (!lagent_candidate_gathering_done)
+ g_main_context_iteration (NULL, TRUE);
+ g_cancellable_reset (global_cancellable);
+
+ g_assert (nice_agent_peer_candidate_gathering_done (ragent, global_rs_id));
+
+ // connchecks will fail causing this mainloop to quit
+ while (global_lagent_state != NICE_COMPONENT_STATE_FAILED)
+ g_main_context_iteration (NULL, TRUE);
+ g_cancellable_reset (global_cancellable);
+
+ g_assert (global_lagent_state == NICE_COMPONENT_STATE_FAILED &&
+ !data_received);
+
+ g_debug ("Setting local candidates of ragent as remote candidates of lagent");
+ swap_candidates (ragent, global_rs_id, lagent, global_ls_id, FALSE);
+ swap_credentials (ragent, global_rs_id, lagent, global_ls_id);
+
+ g_debug ("Setting local candidates of lagent as remote candidates of ragent");
+ swap_candidates (lagent, global_ls_id, ragent, global_rs_id, FALSE);
+ swap_credentials (lagent, global_ls_id, ragent, global_rs_id);
+
+ while (!data_received)
+ g_main_context_iteration (NULL, TRUE);
+ g_cancellable_reset (global_cancellable);
+
+ g_assert (lagent_candidate_gathering_done);
+
+ g_assert (global_lagent_state >= NICE_COMPONENT_STATE_CONNECTED);
+ g_assert (global_ragent_state >= NICE_COMPONENT_STATE_CONNECTED);
+
+ cleanup (lagent, ragent);
+}
+
+static void new_candidate_test(NiceAgent *lagent, NiceAgent *ragent)
+{
+ g_debug ("test-tricklemode:%s", G_STRFUNC);
+
+ init_test (lagent, ragent, TRUE);
+ swap_credentials (lagent, global_ls_id, ragent, global_rs_id);
+ swap_credentials (ragent, global_rs_id, lagent, global_ls_id);
+
+ nice_agent_gather_candidates (lagent, global_ls_id);
+ while (!got_stun_packet)
+ g_main_context_iteration (NULL, TRUE);
+ g_cancellable_reset (global_cancellable);
+ g_assert (global_lagent_state == NICE_COMPONENT_STATE_GATHERING &&
+ !lagent_candidate_gathering_done);
+
+ nice_agent_gather_candidates (ragent, global_rs_id);
+ while (!ragent_candidate_gathering_done)
+ g_main_context_iteration (NULL, TRUE);
+ g_cancellable_reset (global_cancellable);
+ g_assert (nice_agent_peer_candidate_gathering_done (lagent, global_ls_id));
+
+ // Wait for data
+ while (!data_received)
+ g_main_context_iteration (NULL, TRUE);
+ g_cancellable_reset (global_cancellable);
+ g_assert (data_received);
+
+ // Data arrived, signal STUN thread to send STUN response
+ g_mutex_lock (stun_mutex_ptr);
+ send_stun = TRUE;
+ g_cond_signal (stun_signal_ptr);
+ g_mutex_unlock (stun_mutex_ptr);
+
+ // Wait for lagent to finish gathering candidates
+ while (!lagent_candidate_gathering_done)
+ g_main_context_iteration (NULL, TRUE);
+ g_cancellable_reset (global_cancellable);
+ g_assert (nice_agent_peer_candidate_gathering_done (ragent, global_rs_id));
+
+ g_assert (lagent_candidate_gathering_done);
+ g_assert (ragent_candidate_gathering_done);
+
+ g_assert (global_lagent_state == NICE_COMPONENT_STATE_READY);
+ g_assert (global_ragent_state >= NICE_COMPONENT_STATE_CONNECTED);
+
+ cleanup (lagent, ragent);
+}
+
+static void send_dummy_data(void)
+{
+ int sockfd = listen_socket (NULL);
+ union {
+ struct sockaddr_in in;
+ struct sockaddr addr;
+ } addr;
+
+ memset (&addr, 0, sizeof (addr));
+ addr.in.sin_family = AF_INET;
+ inet_pton(AF_INET, "127.0.0.1", &addr.in.sin_addr);
+ addr.in.sin_port = htons (stun_port);
+
+ g_debug ("Sending dummy data to close STUN thread");
+ sendto (sockfd, "close socket", 12, 0,
+ &addr.addr, sizeof (addr));
+}
+
+int main(void)
+{
+ NiceAgent *lagent = NULL, *ragent = NULL;
+ GThread *stun_thread = NULL;
+ NiceAddress baseaddr;
+ GSource *src;
+ int sock;
+
+ global_cancellable = g_cancellable_new ();
+ src = g_cancellable_source_new (global_cancellable);
+ g_source_set_dummy_callback (src);
+ g_source_attach (src, NULL);
+
+ sock = listen_socket (&stun_port);
+
+ if (sock == -1) {
+ g_assert_not_reached ();
+ }
+
+
+ stun_thread = g_thread_new ("listen for STUN requests",
+ stun_thread_func, GINT_TO_POINTER (sock));
+
+ // Once the the thread is forked, we want to listen for a signal
+ // that the socket was opened successfully
+ g_mutex_lock (stun_thread_mutex_ptr);
+ g_cond_wait (stun_thread_signal_ptr, stun_thread_mutex_ptr);
+
+ lagent = nice_agent_new (NULL, NICE_COMPATIBILITY_RFC5245);
+ ragent = nice_agent_new (NULL, NICE_COMPATIBILITY_RFC5245);
+
+ g_object_set (G_OBJECT (lagent), "ice-tcp", FALSE, NULL);
+ g_object_set (G_OBJECT (ragent), "ice-tcp", FALSE, NULL);
+
+ g_object_set (G_OBJECT (lagent), "ice-trickle", TRUE, NULL);
+ g_object_set (G_OBJECT (ragent), "ice-trickle", TRUE, NULL);
+
+ g_object_set (G_OBJECT (lagent), "controlling-mode", TRUE, NULL);
+ g_object_set (G_OBJECT (ragent), "controlling-mode", FALSE, NULL);
+
+ g_object_set (G_OBJECT (lagent), "upnp", USE_UPNP, NULL);
+ g_object_set (G_OBJECT (ragent), "upnp", USE_UPNP, NULL);
+
+ g_object_set (G_OBJECT (lagent), "stun-server", "127.0.0.1", NULL);
+ g_object_set (G_OBJECT (lagent), "stun-server-port", stun_port, NULL);
+
+ g_object_set_data (G_OBJECT (lagent), "other-agent", ragent);
+ g_object_set_data (G_OBJECT (ragent), "other-agent", lagent);
+
+ g_assert (nice_address_set_from_string (&baseaddr, "127.0.0.1"));
+ nice_agent_add_local_address (lagent, &baseaddr);
+ nice_agent_add_local_address (ragent, &baseaddr);
+
+ g_signal_connect(G_OBJECT(lagent), "candidate-gathering-done",
+ G_CALLBACK(cb_candidate_gathering_done), LEFT_AGENT);
+ g_signal_connect(G_OBJECT(ragent), "candidate-gathering-done",
+ G_CALLBACK(cb_candidate_gathering_done), RIGHT_AGENT);
+ g_signal_connect(G_OBJECT(lagent), "component-state-changed",
+ G_CALLBACK(cb_component_state_changed), LEFT_AGENT);
+ g_signal_connect(G_OBJECT(ragent), "component-state-changed",
+ G_CALLBACK(cb_component_state_changed), RIGHT_AGENT);
+
+ standard_test (lagent, ragent);
+ bad_credentials_test (lagent, ragent);
+ bad_candidate_test (lagent, ragent);
+ new_candidate_test (lagent, ragent);
+
+ // Do this to make sure the STUN thread exits
+ exit_stun_thread = TRUE;
+ drop_stun_packets = TRUE;
+ send_stun = FALSE;
+ send_dummy_data ();
+ g_cond_signal (stun_signal_ptr);
+
+ g_object_add_weak_pointer (G_OBJECT (lagent), (gpointer *) &lagent);
+ g_object_add_weak_pointer (G_OBJECT (ragent), (gpointer *) &ragent);
+
+ g_object_unref (lagent);
+ g_object_unref (ragent);
+
+ g_thread_join (stun_thread);
+ g_object_unref (global_cancellable);
+
+ g_source_destroy (src);
+ g_source_unref (src);
+
+ WAIT_UNTIL_UNSET (lagent, NULL);
+ WAIT_UNTIL_UNSET (ragent, NULL);
+
+ return 0;
+}
--- /dev/null
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <gio/gio.h>
+#include <gio/gnetworking.h>
+#include <agent.h>
+
+static NiceComponentState global_lagent_state[2] = { NICE_COMPONENT_STATE_LAST, NICE_COMPONENT_STATE_LAST };
+static NiceComponentState global_ragent_state[2] = { NICE_COMPONENT_STATE_LAST, NICE_COMPONENT_STATE_LAST };
+static guint global_components_ready = 0;
+static gboolean global_lagent_gathering_done = FALSE;
+static gboolean global_ragent_gathering_done = FALSE;
+static int global_lagent_cands = 0;
+static int global_ragent_cands = 0;
+
+static gboolean timer_cb (gpointer pointer)
+{
+ g_debug ("test-nomination:%s: %p", G_STRFUNC, pointer);
+
+ /* signal status via a global variable */
+
+ /* note: should not be reached, abort */
+ g_error ("ERROR: test has got stuck, aborting...");
+
+ return FALSE;
+}
+
+static void cb_nice_recv (NiceAgent *agent, guint stream_id, guint component_id, guint len, gchar *buf, gpointer user_data)
+{
+ g_debug ("test-nomination:%s: %p", G_STRFUNC, user_data);
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent; (void)stream_id; (void)component_id; (void)buf;
+
+ /*
+ * Lets ignore stun packets that got through
+ */
+ if (len < 8)
+ return;
+ if (strncmp ("12345678", buf, 8))
+ return;
+
+ if (component_id != 1)
+ return;
+}
+
+static void cb_candidate_gathering_done(NiceAgent *agent, guint stream_id, gpointer data)
+{
+ g_debug ("test-nomination:%s: %p", G_STRFUNC, data);
+
+ if (GPOINTER_TO_UINT (data) == 1)
+ global_lagent_gathering_done = TRUE;
+ else if (GPOINTER_TO_UINT (data) == 2)
+ global_ragent_gathering_done = TRUE;
+}
+
+
+static void cb_component_state_changed (NiceAgent *agent, guint stream_id, guint component_id, guint state, gpointer data)
+{
+ gboolean ready_to_connected = FALSE;
+ g_debug ("test-nomination:%s: %p", G_STRFUNC, data);
+
+ if (GPOINTER_TO_UINT (data) == 1) {
+ if (global_lagent_state[component_id - 1] == NICE_COMPONENT_STATE_READY &&
+ state == NICE_COMPONENT_STATE_CONNECTED)
+ ready_to_connected = TRUE;
+ global_lagent_state[component_id - 1] = state;
+ } else if (GPOINTER_TO_UINT (data) == 2) {
+ if (global_ragent_state[component_id - 1] == NICE_COMPONENT_STATE_READY &&
+ state == NICE_COMPONENT_STATE_CONNECTED)
+ ready_to_connected = TRUE;
+ global_ragent_state[component_id - 1] = state;
+ }
+
+ if (state == NICE_COMPONENT_STATE_READY)
+ global_components_ready++;
+ else if (state == NICE_COMPONENT_STATE_CONNECTED && ready_to_connected)
+ global_components_ready--;
+ g_assert (state != NICE_COMPONENT_STATE_FAILED);
+
+ g_debug ("test-nomination: checks READY %u.", global_components_ready);
+}
+
+static void cb_new_selected_pair(NiceAgent *agent, guint stream_id,
+ guint component_id, gchar *lfoundation, gchar* rfoundation, gpointer data)
+{
+ g_debug ("test-nomination:%s: %p", G_STRFUNC, data);
+
+ if (GPOINTER_TO_UINT (data) == 1)
+ ++global_lagent_cands;
+ else if (GPOINTER_TO_UINT (data) == 2)
+ ++global_ragent_cands;
+}
+
+static void set_candidates (NiceAgent *from, guint from_stream,
+ NiceAgent *to, guint to_stream, guint component)
+{
+ GSList *cands = NULL, *i;
+
+ cands = nice_agent_get_local_candidates (from, from_stream, component);
+ nice_agent_set_remote_candidates (to, to_stream, component, cands);
+
+ for (i = cands; i; i = i->next)
+ nice_candidate_free ((NiceCandidate *) i->data);
+ g_slist_free (cands);
+}
+
+static void set_credentials (NiceAgent *lagent, guint lstream,
+ NiceAgent *ragent, guint rstream)
+{
+ gchar *ufrag = NULL, *password = NULL;
+
+ nice_agent_get_local_credentials(lagent, lstream, &ufrag, &password);
+ nice_agent_set_remote_credentials (ragent, rstream, ufrag, password);
+ g_free (ufrag);
+ g_free (password);
+ nice_agent_get_local_credentials(ragent, rstream, &ufrag, &password);
+ nice_agent_set_remote_credentials (lagent, lstream, ufrag, password);
+ g_free (ufrag);
+ g_free (password);
+}
+
+static void
+run_test(NiceNominationMode l_nomination_mode,
+ NiceNominationMode r_nomination_mode)
+{
+ NiceAgent *lagent, *ragent; /* agent's L and R */
+ const gchar *localhost;
+ NiceAddress localaddr;
+ guint ls_id, rs_id;
+ gulong timer_id;
+
+ localhost = "127.0.0.1";
+
+ /* step: initialize variables modified by the callbacks */
+ global_components_ready = 0;
+ global_lagent_gathering_done = FALSE;
+ global_ragent_gathering_done = FALSE;
+ global_lagent_cands = global_ragent_cands = 0;
+
+ lagent = nice_agent_new_full (NULL,
+ NICE_COMPATIBILITY_RFC5245,
+ l_nomination_mode == NICE_NOMINATION_MODE_REGULAR ?
+ NICE_AGENT_OPTION_REGULAR_NOMINATION : 0);
+
+ ragent = nice_agent_new_full (NULL,
+ NICE_COMPATIBILITY_RFC5245,
+ r_nomination_mode == NICE_NOMINATION_MODE_REGULAR ?
+ NICE_AGENT_OPTION_REGULAR_NOMINATION : 0);
+
+ g_object_set (G_OBJECT (lagent), "ice-tcp", FALSE, NULL);
+ g_object_set (G_OBJECT (ragent), "ice-tcp", FALSE, NULL);
+
+ g_object_set (G_OBJECT (lagent), "upnp", FALSE, NULL);
+ g_object_set (G_OBJECT (ragent), "upnp", FALSE, NULL);
+ nice_agent_set_software (lagent, "Test-nomination, Left Agent");
+ nice_agent_set_software (ragent, "Test-nomination, Right Agent");
+
+ timer_id = g_timeout_add (30000, timer_cb, NULL);
+
+ if (!nice_address_set_from_string (&localaddr, localhost))
+ g_assert_not_reached ();
+ nice_agent_add_local_address (lagent, &localaddr);
+ nice_agent_add_local_address (ragent, &localaddr);
+
+ g_signal_connect (G_OBJECT (lagent), "candidate-gathering-done",
+ G_CALLBACK (cb_candidate_gathering_done), GUINT_TO_POINTER(1));
+ g_signal_connect (G_OBJECT (ragent), "candidate-gathering-done",
+ G_CALLBACK (cb_candidate_gathering_done), GUINT_TO_POINTER (2));
+ g_signal_connect (G_OBJECT (lagent), "component-state-changed",
+ G_CALLBACK (cb_component_state_changed), GUINT_TO_POINTER (1));
+ g_signal_connect (G_OBJECT (ragent), "component-state-changed",
+ G_CALLBACK (cb_component_state_changed), GUINT_TO_POINTER (2));
+ g_signal_connect (G_OBJECT (lagent), "new-selected-pair",
+ G_CALLBACK (cb_new_selected_pair), GUINT_TO_POINTER(1));
+ g_signal_connect (G_OBJECT (ragent), "new-selected-pair",
+ G_CALLBACK (cb_new_selected_pair), GUINT_TO_POINTER (2));
+
+ g_object_set (G_OBJECT (lagent), "controlling-mode", TRUE, NULL);
+ g_object_set (G_OBJECT (ragent), "controlling-mode", FALSE, NULL);
+
+ ls_id = nice_agent_add_stream (lagent, 1);
+ rs_id = nice_agent_add_stream (ragent, 1);
+ g_assert (ls_id > 0);
+ g_assert (rs_id > 0);
+
+ /* Gather candidates and test nice_agent_set_port_range */
+ g_assert (nice_agent_gather_candidates (lagent, ls_id) == TRUE);
+ g_assert (nice_agent_gather_candidates (ragent, rs_id) == TRUE);
+
+ nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTP,
+ g_main_context_default (), cb_nice_recv, GUINT_TO_POINTER (1));
+ nice_agent_attach_recv (ragent, rs_id, NICE_COMPONENT_TYPE_RTP,
+ g_main_context_default (), cb_nice_recv, GUINT_TO_POINTER (2));
+
+ g_debug ("test-nomination: Added streams, running context until 'candidate-gathering-done'...");
+ while (!global_lagent_gathering_done)
+ g_main_context_iteration (NULL, TRUE);
+ g_assert (global_lagent_gathering_done == TRUE);
+ while (!global_ragent_gathering_done)
+ g_main_context_iteration (NULL, TRUE);
+ g_assert (global_ragent_gathering_done == TRUE);
+
+ set_credentials (lagent, ls_id, ragent, rs_id);
+
+ set_candidates (ragent, rs_id, lagent, ls_id, NICE_COMPONENT_TYPE_RTP);
+ set_candidates (lagent, ls_id, ragent, rs_id, NICE_COMPONENT_TYPE_RTP);
+
+ while (global_lagent_state[0] != NICE_COMPONENT_STATE_READY ||
+ global_ragent_state[0] != NICE_COMPONENT_STATE_READY)
+ g_main_context_iteration (NULL, TRUE);
+ g_assert (global_lagent_state[0] == NICE_COMPONENT_STATE_READY);
+ g_assert (global_ragent_state[0] == NICE_COMPONENT_STATE_READY);
+
+ nice_agent_remove_stream (lagent, ls_id);
+ nice_agent_remove_stream (ragent, rs_id);
+
+ g_source_remove (timer_id);
+
+ g_clear_object(&lagent);
+ g_clear_object(&ragent);
+}
+
+static void
+regular (void)
+{
+ run_test(NICE_NOMINATION_MODE_REGULAR, NICE_NOMINATION_MODE_REGULAR);
+}
+
+static void
+aggressive (void)
+{
+ run_test(NICE_NOMINATION_MODE_AGGRESSIVE, NICE_NOMINATION_MODE_AGGRESSIVE);
+}
+
+static void
+mixed_ra (void)
+{
+ run_test(NICE_NOMINATION_MODE_REGULAR, NICE_NOMINATION_MODE_AGGRESSIVE);
+}
+
+static void
+mixed_ar (void)
+{
+ run_test(NICE_NOMINATION_MODE_AGGRESSIVE, NICE_NOMINATION_MODE_REGULAR);
+}
+
+int
+main (int argc, char **argv)
+{
+ int ret;
+
+ g_networking_init ();
+
+ g_test_init (&argc, &argv, NULL);
+
+ g_test_add_func ("/nice/nomination/regular", regular);
+ g_test_add_func ("/nice/nomination/aggressive", aggressive);
+ g_test_add_func ("/nice/nomination/mixed_ra", mixed_ra);
+ g_test_add_func ("/nice/nomination/mixed_ar", mixed_ar);
+
+ ret = g_test_run ();
+
+ return ret;
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2006, 2007 Collabora Ltd.
+ * Contact: Dafydd Harries
+ * (C) 2006, 2007 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Dafydd Harries, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "agent.h"
+#include "agent-priv.h"
+
+
+int
+main (void)
+{
+ NiceCandidate *candidate;
+
+ candidate = nice_candidate_new (NICE_CANDIDATE_TYPE_HOST);
+ nice_address_set_from_string (&candidate->addr, "127.0.0.1");
+ nice_address_set_from_string (&candidate->base_addr, "127.0.0.1");
+
+ /* test 1 */
+ g_assert_cmpuint (nice_candidate_jingle_priority (candidate), ==, 1000);
+ /* Host UDP */
+ candidate->transport = NICE_CANDIDATE_TRANSPORT_UDP;
+ candidate->component_id = 1;
+ g_assert_cmpuint (nice_candidate_ice_priority (candidate, FALSE, FALSE), ==, 0x780001FF);
+ /* Host UDP reliable */
+ g_assert_cmpuint (nice_candidate_ice_priority (candidate, TRUE, FALSE), ==, 0x3C0001FF);
+ /* Host tcp-active unreliable */
+ candidate->transport = NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE;
+ g_assert_cmpuint (nice_candidate_ice_priority (candidate, FALSE, FALSE) & 0xFFE000FF, ==, 0x3C8000FF);
+ /* Host tcp-active reliable */
+ candidate->transport = NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE;
+ /* Host tcp-active reliable */
+ g_assert_cmpuint (nice_candidate_ice_priority (candidate, TRUE, FALSE) & 0xFFE000FF, ==, 0x788000FF);
+ /* srv-reflexive tcp-active reliable */
+ candidate->type = NICE_CANDIDATE_TYPE_SERVER_REFLEXIVE;
+ candidate->transport = NICE_CANDIDATE_TRANSPORT_TCP_ACTIVE;
+ g_assert_cmpuint (nice_candidate_ice_priority (candidate, TRUE, FALSE) & 0xFFE000FF, ==, 0x648000FF);
+ /* nat-assisted srv-reflexive tcp-active reliable */
+ g_assert_cmpuint (nice_candidate_ice_priority (candidate, TRUE, TRUE) & 0xFFE000FF, ==, 0x698000FF);
+ nice_candidate_free (candidate);
+
+ /* test 2 */
+ /* 2^32*MIN(O,A) + 2*MAX(O,A) + (O>A?1:0)
+ = 2^32*1 + 2*5000 + 0
+ = 4294977296 */
+ g_assert_cmpuint (nice_candidate_pair_priority (1,5000), ==, 4294977296LL);
+
+ /* 2^32*1 + 2*5000 + 1 = 4294977297 */
+ g_assert_cmpuint (nice_candidate_pair_priority (5000, 1), ==, 4294977297LL);
+
+ return 0;
+}
+
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * © 2014, 2015 Collabora Ltd.
+ * Contact: Philip Withnall
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Philip Withnall, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <locale.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <arpa/inet.h>
+
+#include "pseudotcp.h"
+
+
+typedef struct {
+ PseudoTcpSocket *left; /* owned */
+ PseudoTcpSocket *right; /* owned */
+
+ guint32 left_current_time;
+ guint32 right_current_time;
+
+ /* Data sent and received by each socket. */
+ GQueue/*<owned GBytes>*/ *left_sent; /* owned */
+ GQueue/*<owned GBytes>*/ *right_sent; /* owned */
+} Data;
+
+/* NOTE: Must match the on-the-wire flag values from pseudotcp.c. */
+typedef enum {
+ FLAG_NONE = 0,
+ FLAG_FIN = 1 << 0,
+ FLAG_SYN = 1 << 1,
+ FLAG_RST = 1 << 2,
+} SegmentFlags;
+
+typedef void (*TestFunc) (Data *data, const void *next_funcs);
+
+
+static void
+data_clear (Data *data)
+{
+ if (data->left != NULL)
+ g_object_unref (data->left);
+ if (data->right != NULL)
+ g_object_unref (data->right);
+
+ if (data->left_sent != NULL)
+ g_queue_free_full (data->left_sent, (GDestroyNotify) g_bytes_unref);
+ if (data->right_sent != NULL)
+ g_queue_free_full (data->right_sent, (GDestroyNotify) g_bytes_unref);
+}
+
+
+static gchar *
+segment_flags_to_string (SegmentFlags flags)
+{
+ GString *str = g_string_new (NULL);
+
+ if (flags & FLAG_SYN)
+ g_string_append (str, "SYN,");
+ if (flags & FLAG_FIN)
+ g_string_append (str, "FIN,");
+ if (flags & FLAG_RST)
+ g_string_append (str, "RST,");
+
+ /* Strip the trailing comma. */
+ if (str->len > 0)
+ g_string_truncate (str, str->len - 1);
+
+ if (str->len == 0)
+ g_string_append (str, "0");
+
+ return g_string_free (str, FALSE);
+}
+
+static gchar *
+segment_to_string (guint32 seq, guint32 ack, SegmentFlags flags)
+{
+ gchar *ctl, *out;
+
+ ctl = segment_flags_to_string (flags);
+ out = g_strdup_printf ("<SEQ=%u><ACK=%u><CTL=%s>", seq, ack, ctl);
+ g_free (ctl);
+
+ return out;
+}
+
+static gchar *
+segment_bytes_to_string (const guint8 *bytes)
+{
+ union {
+ const guint8 *u8;
+ const guint32 *u32;
+ } b;
+ guint32 seq, ack;
+ guint8 flags;
+
+ b.u8 = bytes;
+
+ seq = ntohl (b.u32[1]);
+ ack = ntohl (b.u32[2]);
+ flags = b.u8[13];
+
+ return segment_to_string (seq, ack, flags);
+}
+
+
+static void
+opened (PseudoTcpSocket *sock, gpointer data)
+{
+ g_debug ("Socket %p opened", sock);
+}
+
+static void
+readable (PseudoTcpSocket *sock, gpointer data)
+{
+ g_debug ("Socket %p readable", sock);
+}
+
+static void
+writable (PseudoTcpSocket *sock, gpointer data)
+{
+ g_debug ("Socket %p writeable", sock);
+}
+
+static void
+closed (PseudoTcpSocket *sock, guint32 err, gpointer data)
+{
+ g_debug ("Socket %p closed: %s", sock, strerror (err));
+}
+
+static PseudoTcpWriteResult
+write_packet (PseudoTcpSocket *sock, const gchar *buffer, guint32 len,
+ gpointer user_data)
+{
+ Data *data = user_data;
+ gchar *str; /* owned */
+ GQueue/*<owned GBytes>*/ *queue; /* unowned */
+ GBytes *segment; /* owned */
+
+ /* Debug output. */
+ str = segment_bytes_to_string ((const guint8 *) buffer);
+ g_debug ("%p sent: %s", sock, str);
+ g_free (str);
+
+ /* One of the sockets has outputted a packet. */
+ if (sock == data->left)
+ queue = data->left_sent;
+ else if (sock == data->right)
+ queue = data->right_sent;
+ else
+ g_assert_not_reached ();
+
+ segment = g_bytes_new (buffer, len);
+ g_queue_push_tail (queue, segment);
+
+ return WR_SUCCESS;
+}
+
+
+static void
+create_sockets (Data *data, gboolean support_fin_ack)
+{
+ PseudoTcpCallbacks cbs = {
+ data, opened, readable, writable, closed, write_packet
+ };
+
+ data->left = g_object_new (PSEUDO_TCP_SOCKET_TYPE,
+ "conversation", 0,
+ "callbacks", &cbs,
+ "support-fin-ack", support_fin_ack,
+ NULL);
+ data->right = g_object_new (PSEUDO_TCP_SOCKET_TYPE,
+ "conversation", 0,
+ "callbacks", &cbs,
+ "support-fin-ack", support_fin_ack,
+ NULL);
+
+ g_debug ("Left: %p, right: %p", data->left, data->right);
+
+ /* Control the socket clocks precisely. */
+ pseudo_tcp_socket_set_time (data->left, 1);
+ pseudo_tcp_socket_set_time (data->right, 1);
+
+ /* Sanity check the socket state. */
+ g_assert_cmpint (pseudo_tcp_socket_send (data->left, "foo", 3), ==, -1);
+ g_assert_cmpint (pseudo_tcp_socket_get_error (data->left), ==, ENOTCONN);
+
+ g_assert_cmpint (pseudo_tcp_socket_send (data->right, "foo", 3), ==, -1);
+ g_assert_cmpint (pseudo_tcp_socket_get_error (data->right), ==, ENOTCONN);
+
+ data->left_sent = g_queue_new ();
+ data->right_sent = g_queue_new ();
+}
+
+static void
+expect_segment (PseudoTcpSocket *socket, GQueue/*<owned GBytes>*/ *queue,
+ guint32 seq, guint32 ack, guint32 len, SegmentFlags flags)
+{
+ GBytes *bytes; /* unowned */
+ union {
+ const guint8 *u8;
+ const guint32 *u32;
+ } b;
+ gsize size;
+ gchar *str;
+
+ str = segment_to_string (seq, ack, flags);
+ g_debug ("%p expect: %s", socket, str);
+ g_free (str);
+
+ /* Grab the segment. */
+ bytes = g_queue_peek_head (queue);
+ g_assert (bytes != NULL);
+
+ b.u8 = g_bytes_get_data (bytes, &size);
+ g_assert_cmpuint (size, >=, 24); /* minimum packet size */
+ g_assert_cmpuint (size - 24, ==, len);
+
+ /* Check the segment’s fields. */
+ g_assert_cmpuint (ntohl (b.u32[1]), ==, seq);
+ g_assert_cmpuint (ntohl (b.u32[2]), ==, ack);
+ g_assert_cmpuint (b.u8[13], ==, flags);
+}
+
+static void
+expect_syn_sent (Data *data)
+{
+ expect_segment (data->left, data->left_sent, 0, 0, 7, FLAG_SYN);
+}
+
+static void
+expect_syn_received (Data *data)
+{
+ expect_segment (data->right, data->right_sent, 0, 7, 7, FLAG_SYN);
+}
+
+static void
+assert_empty_queues (Data *data)
+{
+ g_assert_cmpuint (g_queue_get_length (data->left_sent), ==, 0);
+ g_assert_cmpuint (g_queue_get_length (data->right_sent), ==, 0);
+}
+
+/* Return whether the socket accepted the packet. */
+static gboolean
+forward_segment (GQueue/*<owned GBytes>*/ *from, PseudoTcpSocket *to)
+{
+ GBytes *segment; /* owned */
+ const guint8 *b;
+ gsize size;
+ gboolean retval;
+
+ segment = g_queue_pop_head (from);
+ g_assert (segment != NULL);
+ b = g_bytes_get_data (segment, &size);
+ retval = pseudo_tcp_socket_notify_packet (to, (const gchar *) b, size);
+ g_bytes_unref (segment);
+
+ return retval;
+}
+
+static void
+forward_segment_ltr (Data *data)
+{
+ g_assert (forward_segment (data->left_sent, data->right));
+}
+
+static void
+forward_segment_rtl (Data *data)
+{
+ g_assert (forward_segment (data->right_sent, data->left));
+}
+
+static void
+duplicate_segment (GQueue/*<owned GBytes>*/ *queue)
+{
+ GBytes *segment; /* unowned */
+
+ segment = g_queue_peek_head (queue);
+ g_assert (segment != NULL);
+ g_queue_push_head (queue, g_bytes_ref (segment));
+}
+
+static void
+drop_segment (PseudoTcpSocket *socket, GQueue/*<owned GBytes>*/ *queue)
+{
+ GBytes *segment; /* owned */
+ gchar *str;
+
+ segment = g_queue_pop_head (queue);
+ g_assert (segment != NULL);
+
+ str = segment_bytes_to_string (g_bytes_get_data (segment, NULL));
+ g_debug ("%p drop: %s", socket, str);
+ g_free (str);
+
+ g_bytes_unref (segment);
+}
+
+/* Swap the order of the head-most two segments in the @queue. */
+static void
+reorder_segments (PseudoTcpSocket *socket, GQueue/*<owned GBytes>*/ *queue)
+{
+ GBytes *segment1, *segment2; /* unowned */
+ gchar *str;
+
+ segment1 = g_queue_pop_head (queue);
+ g_assert (segment1 != NULL);
+ segment2 = g_queue_pop_head (queue);
+ g_assert (segment2 != NULL);
+
+ str = segment_bytes_to_string (g_bytes_get_data (segment1, NULL));
+ g_debug ("%p reorder: %s", socket, str);
+ g_free (str);
+ str = segment_bytes_to_string (g_bytes_get_data (segment2, NULL));
+ g_debug ("%p after: %s", socket, str);
+ g_free (str);
+
+ g_queue_push_head (queue, segment1);
+ g_queue_push_head (queue, segment2);
+}
+
+static void
+expect_socket_state (PseudoTcpSocket *socket, PseudoTcpState expected_state)
+{
+ PseudoTcpState state;
+
+ g_object_get (socket, "state", &state, NULL);
+ g_assert_cmpuint (state, ==, expected_state);
+}
+
+static void
+expect_sockets_connected (Data *data)
+{
+ expect_socket_state (data->left, PSEUDO_TCP_ESTABLISHED);
+ expect_socket_state (data->right, PSEUDO_TCP_ESTABLISHED);
+}
+
+static void
+expect_sockets_closed (Data *data)
+{
+ guint8 buf[100];
+
+ expect_socket_state (data->left, PSEUDO_TCP_CLOSED);
+ expect_socket_state (data->right, PSEUDO_TCP_CLOSED);
+
+ g_assert_cmpint (pseudo_tcp_socket_send (data->left, "foo", 3), ==, -1);
+ g_assert_cmpint (pseudo_tcp_socket_get_error (data->left), ==, EPIPE);
+ g_assert_cmpint (pseudo_tcp_socket_recv (data->left, (char *) buf, sizeof (buf)), ==, 0);
+
+ g_assert_cmpint (pseudo_tcp_socket_send (data->right, "foo", 3), ==, -1);
+ g_assert_cmpint (pseudo_tcp_socket_get_error (data->right), ==, EPIPE);
+ g_assert_cmpint (pseudo_tcp_socket_recv (data->right, (char *) buf, sizeof (buf)), ==, 0);
+}
+
+static void
+increment_time (PseudoTcpSocket *socket, guint32 *counter, guint32 increment)
+{
+ g_debug ("Incrementing %p time by %u from %u to %u", socket, increment,
+ *counter, *counter + increment);
+ *counter = *counter + increment;
+
+ pseudo_tcp_socket_set_time (socket, *counter);
+ pseudo_tcp_socket_notify_clock (socket);
+}
+
+static void
+increment_time_both (Data *data, guint32 increment)
+{
+ increment_time (data->left, &data->left_current_time, increment);
+ increment_time (data->right, &data->right_current_time, increment);
+}
+
+static void
+expect_fin (PseudoTcpSocket *socket, GQueue/*<owned GBytes>*/ *queue,
+ guint32 seq, guint32 ack)
+{
+ expect_segment (socket, queue, seq, ack, 0, FLAG_FIN);
+}
+
+static void
+expect_rst (PseudoTcpSocket *socket, GQueue/*<owned GBytes>*/ *queue,
+ guint32 seq, guint32 ack)
+{
+ expect_segment (socket, queue, seq, ack, 0, FLAG_RST);
+}
+
+static void
+expect_ack (PseudoTcpSocket *socket, GQueue/*<owned GBytes>*/ *queue,
+ guint32 seq, guint32 ack)
+{
+ expect_segment (socket, queue, seq, ack, 0, FLAG_NONE);
+}
+
+static void
+expect_data (PseudoTcpSocket *socket, GQueue/*<owned GBytes>*/ *queue,
+ guint32 seq, guint32 ack, guint32 len)
+{
+ expect_segment (socket, queue, seq, ack, len, FLAG_NONE);
+}
+
+static void
+close_socket (PseudoTcpSocket *socket)
+{
+ guint8 buf[100];
+
+ pseudo_tcp_socket_close (socket, FALSE);
+
+ g_assert_cmpint (pseudo_tcp_socket_send (socket, "foo", 3), ==, -1);
+ g_assert_cmpint (pseudo_tcp_socket_get_error (socket), ==, EPIPE);
+ g_assert_cmpint (pseudo_tcp_socket_recv (socket, (char *) buf, sizeof (buf)), ==, 0);
+}
+
+/* Helper to create a socket pair and perform the SYN handshake. */
+static void
+establish_connection (Data *data)
+{
+ create_sockets (data, TRUE);
+ pseudo_tcp_socket_connect (data->left);
+ expect_syn_sent (data);
+ forward_segment_ltr (data);
+ expect_syn_received (data);
+ forward_segment_rtl (data);
+ increment_time_both (data, 110);
+ expect_ack (data->left, data->left_sent, 7, 7);
+ forward_segment_ltr (data);
+ expect_sockets_connected (data);
+
+ assert_empty_queues (data);
+}
+
+/* Helper to close the LHS of a socket pair which has not transmitted any
+ * data (i.e. perform the first half of the FIN handshake). */
+static void
+close_lhs (Data *data)
+{
+ pseudo_tcp_socket_close (data->left, FALSE);
+
+ expect_fin (data->left, data->left_sent, 7, 7);
+ forward_segment_ltr (data);
+
+ expect_ack (data->right, data->right_sent, 7, 8);
+ forward_segment_rtl (data);
+}
+
+/* Helper to close the RHS of a socket pair which has not transmitted any
+ * data (i.e. perform the second half of the FIN handshake). */
+static void
+close_rhs (Data *data)
+{
+ pseudo_tcp_socket_close (data->right, FALSE);
+
+ expect_fin (data->right, data->right_sent, 7, 8);
+ forward_segment_rtl (data);
+
+ increment_time_both (data, 10); /* TIME-WAIT */
+ expect_ack (data->left, data->left_sent, 8, 8);
+ forward_segment_ltr (data);
+}
+
+/* Check that establishing a connection then immediately closing it works, using
+ * normal handshakes (FIN, ACK, FIN, ACK). See: RFC 793, Figure 13. */
+static void
+pseudotcp_close_normal (void)
+{
+ Data data = { 0, };
+ guint8 buf[100];
+
+ /* Establish a connection. */
+ establish_connection (&data);
+
+ /* Close it. Verify that sending fails. */
+ close_socket (data.left);
+
+ expect_fin (data.left, data.left_sent, 7, 7);
+ forward_segment_ltr (&data);
+ expect_ack (data.right, data.right_sent, 7, 8);
+ forward_segment_rtl (&data);
+
+ /* Check the RHS is closed. */
+ g_assert_cmpint (pseudo_tcp_socket_recv (data.right, (char *) buf, sizeof (buf)), ==, 0);
+ close_socket (data.right);
+
+ expect_fin (data.right, data.right_sent, 7, 8);
+ forward_segment_rtl (&data);
+ increment_time_both (&data, 10); /* TIME-WAIT */
+ expect_ack (data.left, data.left_sent, 8, 8);
+ forward_segment_ltr (&data);
+ expect_sockets_closed (&data);
+
+ data_clear (&data);
+}
+
+/* Check that establishing a connection then immediately closing it works, using
+ * simultaneous handshakes (FIN, FIN, ACK, ACK). See: RFC 793, Figure 14. */
+static void
+pseudotcp_close_simultaneous (void)
+{
+ Data data = { 0, };
+
+ /* Establish a connection. */
+ establish_connection (&data);
+
+ /* Close both sides simultaneously. Verify that sending fails. */
+ close_socket (data.left);
+ close_socket (data.right);
+
+ expect_fin (data.left, data.left_sent, 7, 7);
+ expect_fin (data.right, data.right_sent, 7, 7);
+ forward_segment_ltr (&data);
+ forward_segment_rtl (&data);
+
+ expect_ack (data.left, data.left_sent, 8, 8);
+ expect_ack (data.right, data.right_sent, 8, 8);
+ forward_segment_ltr (&data);
+ forward_segment_rtl (&data);
+
+ increment_time_both (&data, 10); /* TIME-WAIT */
+ expect_sockets_closed (&data);
+
+ data_clear (&data);
+}
+
+/* Check that establishing a connection then immediately closing it works, using
+ * skewed handshakes. The segments are reordered so that the FIN and ACK from
+ * the LHS arrive at the RHS in reverse order. The RHS sees the ACK has a higher
+ * sequence number than the bytes it’s seen so far (as it hasn’t seen the LHS
+ * FIN at that point) and thus emits two sequential ACKs: one from before
+ * receiving the FIN (fast retransmit), and one from after.
+ * See: RFC 793, Figure 14. */
+static void
+pseudotcp_close_skew1 (void)
+{
+ Data data = { 0, };
+
+ /* Establish a connection. */
+ establish_connection (&data);
+
+ /* Close both sides simultaneously. Verify that sending fails. */
+ close_socket (data.left);
+ close_socket (data.right);
+
+ expect_fin (data.left, data.left_sent, 7, 7);
+
+ expect_fin (data.right, data.right_sent, 7, 7);
+ forward_segment_rtl (&data);
+
+ reorder_segments (data.left, data.left_sent);
+ expect_ack (data.left, data.left_sent, 8, 8);
+ forward_segment_ltr (&data);
+ forward_segment_ltr (&data);
+
+ expect_ack (data.right, data.right_sent, 8, 7);
+ forward_segment_rtl (&data);
+ expect_ack (data.right, data.right_sent, 8, 8);
+ forward_segment_rtl (&data);
+
+ increment_time_both (&data, 10); /* TIME-WAIT */
+ expect_sockets_closed (&data);
+
+ data_clear (&data);
+}
+
+/* Same as pseudotcp_close_skew1() but with the packets reordered in a
+ * different way. */
+static void
+pseudotcp_close_skew2 (void)
+{
+ Data data = { 0, };
+
+ /* Establish a connection. */
+ establish_connection (&data);
+
+ /* Close both sides simultaneously. Verify that sending fails. */
+ close_socket (data.left);
+ close_socket (data.right);
+
+ expect_fin (data.right, data.right_sent, 7, 7);
+
+ expect_fin (data.left, data.left_sent, 7, 7);
+ forward_segment_ltr (&data);
+
+ reorder_segments (data.right, data.right_sent);
+ expect_ack (data.right, data.right_sent, 8, 8);
+ forward_segment_rtl (&data);
+ forward_segment_rtl (&data);
+
+ expect_ack (data.left, data.left_sent, 8, 7);
+ forward_segment_ltr (&data);
+ expect_ack (data.left, data.left_sent, 8, 8);
+ forward_segment_ltr (&data);
+
+ increment_time_both (&data, 10); /* TIME-WAIT */
+ expect_sockets_closed (&data);
+
+ data_clear (&data);
+}
+
+/* Check that closing a connection recovers from the initial FIN segment being
+ * dropped. Based on: RFC 793, Figure 13. */
+static void
+pseudotcp_close_normal_recovery1 (void)
+{
+ Data data = { 0, };
+
+ /* Establish a connection. */
+ establish_connection (&data);
+
+ /* Close the LHS and drop the FIN segment. */
+ close_socket (data.left);
+
+ expect_fin (data.left, data.left_sent, 7, 7);
+ drop_segment (data.left, data.left_sent);
+
+ increment_time_both (&data, 1100); /* retransmit timeout */
+
+ expect_fin (data.left, data.left_sent, 7, 7);
+ forward_segment_ltr (&data);
+
+ expect_ack (data.right, data.right_sent, 7, 8);
+ forward_segment_rtl (&data);
+
+ /* Close the RHS. */
+ close_rhs (&data);
+
+ expect_sockets_closed (&data);
+
+ data_clear (&data);
+}
+
+/* Check that closing a connection recovers from the initial ACK segment being
+ * dropped. Based on: RFC 793, Figure 13. */
+static void
+pseudotcp_close_normal_recovery2 (void)
+{
+ Data data = { 0, };
+
+ /* Establish a connection. */
+ establish_connection (&data);
+
+ /* Close the LHS and drop the ACK segment. The LHS should retransmit the
+ * FIN. */
+ close_socket (data.left);
+
+ expect_fin (data.left, data.left_sent, 7, 7);
+ forward_segment_ltr (&data);
+
+ expect_ack (data.right, data.right_sent, 7, 8);
+ drop_segment (data.right, data.right_sent);
+ increment_time_both (&data, 1100); /* retransmit timeout */
+ expect_fin (data.left, data.left_sent, 7, 7);
+ forward_segment_ltr (&data);
+ expect_ack (data.right, data.right_sent, 7, 8);
+ forward_segment_rtl (&data);
+
+ /* Close the RHS. */
+ close_rhs (&data);
+
+ expect_sockets_closed (&data);
+
+ data_clear (&data);
+}
+
+/* Check that closing a connection recovers from the second FIN segment being
+ * dropped. Based on: RFC 793, Figure 13. */
+static void
+pseudotcp_close_normal_recovery3 (void)
+{
+ Data data = { 0, };
+
+ /* Establish a connection. */
+ establish_connection (&data);
+
+ /* Close the LHS. */
+ close_lhs (&data);
+
+ /* Close the RHS and drop the FIN segment. */
+ close_socket (data.right);
+
+ expect_fin (data.right, data.right_sent, 7, 8);
+ drop_segment (data.right, data.right_sent);
+ increment_time_both (&data, 300); /* retransmit timeout */
+ expect_fin (data.right, data.right_sent, 7, 8);
+ forward_segment_rtl (&data);
+
+ increment_time_both (&data, 10); /* TIME-WAIT */
+ expect_ack (data.left, data.left_sent, 8, 8);
+ forward_segment_ltr (&data);
+
+ expect_sockets_closed (&data);
+
+ data_clear (&data);
+}
+
+/* Check that closing a connection recovers from the second ACK segment being
+ * dropped. Based on: RFC 793, Figure 13. */
+static void
+pseudotcp_close_normal_recovery4 (void)
+{
+ Data data = { 0, };
+
+ /* Establish a connection. */
+ establish_connection (&data);
+
+ /* Close the LHS. */
+ close_lhs (&data);
+
+ /* Close the RHS and drop the ACK segment. The RHS should retransmit the
+ * FIN. The timers for the two peers are manipulated separately so the LHS
+ * doesn’t exceed its TIME-WAIT while waiting for the retransmit. */
+ close_socket (data.right);
+
+ expect_fin (data.right, data.right_sent, 7, 8);
+ forward_segment_rtl (&data);
+
+ expect_ack (data.left, data.left_sent, 8, 8);
+ drop_segment (data.left, data.left_sent);
+ increment_time (data.right, &data.right_current_time, 300); /* retransmit timeout */
+ expect_fin (data.right, data.right_sent, 7, 8);
+ forward_segment_rtl (&data);
+ increment_time (data.left, &data.left_current_time, 10); /* TIME-WAIT */
+ expect_ack (data.left, data.left_sent, 8, 8);
+ forward_segment_ltr (&data);
+
+ expect_sockets_closed (&data);
+
+ data_clear (&data);
+}
+
+/* Check that closing a connection recovers from a data segment being dropped
+ * immediately before the first FIN is sent. Based on: RFC 793, Figure 13. */
+static void
+pseudotcp_close_normal_recovery_data (void)
+{
+ Data data = { 0, };
+
+ /* Establish a connection. */
+ establish_connection (&data);
+
+ /* Send some data from LHS to RHS, but drop the segment. */
+ g_assert_cmpint (pseudo_tcp_socket_send (data.left, "foo", 3), ==, 3);
+ expect_data (data.left, data.left_sent, 7, 7, 3);
+ drop_segment (data.left, data.left_sent);
+
+ assert_empty_queues(&data);
+
+ /* Close the LHS. */
+ g_assert_cmpint (pseudo_tcp_socket_get_available_bytes (data.left), ==, 0);
+ g_assert_cmpint (pseudo_tcp_socket_get_available_bytes (data.right), ==, 0);
+ close_socket (data.left);
+
+ expect_socket_state (data.left, PSEUDO_TCP_FIN_WAIT_1);
+ expect_fin (data.left, data.left_sent, 10, 7);
+ forward_segment_ltr (&data);
+
+ expect_socket_state (data.right, PSEUDO_TCP_ESTABLISHED);
+ expect_ack (data.right, data.right_sent, 7, 7);
+ forward_segment_rtl (&data);
+
+ expect_socket_state (data.left, PSEUDO_TCP_FIN_WAIT_1);
+
+ assert_empty_queues(&data);
+
+ /* Close the RHS. */
+ close_socket (data.right);
+
+ expect_socket_state (data.right, PSEUDO_TCP_FIN_WAIT_1);
+
+ expect_fin (data.right, data.right_sent, 7, 7);
+ forward_segment_rtl (&data);
+
+ expect_socket_state (data.left, PSEUDO_TCP_CLOSING);
+
+ expect_ack (data.left, data.left_sent, 11, 8);
+ forward_segment_ltr (&data);
+
+ expect_socket_state (data.right, PSEUDO_TCP_FIN_WAIT_2);
+
+ expect_data (data.right, data.right_sent, 8, 7, 0);
+ forward_segment_rtl (&data);
+ expect_socket_state (data.left, PSEUDO_TCP_CLOSING);
+
+ expect_data (data.left, data.left_sent, 7, 8, 3);
+ forward_segment_ltr (&data);
+ expect_socket_state (data.right, PSEUDO_TCP_TIME_WAIT);
+
+ increment_time_both (&data, 100); /* Delayed ACK */
+
+ expect_ack (data.right, data.right_sent, 8, 11);
+ forward_segment_rtl (&data);
+ expect_socket_state (data.left, PSEUDO_TCP_TIME_WAIT);
+
+ increment_time_both (&data, 10); /* TIME-WAIT */
+
+ expect_sockets_closed (&data);
+
+ data_clear (&data);
+}
+
+/* Check that if both FIN segments from a simultaneous FIN handshake are
+ * dropped, the handshake recovers and completes successfully.
+ * See: RFC 793, Figure 14. */
+static void
+pseudotcp_close_simultaneous_recovery1 (void)
+{
+ Data data = { 0, };
+
+ /* Establish a connection. */
+ establish_connection (&data);
+
+ /* Close both sides simultaneously and drop the FINs. */
+ close_socket (data.left);
+ close_socket (data.right);
+
+ expect_fin (data.left, data.left_sent, 7, 7);
+ expect_fin (data.right, data.right_sent, 7, 7);
+ drop_segment (data.left, data.left_sent);
+ drop_segment (data.right, data.right_sent);
+
+ increment_time_both (&data, 1200); /* retransmit timeout */
+
+ expect_fin (data.left, data.left_sent, 7, 7);
+ expect_fin (data.right, data.right_sent, 7, 7);
+ forward_segment_ltr (&data);
+ forward_segment_rtl (&data);
+
+ expect_ack (data.left, data.left_sent, 8, 8);
+ expect_ack (data.right, data.right_sent, 8, 8);
+ forward_segment_ltr (&data);
+ forward_segment_rtl (&data);
+
+ increment_time_both (&data, 10); /* TIME-WAIT */
+ expect_sockets_closed (&data);
+
+ data_clear (&data);
+}
+
+/* Check that if both ACK segments from a simultaneous FIN handshake are
+ * dropped, the handshake recovers and completes successfully.
+ * See: RFC 793, Figure 14. */
+static void
+pseudotcp_close_simultaneous_recovery2 (void)
+{
+ Data data = { 0, };
+
+ /* Establish a connection. */
+ establish_connection (&data);
+
+ /* Close both sides simultaneously and forward the FINs. */
+ close_socket (data.left);
+ close_socket (data.right);
+
+ expect_fin (data.left, data.left_sent, 7, 7);
+ expect_fin (data.right, data.right_sent, 7, 7);
+ forward_segment_ltr (&data);
+ forward_segment_rtl (&data);
+
+ /* Drop the ACKs. */
+ expect_ack (data.left, data.left_sent, 8, 8);
+ expect_ack (data.right, data.right_sent, 8, 8);
+ drop_segment (data.left, data.left_sent);
+ drop_segment (data.right, data.right_sent);
+
+ increment_time_both (&data, 1200); /* retransmit timeout */
+
+ expect_fin (data.left, data.left_sent, 7, 8);
+ expect_fin (data.right, data.right_sent, 7, 8);
+ forward_segment_ltr (&data);
+ forward_segment_rtl (&data);
+
+ expect_ack (data.left, data.left_sent, 8, 8);
+ expect_ack (data.right, data.right_sent, 8, 8);
+ forward_segment_ltr (&data);
+ forward_segment_rtl (&data);
+
+ increment_time_both (&data, 10); /* TIME-WAIT */
+
+ expect_sockets_closed (&data);
+
+ data_clear (&data);
+}
+
+/* Check that closing a connection ignores a duplicate FIN segment.
+ * Based on: RFC 793, Figure 13. */
+static void
+pseudotcp_close_duplicate_fin (void)
+{
+ Data data = { 0, };
+
+ /* Establish a connection. */
+ establish_connection (&data);
+
+ /* Close the LHS. */
+ close_lhs (&data);
+
+ /* Close the RHS and duplicate the FIN segment. */
+ close_socket (data.right);
+
+ expect_fin (data.right, data.right_sent, 7, 8);
+ duplicate_segment (data.right_sent);
+ forward_segment_rtl (&data);
+ forward_segment_rtl (&data);
+
+ increment_time (data.left, &data.left_current_time, 10); /* TIME-WAIT */
+ expect_ack (data.left, data.left_sent, 8, 8);
+ forward_segment_ltr (&data);
+
+ expect_sockets_closed (&data);
+
+ data_clear (&data);
+}
+
+/* Check that closing a connection ignores a duplicate ACK segment.
+ * Based on: RFC 793, Figure 13. */
+static void
+pseudotcp_close_duplicate_ack (void)
+{
+ Data data = { 0, };
+
+ /* Establish a connection. */
+ establish_connection (&data);
+
+ /* Close the LHS. */
+ close_lhs (&data);
+
+ /* Close the RHS and duplicate the ACK segment. The RHS should reject the
+ * duplicate with a RST segment. The LHS should then reject the RST. */
+ close_socket (data.right);
+
+ expect_fin (data.right, data.right_sent, 7, 8);
+ forward_segment_rtl (&data);
+
+ increment_time (data.left, &data.left_current_time, 10); /* TIME-WAIT */
+ expect_ack (data.left, data.left_sent, 8, 8);
+ duplicate_segment (data.left_sent);
+ forward_segment_ltr (&data);
+ g_assert (!forward_segment (data.left_sent, data.right));
+ expect_rst (data.right, data.right_sent, 8, 8);
+ g_assert (!forward_segment (data.right_sent, data.left));
+
+ expect_sockets_closed (&data);
+
+ data_clear (&data);
+}
+
+/* Check that forcefully closing a connection by sending a RST segment works.
+ * See: RFC 1122, §4.2.2.13. */
+static void
+pseudotcp_close_rst (void)
+{
+ Data data = { 0, };
+ guint8 buf[100];
+
+ /* Establish a connection. */
+ establish_connection (&data);
+
+ /* Close the LHS. */
+ pseudo_tcp_socket_close (data.left, TRUE);
+
+ g_assert_cmpint (pseudo_tcp_socket_send (data.left, "foo", 3), ==, -1);
+ g_assert_cmpint (pseudo_tcp_socket_get_error (data.left), ==, EPIPE);
+ g_assert_cmpint (pseudo_tcp_socket_recv (data.left, (char *) buf, sizeof (buf)), ==, 0);
+
+ expect_rst (data.left, data.left_sent, 7, 7);
+ g_assert (!forward_segment (data.left_sent, data.right));
+
+ /* Check the RHS is closed. */
+ g_assert_cmpint (pseudo_tcp_socket_send (data.right, "foo", 3), ==, -1);
+ g_assert_cmpint (pseudo_tcp_socket_get_error (data.right), ==, EPIPE);
+ g_assert_cmpint (pseudo_tcp_socket_recv (data.right, (char *) buf, sizeof (buf)), ==, 0);
+
+ expect_sockets_closed (&data);
+
+ data_clear (&data);
+}
+
+/* Check that an RST is sent if a connection is closed with pending data in the
+ * local receive buffer. See: RFC 1122, §4.2.2.13. */
+static void
+pseudotcp_close_pending_received (void)
+{
+ Data data = { 0, };
+ guint8 buf[100];
+
+ /* Establish a connection. */
+ establish_connection (&data);
+
+ /* Send some data from RHS to LHS. Do *not* read the data from the LHS receive
+ * buffer. */
+ g_assert_cmpint (pseudo_tcp_socket_send (data.right, "foo", 3), ==, 3);
+ expect_data (data.right, data.right_sent, 7, 7, 3);
+ forward_segment_rtl (&data);
+
+ /* Close the LHS. */
+ g_assert_cmpint (pseudo_tcp_socket_get_available_bytes (data.left), ==, 3);
+ close_socket (data.left);
+
+ expect_rst (data.left, data.left_sent, 7, 10);
+ g_assert (!forward_segment (data.left_sent, data.right));
+
+ /* Check the RHS is closed. */
+ g_assert_cmpint (pseudo_tcp_socket_send (data.right, "foo", 3), ==, -1);
+ g_assert_cmpint (pseudo_tcp_socket_get_error (data.right), ==, EPIPE);
+ g_assert_cmpint (pseudo_tcp_socket_recv (data.right, (char *) buf, sizeof (buf)), ==, 0);
+
+ expect_sockets_closed (&data);
+
+ data_clear (&data);
+}
+
+/* Check that an RST is sent if data is received on a socket after close() has
+ * been called. See: RFC 1122, §4.2.2.13. */
+static void
+pseudotcp_close_rst_afterwards (void)
+{
+ Data data = { 0, };
+ guint8 buf[100];
+
+ /* Establish a connection. */
+ establish_connection (&data);
+
+ /* Close the LHS. */
+ g_assert_cmpint (pseudo_tcp_socket_get_available_bytes (data.left), ==, 0);
+ pseudo_tcp_socket_close (data.left, TRUE);
+ close_socket (data.left);
+
+ expect_rst (data.left, data.left_sent, 7, 7);
+ drop_segment (data.left, data.left_sent); /* just to get it out of the way */
+
+ assert_empty_queues(&data);
+
+ /* Send some data from RHS to LHS, which should result in an RST. */
+ g_assert_cmpint (pseudo_tcp_socket_send (data.right, "foo", 3), ==, 3);
+ expect_data (data.right, data.right_sent, 7, 7, 3);
+ g_assert (!forward_segment (data.right_sent, data.left));
+
+ expect_rst (data.left, data.left_sent, 7, 7);
+ g_assert (!forward_segment (data.left_sent, data.right));
+
+ /* Check the RHS is closed. */
+ g_assert_cmpint (pseudo_tcp_socket_send (data.right, "foo", 3), ==, -1);
+ g_assert_cmpint (pseudo_tcp_socket_get_error (data.right), ==, EPIPE);
+ g_assert_cmpint (pseudo_tcp_socket_recv (data.right, (char *) buf, sizeof (buf)), ==, 0);
+
+ expect_sockets_closed (&data);
+
+ data_clear (&data);
+}
+
+/* Check that two pseudo-TCP sockets interact correctly even if FIN–ACK support
+ * is disabled on one of them. */
+static void
+pseudotcp_compatibility (void)
+{
+ Data data = { 0, };
+ guint8 buf[100];
+ guint64 timeout;
+
+ /* Establish a connection. Note the sequence numbers should start at 4 this
+ * time, rather than the 7 in other tests, because the FIN–ACK option should
+ * not be being sent. */
+ create_sockets (&data, FALSE);
+ pseudo_tcp_socket_connect (data.left);
+ expect_segment (data.left, data.left_sent, 0, 0, 4, FLAG_SYN);
+ forward_segment_ltr (&data);
+ expect_segment (data.right, data.right_sent, 0, 4, 4, FLAG_SYN);
+ forward_segment_rtl (&data);
+ increment_time_both (&data, 110);
+ expect_ack (data.left, data.left_sent, 4, 4);
+ forward_segment_ltr (&data);
+ expect_sockets_connected (&data);
+
+ /* Close it. Sending shouldn’t fail. */
+ pseudo_tcp_socket_close (data.left, FALSE);
+ g_assert (!pseudo_tcp_socket_is_closed (data.left));
+
+ g_assert_cmpint (pseudo_tcp_socket_send (data.left, "foo", 3), ==, 3);
+ g_assert_cmpint (pseudo_tcp_socket_recv (data.left, (char *) buf, sizeof (buf)), ==, -1);
+ g_assert_cmpint (pseudo_tcp_socket_get_error (data.left), ==, EWOULDBLOCK);
+
+ expect_data (data.left, data.left_sent, 4, 4, 3);
+ forward_segment_ltr (&data);
+
+ increment_time_both (&data, 100);
+
+ expect_ack (data.right, data.right_sent, 4, 7);
+ forward_segment_rtl (&data);
+
+ /* Advance the timers; now the LHS should be closed, as the RHS has ACKed all
+ * outstanding data. */
+ increment_time_both (&data, 50);
+
+ g_assert (!pseudo_tcp_socket_get_next_clock (data.left, &timeout));
+
+ /* Check the RHS can be closed after receiving the data just sent. */
+ g_assert_cmpint (pseudo_tcp_socket_recv (data.right, (char *) buf, sizeof (buf)), ==, 3);
+ g_assert_cmpint (pseudo_tcp_socket_recv (data.right, (char *) buf, sizeof (buf)), ==, -1);
+ g_assert_cmpint (pseudo_tcp_socket_get_error (data.right), ==, EWOULDBLOCK);
+
+ pseudo_tcp_socket_close (data.right, FALSE);
+
+ g_assert (!pseudo_tcp_socket_get_next_clock (data.right, &timeout));
+
+ expect_sockets_closed (&data);
+
+ data_clear (&data);
+}
+
+
+/* Check that after receiving a FIN, queued data can still be read */
+static void
+pseudotcp_close_recv_queued (void)
+{
+ Data data = { 0, };
+ guint8 buf[100];
+
+ /* Establish a connection. */
+ establish_connection (&data);
+
+ g_assert_cmpint (pseudo_tcp_socket_get_available_bytes (data.left), ==, 0);
+ g_assert_cmpint (pseudo_tcp_socket_get_available_bytes (data.right), ==, 0);
+ g_assert_cmpint (pseudo_tcp_socket_get_available_send_space (data.right), >,
+ 0);
+ g_assert_cmpint (pseudo_tcp_socket_get_available_send_space (data.left), >,
+ 0);
+
+ g_assert_cmpint (pseudo_tcp_socket_send (data.left, "foo", 3), ==, 3);
+ expect_data (data.left, data.left_sent, 7, 7, 3);
+ forward_segment_ltr (&data);
+
+ increment_time_both (&data, 100); /* Delayed ACK */
+ expect_ack (data.right, data.right_sent, 7, 10);
+ forward_segment_rtl (&data);
+
+ close_socket (data.left);
+ expect_fin (data.left, data.left_sent, 10, 7);
+ forward_segment_ltr (&data);
+
+ expect_socket_state (data.left, PSEUDO_TCP_FIN_WAIT_1);
+ expect_socket_state (data.right, PSEUDO_TCP_CLOSE_WAIT);
+
+ g_assert_cmpint (pseudo_tcp_socket_get_available_bytes (data.left), ==, 0);
+ g_assert_cmpint (pseudo_tcp_socket_get_available_send_space (data.left), ==,
+ 0);
+
+ expect_ack (data.right, data.right_sent, 7, 11);
+ forward_segment_rtl (&data);
+
+ expect_socket_state (data.left, PSEUDO_TCP_FIN_WAIT_2);
+
+
+ g_assert_cmpint (pseudo_tcp_socket_get_available_bytes (data.right), ==, 3);
+
+ g_assert_cmpint (pseudo_tcp_socket_get_available_send_space (data.right), >,
+ 0);
+
+ /* Check that the data can be read */
+ g_assert_cmpint (pseudo_tcp_socket_recv (data.right, (char *) buf, sizeof (buf)), ==, 3);
+
+ /* Now the socket should be empty */
+ g_assert_cmpint (pseudo_tcp_socket_recv (data.right, (char *) buf, sizeof (buf)), ==, 0);
+
+ data_clear (&data);
+}
+
+int
+main (int argc, char *argv[])
+{
+ setlocale (LC_ALL, "");
+ g_test_init (&argc, &argv, NULL);
+ pseudo_tcp_set_debug_level (PSEUDO_TCP_DEBUG_VERBOSE);
+
+ /* There are four possible scenarios for the FIN handshake, if the possibility
+ * of dropped or duplicated segments is ignored (but reordered segments are
+ * allowed: normal, simultaneous, and two types of skew.
+ *
+ * These can be generated by considering the events happening at a single peer
+ * during connection closure: sending the FIN (SF), receiving a FIN and
+ * sending a FIN-ACK (RF), receiving a FIN-ACK (RA). These have the following
+ * permutations:
+ * • SF, RF, RA
+ * • SF, RA, RF
+ * • RF, SF, RA
+ * Other permutations are disallowed because SF must come before RA.
+ *
+ * The permutations of one peer’s (1) behaviour with a second (2) can then be
+ * considered:
+ * • 1: SF, RF, RA; 2: SF, RF, RA (simultaneous)
+ * • 1: SF, RF, RA; 2: SF, RA, RF (skew 1)
+ * • 1: SF, RF, RA; 2: RF, SF, RA (skew 2)
+ * • 1: SF, RA, RF; 2: RF, SF, RA (normal)
+ * Other permutations are disallowed because SF on one peer must come before
+ * RF on the other; similarly RF on one must come before RA on the other.
+ *
+ * Thus, the following unit tests provably cover all possible scenarios where
+ * segments can be reordered but not dropped or duplicated. */
+ g_test_add_func ("/pseudotcp/close/normal",
+ pseudotcp_close_normal);
+ g_test_add_func ("/pseudotcp/close/simultaneous",
+ pseudotcp_close_simultaneous);
+ g_test_add_func ("/pseudotcp/close/skew1",
+ pseudotcp_close_skew1);
+ g_test_add_func ("/pseudotcp/close/skew2",
+ pseudotcp_close_skew2);
+
+ /* An arbitrary (less methodical) selection of unit tests for dropped and
+ * duplicated packets. */
+ g_test_add_func ("/pseudotcp/close/normal/recovery1",
+ pseudotcp_close_normal_recovery1);
+ g_test_add_func ("/pseudotcp/close/normal/recovery2",
+ pseudotcp_close_normal_recovery2);
+ g_test_add_func ("/pseudotcp/close/normal/recovery3",
+ pseudotcp_close_normal_recovery3);
+ g_test_add_func ("/pseudotcp/close/normal/recovery4",
+ pseudotcp_close_normal_recovery4);
+ g_test_add_func ("/pseudotcp/close/normal/recovery-data",
+ pseudotcp_close_normal_recovery_data);
+ g_test_add_func ("/pseudotcp/close/simultaneous/recovery1",
+ pseudotcp_close_simultaneous_recovery1);
+ g_test_add_func ("/pseudotcp/close/simultaneous/recovery2",
+ pseudotcp_close_simultaneous_recovery2);
+ g_test_add_func ("/pseudotcp/close/duplicate-fin",
+ pseudotcp_close_duplicate_fin);
+ g_test_add_func ("/pseudotcp/close/duplicate-ack",
+ pseudotcp_close_duplicate_ack);
+
+ g_test_add_func ("/pseudotcp/close/rst",
+ pseudotcp_close_rst);
+ g_test_add_func ("/pseudotcp/close/pending-received",
+ pseudotcp_close_pending_received);
+ g_test_add_func ("/pseudotcp/close/rst-afterwards",
+ pseudotcp_close_rst_afterwards);
+
+ g_test_add_func ("/pseudotcp/close/recv-queued",
+ pseudotcp_close_recv_queued);
+
+ g_test_add_func ("/pseudotcp/compatibility",
+ pseudotcp_compatibility);
+
+ g_test_run ();
+
+ return 0;
+}
--- /dev/null
+/* vim: et ts=2 sw=2 tw=80: */
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2010, 2014 Collabora Ltd.
+ * Contact: Philip Withnall
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Philip Withnall, Collabora Ltd.
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <locale.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <math.h>
+
+#include "pseudotcp.h"
+
+
+/**
+ * A fuzzing test for the pseudotcp socket. This connects two sockets in a
+ * loopback arrangement, with the packet output from one being fed to the other,
+ * and vice-versa. Fuzzing happens on the packet interface between the two,
+ * mutating the packets slightly and seeing what happens.
+ *
+ * The input data to the left-most socket is read from a file. The output data
+ * from the loopback is written to another file, although this probably isn’t
+ * very useful. If no files are provided, a small amount of dummy data is sent
+ * through the sockets instead. This almost certainly won’t catch any bugs, and
+ * is just present to allow this test to be run as part of `make check` so it
+ * doesn’t bit rot.
+ *
+ * A good command to generate an input file is:
+ * dd if=/dev/urandom of=rand count=10000 ibs=1024
+ *
+ * None of the data is validated, and the test results are effectively the 1-bit
+ * value of ‘did it crash?’. In particular, the output file is not validated,
+ * and the TCP packets emitted by both sockets are not checked for validity.
+ *
+ * It is suggested that this test is run under GDB and Valgrind. Any crashes or
+ * errors which are detected can be reproduced by providing the same input file
+ * and seed (using the --seed option). The seed is printed out at the beginning
+ * of each test run.
+ */
+
+
+PseudoTcpSocket *left;
+PseudoTcpSocket *right;
+GMainLoop *main_loop = NULL;
+GRand *prng = NULL;
+gint retval = 0;
+FILE *in = NULL;
+FILE *out = NULL;
+int total_read = 0;
+int total_wrote = 0;
+guint left_clock = 0;
+guint right_clock = 0;
+gboolean left_closed = FALSE;
+gboolean right_closed = FALSE;
+gboolean reading_done = FALSE;
+
+/* Number of bytes of payload each socket has received so far. */
+guint32 left_stream_pos = 0;
+guint32 right_stream_pos = 0;
+
+/* Configuration options. */
+gint64 seed = 0;
+guint32 fuzz_start_pos = 1; /* bytes into stream payload; after the SYN-ACKs */
+guint n_changes_lambda = 1; /* lambda parameter for a Poisson distribution
+ * controlling the number of mutations made to each
+ * packet */
+
+
+static void
+adjust_clock (PseudoTcpSocket *sock);
+
+
+static void
+write_to_sock (PseudoTcpSocket *sock)
+{
+ gchar buf[1024];
+ gsize len;
+ gint wlen;
+ guint total = 0;
+
+ while (TRUE) {
+ len = fread (buf, 1, sizeof(buf), in);
+ if (len == 0) {
+ g_debug ("Done reading data from file");
+ g_assert (feof (in));
+ reading_done = TRUE;
+ pseudo_tcp_socket_close (sock, FALSE);
+ break;
+ } else {
+ wlen = pseudo_tcp_socket_send (sock, buf, len);
+ g_debug ("Sending %" G_GSIZE_FORMAT " bytes : %d", len, wlen);
+ total += wlen;
+ total_read += wlen;
+ if (wlen < (gint) len) {
+ g_debug ("seeking %" G_GSIZE_FORMAT " from %lu", wlen - len, ftell (in));
+ fseek (in, wlen - len, SEEK_CUR);
+ g_assert (!feof (in));
+ g_debug ("Socket queue full after %d bytes written", total);
+ break;
+ }
+ }
+ }
+ adjust_clock (sock);
+}
+
+static void
+opened (PseudoTcpSocket *sock, gpointer data)
+{
+ g_debug ("Socket %p Opened", sock);
+ if (sock == left) {
+ if (in)
+ write_to_sock (sock);
+ else {
+ pseudo_tcp_socket_send (sock, "abcdefghijklmnopqrstuvwxyz", 26);
+ reading_done = TRUE;
+ pseudo_tcp_socket_close (sock, FALSE);
+ }
+ }
+}
+
+static void
+readable (PseudoTcpSocket *sock, gpointer data)
+{
+ gchar buf[1024];
+ gint len;
+ g_debug ("Socket %p Readable", sock);
+
+ do {
+ len = pseudo_tcp_socket_recv (sock, buf, sizeof(buf));
+
+ if (len > 0) {
+ g_debug ("Read %d bytes", len);
+ if (out) {
+ if (fwrite (buf, len, 1, out) == 0)
+ g_debug ("Error writing to output file");
+ else {
+ total_wrote += len;
+
+ g_assert (total_wrote <= total_read);
+ g_debug ("Written %d bytes, need %d bytes", total_wrote, total_read);
+ if (total_wrote == total_read && feof (in)) {
+ g_assert (reading_done);
+ pseudo_tcp_socket_close (sock, FALSE);
+ }
+ }
+ } else {
+ pseudo_tcp_socket_close (sock, FALSE);
+ }
+ } else if (len == 0) {
+ pseudo_tcp_socket_close (sock, FALSE);
+ }
+ } while (len > 0);
+
+ if (len == -1 &&
+ pseudo_tcp_socket_get_error (sock) != EWOULDBLOCK) {
+ g_printerr ("Error reading from socket %p: %s.\n",
+ sock, g_strerror (pseudo_tcp_socket_get_error (sock)));
+
+ retval = -1;
+ g_main_loop_quit (main_loop);
+ return;
+ }
+}
+
+static void
+writable (PseudoTcpSocket *sock, gpointer data)
+{
+ g_debug ("Socket %p Writable", sock);
+ if (in && sock == left)
+ write_to_sock (sock);
+}
+
+static void
+closed (PseudoTcpSocket *sock, guint32 err, gpointer data)
+{
+ /* Don’t treat this as an error, since we’re throwing rubbish into the
+ * socket and can hardly expect it to complete successfully. */
+ g_debug ("Socket %p Closed: %s", sock, g_strerror (err));
+ retval = 0;
+ g_main_loop_quit (main_loop);
+}
+
+struct notify_data {
+ PseudoTcpSocket *sock;
+ guint32 len;
+ guint32 stream_pos;
+ guint8 buffer[];
+};
+
+/**
+ * random_int_poisson:
+ * @lambda: Lambda parameter for the distribution function, which must be
+ * non-zero
+ *
+ * Generate a random variable from a Poisson distribution with parameter
+ * @lambda. This consumes one %gdouble’s worth of randomness from the global
+ * @prng.
+ *
+ * This is implemented using the inverse transform of the Poisson CDF, and is
+ * guaranteed to return in time linearly proportional to @lambda.
+ *
+ * Returns: Poisson-distributed pseudo-random variable
+ */
+static guint32
+random_int_poisson (guint lambda)
+{
+ gdouble U;
+ guint32 i;
+ gdouble p, F;
+
+ g_return_val_if_fail (lambda > 0, 0);
+
+ /*
+ * Reference: http://www.cs.bgu.ac.il/~mps042/invtransnote.htm,
+ * §Simulating a Poisson random variable.
+ */
+ U = g_rand_double (prng); /* step 1 */
+ i = 0;
+ p = exp (0.0 - (gdouble) lambda);
+ F = p; /* step 2 */
+
+ while (U >= F) { /* step 3 */
+ p = (lambda * p) / (i + 1);
+ F += p;
+ i += 1; /* step 4 and 5 */
+ }
+
+ return i;
+}
+
+static guint32
+fuzz_packet (guint8 *buf, guint32 len, guint32 stream_pos)
+{
+ guint32 i;
+ guint n_changes;
+#define HEADER_LENGTH 24 /* bytes; or thereabouts (include some options) */
+
+ /* Do we want to fuzz this packet? */
+ if (stream_pos < fuzz_start_pos) {
+ return len;
+ }
+
+ /* Get fuzzing. Only bother fuzzing the header; fuzzing the payload is
+ * pointless. Weight the number of changes towards having only a few changes,
+ * since that makes them less likely to be summarily rejected. */
+ n_changes = random_int_poisson (n_changes_lambda);
+ g_debug ("Making %u changes for bytes at stream position %u:",
+ n_changes, stream_pos);
+
+ for (i = 0; i < n_changes; i++) {
+ guint32 pos = g_rand_int_range (prng, 0, MIN (len, HEADER_LENGTH));
+ g_debug (" • Changing byte %u.", stream_pos + pos);
+ buf[pos] = g_rand_int_range (prng, 0, G_MAXUINT8 + 1);
+ }
+
+ return len;
+}
+
+static gboolean
+notify_packet (gpointer user_data)
+{
+ struct notify_data *data = (struct notify_data*) user_data;
+
+ /* Fuzz the packet. */
+ data->len = fuzz_packet (data->buffer, data->len, data->stream_pos);
+
+ pseudo_tcp_socket_notify_packet (data->sock,
+ (gchar *) data->buffer, data->len);
+ adjust_clock (data->sock);
+
+ g_free (data);
+ return FALSE;
+}
+
+static PseudoTcpWriteResult
+write_packet (PseudoTcpSocket *sock, const gchar *buffer, guint32 len,
+ gpointer user_data)
+{
+ struct notify_data *data;
+ PseudoTcpState state;
+ g_object_get (sock, "state", &state, NULL);
+
+ data = g_malloc (sizeof(struct notify_data) + len);
+
+ g_debug ("Socket %p(%d) Writing : %d bytes", sock, state, len);
+
+ memcpy (data->buffer, buffer, len);
+ data->len = len;
+
+ if (sock == left) {
+ data->stream_pos = left_stream_pos;
+ left_stream_pos += len;
+ data->sock = right;
+ } else {
+ data->stream_pos = right_stream_pos;
+ right_stream_pos += len;
+ data->sock = left;
+ }
+
+ g_idle_add (notify_packet, data);
+
+ return WR_SUCCESS;
+}
+
+
+static gboolean notify_clock (gpointer data)
+{
+ PseudoTcpSocket *sock = (PseudoTcpSocket *)data;
+ //g_debug ("Socket %p: Notifying clock", sock);
+ pseudo_tcp_socket_notify_clock (sock);
+ adjust_clock (sock);
+ return FALSE;
+}
+
+static void adjust_clock (PseudoTcpSocket *sock)
+{
+ guint64 timeout = 0;
+
+ if (pseudo_tcp_socket_get_next_clock (sock, &timeout)) {
+ timeout -= g_get_monotonic_time () / 1000;
+ g_debug ("Socket %p: Adjusting clock to %" G_GUINT64_FORMAT " ms", sock, timeout);
+ if (sock == left) {
+ if (left_clock != 0)
+ g_source_remove (left_clock);
+ left_clock = g_timeout_add (timeout, notify_clock, sock);
+ } else {
+ if (right_clock != 0)
+ g_source_remove (right_clock);
+ right_clock = g_timeout_add (timeout, notify_clock, sock);
+ }
+ } else {
+ g_debug ("Socket %p should be destroyed, it's done", sock);
+ if (sock == left)
+ left_closed = TRUE;
+ else
+ right_closed = TRUE;
+ if (left_closed && right_closed)
+ g_main_loop_quit (main_loop);
+ }
+}
+
+static GOptionEntry entries[] = {
+ { "seed", 's', 0, G_OPTION_ARG_INT64, &seed, "PRNG seed", "N" },
+ { "fuzz-start-position", 'p', 0, G_OPTION_ARG_INT, &fuzz_start_pos,
+ "Number of bytes into the stream to start fuzzing after", "B" },
+ { "fuzz-n-changes-lambda", 'l', 0, G_OPTION_ARG_INT, &n_changes_lambda,
+ "Lambda value for the Poisson distribution controlling the number of "
+ "changes made to each packet", "λ" },
+ { NULL }
+};
+
+int main (int argc, char *argv[])
+{
+ PseudoTcpCallbacks cbs = {
+ NULL, opened, readable, writable, closed, write_packet
+ };
+ GOptionContext *context;
+ GError *error = NULL;
+
+ setlocale (LC_ALL, "");
+
+ /* Configuration. */
+ context = g_option_context_new ("— fuzz-test the pseudotcp socket");
+ g_option_context_add_main_entries (context, entries, NULL);
+
+ if (!g_option_context_parse (context, &argc, &argv, &error)) {
+ g_printerr ("Option parsing failed: %s\n", error->message);
+ goto context_error;
+ }
+
+ if (n_changes_lambda == 0) {
+ g_printerr ("Option parsing failed: %s\n",
+ "Lambda values must be positive.");
+ goto context_error;
+ }
+
+ g_option_context_free (context);
+
+ /* Tweak the configuration. */
+ if (seed == 0) {
+ seed = g_get_real_time ();
+ }
+
+ /* Open the input and output files */
+ if (argc >= 3) {
+ in = fopen (argv[1], "r");
+ out = fopen (argv[2], "w");
+ }
+
+ /* Set up the main loop and sockets. */
+ main_loop = g_main_loop_new (NULL, FALSE);
+
+ g_print ("Using seed: %" G_GINT64_FORMAT ", start position: %u, λ: %u\n",
+ seed, fuzz_start_pos, n_changes_lambda);
+ prng = g_rand_new_with_seed (seed);
+
+ pseudo_tcp_set_debug_level (PSEUDO_TCP_DEBUG_VERBOSE);
+
+ left = pseudo_tcp_socket_new (0, &cbs);
+ right = pseudo_tcp_socket_new (0, &cbs);
+ g_debug ("Left: %p. Right: %p", left, right);
+
+ pseudo_tcp_socket_notify_mtu (left, 1496);
+ pseudo_tcp_socket_notify_mtu (right, 1496);
+
+ pseudo_tcp_socket_connect (left);
+ adjust_clock (left);
+ adjust_clock (right);
+
+ /* Run the main loop. */
+ g_main_loop_run (main_loop);
+ g_main_loop_unref (main_loop);
+
+ g_object_unref (left);
+ g_object_unref (right);
+
+ g_rand_free (prng);
+
+ if (in != NULL)
+ fclose (in);
+ if (out != NULL)
+ fclose (out);
+
+ return retval;
+
+context_error:
+ g_printerr ("\n%s\n", g_option_context_get_help (context, TRUE, NULL));
+ g_option_context_free (context);
+
+ return 1;
+}
--- /dev/null
+#!/bin/sh
+
+set -e
+
+if test -n "${BUILT_WITH_MESON}"; then
+ TEST_PSEUDOTCP=$1
+else
+ TEST_PSEUDOTCP=./test-pseudotcp
+fi
+
+cleanup() {
+ rm -rf rand rand-copy
+}
+
+trap cleanup EXIT
+
+dd if=/dev/urandom of=rand count=1024 ibs=1024
+"${TEST_PSEUDOTCP}" rand rand-copy
+diff rand rand-copy
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2010 Collabora Ltd.
+ * Contact: Youness Alaoui
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Youness Alaoui, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <locale.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "pseudotcp.h"
+
+PseudoTcpSocket *left;
+PseudoTcpSocket *right;
+GMainLoop *mainloop = NULL;
+FILE *in = NULL;
+FILE *out = NULL;
+int total_read = 0;
+int total_wrote = 0;
+guint left_clock = 0;
+guint right_clock = 0;
+gboolean left_closed;
+gboolean right_closed;
+
+gboolean reading_done = FALSE;
+
+static void adjust_clock (PseudoTcpSocket *sock);
+
+static void write_to_sock (PseudoTcpSocket *sock)
+{
+ gchar buf[1024];
+ gsize len;
+ gint wlen;
+ guint total = 0;
+
+ while (TRUE) {
+ len = fread (buf, 1, sizeof(buf), in);
+ if (len == 0) {
+ g_debug ("Done reading data from file");
+ g_assert (feof (in));
+ reading_done = TRUE;
+ pseudo_tcp_socket_close (sock, FALSE);
+ break;
+ } else {
+ wlen = pseudo_tcp_socket_send (sock, buf, len);
+ g_debug ("Sending %" G_GSIZE_FORMAT " bytes : %d", len, wlen);
+ total += wlen;
+ total_read += wlen;
+ if (wlen < (gint) len) {
+ g_debug ("seeking %" G_GSIZE_FORMAT " from %lu", wlen - len,
+ ftell (in));
+ fseek (in, wlen - len, SEEK_CUR);
+ g_assert (!feof (in));
+ g_debug ("Socket queue full after %d bytes written", total);
+ break;
+ }
+ }
+ }
+ adjust_clock (sock);
+}
+
+static void opened (PseudoTcpSocket *sock, gpointer data)
+{
+ g_debug ("Socket %p Opened", sock);
+ if (sock == left) {
+ if (in)
+ write_to_sock (sock);
+ else {
+ pseudo_tcp_socket_send (sock, "abcdefghijklmnopqrstuvwxyz", 26);
+ reading_done = TRUE;
+ pseudo_tcp_socket_close (sock, FALSE);
+ }
+ }
+}
+
+static void readable (PseudoTcpSocket *sock, gpointer data)
+{
+ gchar buf[1024];
+ gint len;
+ g_debug ("Socket %p Readable", sock);
+
+ do {
+ len = pseudo_tcp_socket_recv (sock, buf, sizeof(buf));
+
+ if (len > 0) {
+ g_debug ("Read %d bytes", len);
+ if (out) {
+ if (fwrite (buf, len, 1, out) == 0)
+ g_debug ("Error writing to output file");
+ else {
+ total_wrote += len;
+
+ g_assert (total_wrote <= total_read);
+ g_debug ("Written %d bytes, need %d bytes", total_wrote, total_read);
+ if (total_wrote == total_read && feof (in)) {
+ g_assert (reading_done);
+ pseudo_tcp_socket_close (sock, FALSE);
+ }
+ }
+ } else {
+ if (len == 26 && strncmp (buf, "abcdefghijklmnopqrstuvwxyz", len) == 0) {
+ pseudo_tcp_socket_close (sock, FALSE);
+ } else {
+ g_debug ("Error reading data.. read %d bytes : %s", len, buf);
+ exit (-1);
+ }
+ }
+ } else if (len == 0) {
+ pseudo_tcp_socket_close (sock, FALSE);
+ }
+ } while (len > 0);
+
+ if (len == -1 &&
+ pseudo_tcp_socket_get_error (sock) != EWOULDBLOCK) {
+ g_debug ("Error reading from socket %p: %s", sock,
+ g_strerror (pseudo_tcp_socket_get_error (sock)));
+ exit (-1);
+ }
+}
+
+static void writable (PseudoTcpSocket *sock, gpointer data)
+{
+ g_debug ("Socket %p Writable", sock);
+ if (in && sock == left)
+ write_to_sock (sock);
+}
+
+static void closed (PseudoTcpSocket *sock, guint32 err, gpointer data)
+{
+ g_error ("Socket %p Closed : %d", sock, err);
+}
+
+struct notify_data {
+ PseudoTcpSocket *sock;
+ guint32 len;
+ gchar buffer[];
+};
+
+static gboolean notify_packet (gpointer user_data)
+{
+ struct notify_data *data = (struct notify_data*) user_data;
+
+ pseudo_tcp_socket_notify_packet (data->sock, data->buffer, data->len);
+ adjust_clock (data->sock);
+
+ g_free (data);
+ return FALSE;
+}
+
+static PseudoTcpWriteResult write_packet (PseudoTcpSocket *sock,
+ const gchar *buffer, guint32 len, gpointer user_data)
+{
+ struct notify_data *data;
+ PseudoTcpState state;
+ int drop_rate = rand () % 100;
+ g_object_get (sock, "state", &state, NULL);
+
+ if (drop_rate < 5) {
+ g_debug ("*********************Dropping packet (%d) from %p", drop_rate,
+ sock);
+ return WR_SUCCESS;
+ }
+
+ data = g_malloc (sizeof(struct notify_data) + len);
+
+ g_debug ("Socket %p(%d) Writing : %d bytes", sock, state, len);
+
+ memcpy (data->buffer, buffer, len);
+ data->len = len;
+
+ if (sock == left)
+ data->sock = right;
+ else
+ data->sock = left;
+
+ g_idle_add (notify_packet, data);
+
+ return WR_SUCCESS;
+}
+
+
+static gboolean notify_clock (gpointer data)
+{
+ PseudoTcpSocket *sock = (PseudoTcpSocket *)data;
+ //g_debug ("Socket %p: Notifying clock", sock);
+ pseudo_tcp_socket_notify_clock (sock);
+ adjust_clock (sock);
+ return FALSE;
+}
+
+static void adjust_clock (PseudoTcpSocket *sock)
+{
+ guint64 timeout = 0;
+
+ if (pseudo_tcp_socket_get_next_clock (sock, &timeout)) {
+ timeout -= g_get_monotonic_time () / 1000;
+ g_debug ("Socket %p: Adjusting clock to %" G_GUINT64_FORMAT " ms", sock, timeout);
+ if (sock == left) {
+ if (left_clock != 0)
+ g_source_remove (left_clock);
+ left_clock = g_timeout_add (timeout, notify_clock, sock);
+ } else {
+ if (right_clock != 0)
+ g_source_remove (right_clock);
+ right_clock = g_timeout_add (timeout, notify_clock, sock);
+ }
+ } else {
+ g_debug ("Socket %p should be destroyed, it's done", sock);
+ if (sock == left)
+ left_closed = TRUE;
+ else
+ right_closed = TRUE;
+ if (left_closed && right_closed)
+ g_main_loop_quit (mainloop);
+ }
+}
+
+
+int main (int argc, char *argv[])
+{
+ PseudoTcpCallbacks cbs = {
+ NULL, opened, readable, writable, closed, write_packet
+ };
+
+ setlocale (LC_ALL, "");
+
+ mainloop = g_main_loop_new (NULL, FALSE);
+
+ pseudo_tcp_set_debug_level (PSEUDO_TCP_DEBUG_VERBOSE);
+
+ left_closed = right_closed = FALSE;
+
+ left = pseudo_tcp_socket_new (0, &cbs);
+ right = pseudo_tcp_socket_new (0, &cbs);
+ g_debug ("Left: %p. Right: %p", left, right);
+
+ pseudo_tcp_socket_notify_mtu (left, 1496);
+ pseudo_tcp_socket_notify_mtu (right, 1496);
+
+ pseudo_tcp_socket_connect (left);
+ adjust_clock (left);
+ adjust_clock (right);
+
+ if (argc == 3) {
+ in = fopen (argv[1], "r");
+ out = fopen (argv[2], "w");
+ }
+
+ g_main_loop_run (mainloop);
+
+ g_object_unref (left);
+ g_object_unref (right);
+
+ if (in)
+ fclose (in);
+ if (out)
+ fclose (out);
+
+ return 0;
+}
+
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2007 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Kai Vehmanen, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "agent.h"
+#include "agent-priv.h" /* for testing purposes */
+
+#include <stdlib.h>
+#include <string.h>
+#ifdef _WIN32
+#include <io.h>
+#endif
+
+static NiceComponentState global_lagent_state = NICE_COMPONENT_STATE_LAST;
+static NiceComponentState global_ragent_state = NICE_COMPONENT_STATE_LAST;
+static guint global_components_ready = 0;
+static guint global_components_ready_exit = 0;
+static guint global_components_failed = 0;
+static guint global_components_failed_exit = 0;
+static GMainLoop *global_mainloop = NULL;
+static gboolean global_lagent_gathering_done = FALSE;
+static gboolean global_ragent_gathering_done = FALSE;
+static gboolean global_lagent_ibr_received = FALSE;
+static gboolean global_ragent_ibr_received = FALSE;
+static int global_lagent_cands = 0;
+static int global_ragent_cands = 0;
+static gint global_ragent_read = 0;
+static gint global_ragent_read_exit = 0;
+
+static void priv_print_global_status (void)
+{
+ g_debug ("\tgathering_done=%d", global_lagent_gathering_done && global_ragent_gathering_done);
+ g_debug ("\tlstate=%d", global_lagent_state);
+ g_debug ("\trstate=%d", global_ragent_state);
+}
+
+static gboolean timer_cb (gpointer pointer)
+{
+ g_debug ("test-restart:%s: %p", G_STRFUNC, pointer);
+
+ /* signal status via a global variable */
+
+ /* note: should not be reached, abort */
+ g_debug ("ERROR: test has got stuck, aborting...");
+ exit (-1);
+
+}
+
+static void cb_nice_recv (NiceAgent *agent, guint stream_id, guint component_id, guint len, gchar *buf, gpointer user_data)
+{
+ g_debug ("test-restart:%s: %p", G_STRFUNC, user_data);
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent; (void)stream_id; (void)component_id; (void)buf;
+
+ if ((intptr_t)user_data == 2) {
+ global_ragent_read += len;
+
+ if (global_ragent_read == global_ragent_read_exit)
+ g_main_loop_quit (global_mainloop);
+ }
+}
+
+static void cb_candidate_gathering_done(NiceAgent *agent, guint stream_id, gpointer data)
+{
+ g_debug ("test-restart:%s: %p", G_STRFUNC, data);
+
+ if ((intptr_t)data == 1)
+ global_lagent_gathering_done = TRUE;
+ else if ((intptr_t)data == 2)
+ global_ragent_gathering_done = TRUE;
+
+ if (global_lagent_gathering_done &&
+ global_ragent_gathering_done)
+ g_main_loop_quit (global_mainloop);
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent;
+}
+
+static void cb_component_state_changed (NiceAgent *agent, guint stream_id, guint component_id, guint state, gpointer data)
+{
+ g_debug ("test-restart:%s: %p", G_STRFUNC, data);
+
+ if ((intptr_t)data == 1)
+ global_lagent_state = state;
+ else if ((intptr_t)data == 2)
+ global_ragent_state = state;
+
+ if (state == NICE_COMPONENT_STATE_READY)
+ global_components_ready++;
+ if (state == NICE_COMPONENT_STATE_FAILED)
+ global_components_failed++;
+
+ g_debug ("test-restart: READY %u exit at %u.", global_components_ready, global_components_ready_exit);
+
+ /* signal status via a global variable */
+ if (global_components_ready == global_components_ready_exit) {
+ g_main_loop_quit (global_mainloop);
+ return;
+ }
+
+ /* signal status via a global variable */
+ if (global_components_failed == global_components_failed_exit) {
+ g_main_loop_quit (global_mainloop);
+ return;
+ }
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent; (void)stream_id; (void)data; (void)component_id;
+}
+
+static void cb_new_selected_pair(NiceAgent *agent, guint stream_id, guint component_id,
+ gchar *lfoundation, gchar* rfoundation, gpointer data)
+{
+ g_debug ("test-restart:%s: %p", G_STRFUNC, data);
+
+ if ((intptr_t)data == 1)
+ ++global_lagent_cands;
+ else if ((intptr_t)data == 2)
+ ++global_ragent_cands;
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent; (void)stream_id; (void)component_id; (void)lfoundation; (void)rfoundation;
+}
+
+static void cb_new_candidate(NiceAgent *agent, guint stream_id, guint component_id,
+ gchar *foundation, gpointer data)
+{
+ g_debug ("test-restart:%s: %p", G_STRFUNC, data);
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent; (void)stream_id; (void)data; (void)component_id; (void)foundation;
+}
+
+static void cb_initial_binding_request_received(NiceAgent *agent, guint stream_id, gpointer data)
+{
+ g_debug ("test-restart:%s: %p", G_STRFUNC, data);
+
+ if ((intptr_t)data == 1)
+ global_lagent_ibr_received = TRUE;
+ else if ((intptr_t)data == 2)
+ global_ragent_ibr_received = TRUE;
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent; (void)stream_id; (void)data;
+}
+
+static void priv_get_local_addr (NiceAgent *agent, guint stream_id, guint component_id, NiceAddress *dstaddr)
+{
+ GSList *cands, *i;
+ cands = nice_agent_get_local_candidates(agent, stream_id, component_id);
+ for (i = cands; i; i = i->next) {
+ NiceCandidate *cand = i->data;
+ if (cand) {
+ g_assert (dstaddr);
+ *dstaddr = cand->addr;
+ }
+ }
+ for (i = cands; i; i = i->next)
+ nice_candidate_free ((NiceCandidate *) i->data);
+ g_slist_free (cands);
+}
+
+static int run_restart_test (NiceAgent *lagent, NiceAgent *ragent, NiceAddress *baseaddr)
+{
+ NiceAddress laddr, raddr, laddr_rtcp, raddr_rtcp;
+ NiceCandidate cdes;
+ GSList *cands;
+ guint ls_id, rs_id;
+ guint64 tie_breaker;
+
+ /* XXX: dear compiler, these are for you: */
+ (void)baseaddr;
+
+ memset (&cdes, 0, sizeof(NiceCandidate));
+ cdes.priority = 10000;
+ strcpy (cdes.foundation, "1");
+ cdes.type = NICE_CANDIDATE_TYPE_HOST;
+ cdes.transport = NICE_CANDIDATE_TRANSPORT_UDP;
+
+ /* step: initialize variables modified by the callbacks */
+ global_components_ready = 0;
+ global_components_ready_exit = 4;
+ global_components_failed = 0;
+ global_components_failed_exit = 4;
+ global_lagent_gathering_done = FALSE;
+ global_ragent_gathering_done = FALSE;
+ global_lagent_ibr_received =
+ global_ragent_ibr_received = FALSE;
+ global_lagent_cands =
+ global_ragent_cands = 0;
+ global_ragent_read_exit = -1;
+
+ g_object_set (G_OBJECT (lagent), "controlling-mode", TRUE, NULL);
+ g_object_set (G_OBJECT (ragent), "controlling-mode", FALSE, NULL);
+
+ /* step: add one stream, with RTP+RTCP components, to each agent */
+ ls_id = nice_agent_add_stream (lagent, 2);
+ rs_id = nice_agent_add_stream (ragent, 2);
+ g_assert (ls_id > 0);
+ g_assert (rs_id > 0);
+
+ nice_agent_gather_candidates (lagent, ls_id);
+ nice_agent_gather_candidates (ragent, rs_id);
+
+ /* step: attach to mainloop (needed to register the fds) */
+ nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv, (gpointer)1);
+ nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTCP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv, (gpointer)1);
+ nice_agent_attach_recv (ragent, rs_id, NICE_COMPONENT_TYPE_RTP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv, (gpointer)2);
+ nice_agent_attach_recv (ragent, rs_id, NICE_COMPONENT_TYPE_RTCP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv, (gpointer)2);
+
+ /* step: run mainloop until local candidates are ready
+ * (see timer_cb() above) */
+ if (global_lagent_gathering_done != TRUE ||
+ global_ragent_gathering_done != TRUE) {
+ g_debug ("test-restart: Added streams, running mainloop until 'candidate-gathering-done'...");
+ g_main_loop_run (global_mainloop);
+ g_assert (global_lagent_gathering_done == TRUE);
+ g_assert (global_ragent_gathering_done == TRUE);
+ }
+
+ /* step: find out the local candidates of each agent */
+
+ priv_get_local_addr (ragent, rs_id, NICE_COMPONENT_TYPE_RTP, &raddr);
+ g_debug ("test-restart: local RTP port R %u",
+ nice_address_get_port (&raddr));
+
+ priv_get_local_addr (lagent, ls_id, NICE_COMPONENT_TYPE_RTP, &laddr);
+ g_debug ("test-restart: local RTP port L %u",
+ nice_address_get_port (&laddr));
+
+ priv_get_local_addr (ragent, rs_id, NICE_COMPONENT_TYPE_RTCP, &raddr_rtcp);
+ g_debug ("test-restart: local RTCP port R %u",
+ nice_address_get_port (&raddr_rtcp));
+
+ priv_get_local_addr (lagent, ls_id, NICE_COMPONENT_TYPE_RTCP, &laddr_rtcp);
+ g_debug ("test-restart: local RTCP port L %u",
+ nice_address_get_port (&laddr_rtcp));
+
+ /* step: pass the remote candidates to agents */
+ cands = g_slist_append (NULL, &cdes);
+ {
+ gchar *ufrag = NULL, *password = NULL;
+ nice_agent_get_local_credentials(lagent, ls_id, &ufrag, &password);
+ nice_agent_set_remote_credentials (ragent,
+ rs_id, ufrag, password);
+ g_free (ufrag);
+ g_free (password);
+ nice_agent_get_local_credentials(ragent, rs_id, &ufrag, &password);
+ nice_agent_set_remote_credentials (lagent,
+ ls_id, ufrag, password);
+ g_free (ufrag);
+ g_free (password);
+ }
+ cdes.component_id = NICE_COMPONENT_TYPE_RTP;
+ cdes.addr = raddr;
+ nice_agent_set_remote_candidates (lagent, ls_id, NICE_COMPONENT_TYPE_RTP, cands);
+ cdes.addr = laddr;
+ nice_agent_set_remote_candidates (ragent, rs_id, NICE_COMPONENT_TYPE_RTP, cands);
+ cdes.component_id = NICE_COMPONENT_TYPE_RTCP;
+ cdes.addr = raddr_rtcp;
+ nice_agent_set_remote_candidates (lagent, ls_id, NICE_COMPONENT_TYPE_RTCP, cands);
+ cdes.addr = laddr_rtcp;
+ nice_agent_set_remote_candidates (ragent, rs_id, NICE_COMPONENT_TYPE_RTCP, cands);
+ /* This role switch request will be effective after restart. We test
+ * here that the role cannot be externally modified after conncheck
+ * has started. */
+ g_object_set (G_OBJECT (ragent), "controlling-mode", TRUE, NULL);
+ g_assert (ragent->controlling_mode == FALSE);
+
+ g_debug ("test-restart: Set properties, next running mainloop until connectivity checks succeed...");
+
+ /* step: run the mainloop until connectivity checks succeed
+ * (see timer_cb() above) */
+ g_main_loop_run (global_mainloop);
+
+ /* note: verify that STUN binding requests were sent */
+ g_assert (global_lagent_ibr_received == TRUE);
+ g_assert (global_ragent_ibr_received == TRUE);
+ /* note: verify that correct number of local candidates were reported */
+ g_assert (global_lagent_cands == 2);
+ g_assert (global_ragent_cands == 2);
+ /* note: verify that agents are in correct state */
+ g_assert (global_lagent_state == NICE_COMPONENT_STATE_READY);
+ g_assert (global_ragent_state == NICE_COMPONENT_STATE_READY);
+
+ /* step: next send a packet (should work during restart) and
+ * then request an ICE restart by resetting the remote
+ * candidates for agent R */
+
+ g_debug ("-------------------------------------------\n"
+ "test-restart: Requesting a RESTART...");
+
+ /* step: send a new test packet from L ot R */
+ global_ragent_read = 0;
+ g_assert (nice_agent_send (lagent, ls_id, 1, 16, "1234567812345678") == 16);
+
+ /* Both agent have a distinct role at the end of the conncheck */
+ g_assert (lagent->controlling_mode == TRUE);
+ g_assert (ragent->controlling_mode == FALSE);
+ /* step: restart agents, exchange updated credentials */
+ tie_breaker = ragent->tie_breaker;
+ nice_agent_restart (ragent);
+ g_assert (tie_breaker != ragent->tie_breaker);
+ /* This role switch of ragent should be done now, and both agents
+ * have now the same role, which should generate a role conflict
+ * resolution situation */
+ g_assert (lagent->controlling_mode == TRUE);
+ g_assert (ragent->controlling_mode == TRUE);
+ nice_agent_restart (lagent);
+ {
+ gchar *ufrag = NULL, *password = NULL;
+ nice_agent_get_local_credentials(lagent, ls_id, &ufrag, &password);
+ nice_agent_set_remote_credentials (ragent,
+ rs_id, ufrag, password);
+ g_free (ufrag);
+ g_free (password);
+ nice_agent_get_local_credentials(ragent, rs_id, &ufrag, &password);
+ nice_agent_set_remote_credentials (lagent,
+ ls_id, ufrag, password);
+ g_free (ufrag);
+ g_free (password);
+ }
+
+ /* send another packet after restart */
+ g_assert (nice_agent_send (lagent, ls_id, 1, 16, "1234567812345678") == 16);
+
+ /* step: reset state variables */
+ global_lagent_ibr_received = FALSE;
+ global_ragent_ibr_received = FALSE;
+ global_components_ready = 0;
+
+ /* step: exchange remote candidates */
+ cdes.component_id = NICE_COMPONENT_TYPE_RTP;
+ cdes.addr = raddr;
+ nice_agent_set_remote_candidates (lagent, ls_id, NICE_COMPONENT_TYPE_RTP, cands);
+ cdes.addr = laddr;
+ nice_agent_set_remote_candidates (ragent, rs_id, NICE_COMPONENT_TYPE_RTP, cands);
+ cdes.component_id = NICE_COMPONENT_TYPE_RTCP;
+ cdes.addr = raddr_rtcp;
+ nice_agent_set_remote_candidates (lagent, ls_id, NICE_COMPONENT_TYPE_RTCP, cands);
+ cdes.addr = laddr_rtcp;
+ nice_agent_set_remote_candidates (ragent, rs_id, NICE_COMPONENT_TYPE_RTCP, cands);
+
+ g_main_loop_run (global_mainloop);
+
+ /* note: verify that payload was succesfully received */
+ g_assert (global_ragent_read == 32);
+ /* note: verify binding requests were resent after restart */
+ g_assert (global_lagent_ibr_received == TRUE);
+ g_assert (global_ragent_ibr_received == TRUE);
+ /* note: verify that a role switch occured for one of the agents */
+ g_assert (ragent->controlling_mode != lagent->controlling_mode);
+
+ g_debug ("test-restart: Ran mainloop, removing streams...");
+
+ /* step: clean up resources and exit */
+
+ g_slist_free (cands);
+ nice_agent_remove_stream (lagent, ls_id);
+ nice_agent_remove_stream (ragent, rs_id);
+
+ return 0;
+}
+
+int main (void)
+{
+ NiceAgent *lagent, *ragent; /* agent's L and R */
+ NiceAddress baseaddr;
+ int result;
+ guint timer_id;
+ const char *stun_server = NULL, *stun_server_port = NULL;
+
+#ifdef G_OS_WIN32
+ WSADATA w;
+
+ WSAStartup(0x0202, &w);
+#endif
+
+ global_mainloop = g_main_loop_new (NULL, FALSE);
+
+ /* Note: impl limits ...
+ * - no multi-stream support
+ * - no IPv6 support
+ */
+
+
+ /* step: create the agents L and R */
+ lagent = nice_agent_new (g_main_loop_get_context (global_mainloop), NICE_COMPATIBILITY_RFC5245);
+ ragent = nice_agent_new (g_main_loop_get_context (global_mainloop), NICE_COMPATIBILITY_RFC5245);
+ g_object_set (G_OBJECT (lagent), "ice-tcp", FALSE, NULL);
+ g_object_set (G_OBJECT (ragent), "ice-tcp", FALSE, NULL);
+
+ g_object_set (G_OBJECT (lagent), "upnp", FALSE, NULL);
+ g_object_set (G_OBJECT (ragent), "upnp", FALSE, NULL);
+
+ /* step: add a timer to catch state changes triggered by signals */
+ timer_id = g_timeout_add (30000, timer_cb, NULL);
+
+ /* step: specify which local interface to use */
+ if (!nice_address_set_from_string (&baseaddr, "127.0.0.1"))
+ g_assert_not_reached ();
+ nice_agent_add_local_address (lagent, &baseaddr);
+ nice_agent_add_local_address (ragent, &baseaddr);
+
+ g_signal_connect (G_OBJECT (lagent), "candidate-gathering-done",
+ G_CALLBACK (cb_candidate_gathering_done), (gpointer)1);
+ g_signal_connect (G_OBJECT (ragent), "candidate-gathering-done",
+ G_CALLBACK (cb_candidate_gathering_done), (gpointer)2);
+ g_signal_connect (G_OBJECT (lagent), "component-state-changed",
+ G_CALLBACK (cb_component_state_changed), (gpointer)1);
+ g_signal_connect (G_OBJECT (ragent), "component-state-changed",
+ G_CALLBACK (cb_component_state_changed), (gpointer)2);
+ g_signal_connect (G_OBJECT (lagent), "new-selected-pair",
+ G_CALLBACK (cb_new_selected_pair), (gpointer)1);
+ g_signal_connect (G_OBJECT (ragent), "new-selected-pair",
+ G_CALLBACK (cb_new_selected_pair), (gpointer)2);
+ g_signal_connect (G_OBJECT (lagent), "new-candidate",
+ G_CALLBACK (cb_new_candidate), (gpointer)1);
+ g_signal_connect (G_OBJECT (ragent), "new-candidate",
+ G_CALLBACK (cb_new_candidate), (gpointer)2);
+ g_signal_connect (G_OBJECT (lagent), "initial-binding-request-received",
+ G_CALLBACK (cb_initial_binding_request_received), (gpointer)1);
+ g_signal_connect (G_OBJECT (ragent), "initial-binding-request-received",
+ G_CALLBACK (cb_initial_binding_request_received), (gpointer)2);
+
+ stun_server = getenv ("NICE_STUN_SERVER");
+ stun_server_port = getenv ("NICE_STUN_SERVER_PORT");
+ if (stun_server) {
+ g_object_set (G_OBJECT (lagent), "stun-server", stun_server, NULL);
+ g_object_set (G_OBJECT (lagent), "stun-server-port", atoi (stun_server_port), NULL);
+ g_object_set (G_OBJECT (ragent), "stun-server", stun_server, NULL);
+ g_object_set (G_OBJECT (ragent), "stun-server-port", atoi (stun_server_port), NULL);
+ }
+
+ /* step: run test the first time */
+ g_debug ("test-restart: TEST STARTS / restart test");
+ result = run_restart_test (lagent, ragent, &baseaddr);
+ priv_print_global_status ();
+ g_assert (result == 0);
+ g_assert (global_lagent_state == NICE_COMPONENT_STATE_READY);
+ g_assert (global_ragent_state == NICE_COMPONENT_STATE_READY);
+
+ g_object_unref (lagent);
+ g_object_unref (ragent);
+
+
+ g_main_loop_unref (global_mainloop);
+ global_mainloop = NULL;
+
+ g_source_remove (timer_id);
+#ifdef G_OS_WIN32
+ WSACleanup();
+#endif
+ return result;
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2014 Collabora Ltd.
+ * Contact: Philip Withnall
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Philip Withnall, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+
+/**
+ * This is a comprehensive unit test for send() and recv() behaviour in libnice,
+ * covering all APIs except the old nice_agent_attach_recv() one. It aims to
+ * test the correctness of reliable and non-reliable I/O through libnice, using
+ * a variety of data and a variety of buffer sizes.
+ *
+ * Abnormal features like error handling, zero-length buffer handling, stream
+ * closure and cancellation are not tested.
+ *
+ * This is *not* a performance test, and would require significant work to be
+ * useful as one. It allocates all of its buffers dynamically, and walks over
+ * them frequently to set and check data.
+ *
+ * Several of the strategies in the test make use of random numbers. The seed
+ * values for these are deterministically set (in main()), but may be specified
+ * on the command line to allow fuzzing.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "agent.h"
+#include "test-io-stream-common.h"
+
+#include <stdlib.h>
+#include <string.h>
+#ifndef G_OS_WIN32
+#include <unistd.h>
+#endif
+
+/* Maximum IP payload ((1 << 16) - 1), minus IP header, minus UDP header. */
+#define MAX_MESSAGE_SIZE (65535 - 20 - 8) /* bytes */
+
+typedef enum {
+ STREAM_AGENT, /* nice_agent_[send|recv]() */
+ STREAM_AGENT_NONBLOCKING, /* nice_agent_[send|recv]_nonblocking() */
+ STREAM_GIO, /* Nice[Input|Output]Stream */
+ STREAM_GSOURCE, /* GPollable[Input|Output]Stream */
+} StreamApi;
+#define STREAM_API_N_ELEMENTS (STREAM_GSOURCE + 1)
+
+typedef enum {
+ BUFFER_SIZE_CONSTANT_LARGE, /* always 65535 bytes */
+ BUFFER_SIZE_CONSTANT_SMALL, /* always 4096 bytes */
+ BUFFER_SIZE_CONSTANT_TINY, /* always 1 byte */
+ BUFFER_SIZE_ASCENDING, /* ascending powers of 2 */
+ BUFFER_SIZE_RANDOM, /* random every time */
+} BufferSizeStrategy;
+#define BUFFER_SIZE_STRATEGY_N_ELEMENTS (BUFFER_SIZE_RANDOM + 1)
+
+typedef enum {
+ BUFFER_COUNT_CONSTANT_ONE, /* always a single buffer */
+ BUFFER_COUNT_CONSTANT_TWO, /* always two buffers */
+ BUFFER_COUNT_RANDOM, /* random every time */
+} BufferCountStrategy;
+#define BUFFER_COUNT_STRATEGY_N_ELEMENTS (BUFFER_COUNT_RANDOM + 1)
+
+typedef enum {
+ MESSAGE_COUNT_CONSTANT_ONE, /* always a single message */
+ MESSAGE_COUNT_CONSTANT_TWO, /* always two messages */
+ MESSAGE_COUNT_RANDOM, /* random every time */
+} MessageCountStrategy;
+#define MESSAGE_COUNT_STRATEGY_N_ELEMENTS (MESSAGE_COUNT_RANDOM + 1)
+
+typedef enum {
+ BUFFER_DATA_CONSTANT, /* fill with 0xfe */
+ BUFFER_DATA_ASCENDING, /* ascending values for each byte */
+ BUFFER_DATA_PSEUDO_RANDOM, /* every byte is pseudo-random */
+} BufferDataStrategy;
+#define BUFFER_DATA_STRATEGY_N_ELEMENTS (BUFFER_DATA_PSEUDO_RANDOM + 1)
+
+typedef struct {
+ /* Test configuration (immutable per test run). */
+ gboolean reliable;
+ StreamApi stream_api;
+ struct {
+ BufferSizeStrategy buffer_size_strategy;
+ BufferCountStrategy buffer_count_strategy;
+ MessageCountStrategy message_count_strategy;
+ } transmit;
+ struct {
+ BufferSizeStrategy buffer_size_strategy;
+ BufferCountStrategy buffer_count_strategy;
+ MessageCountStrategy message_count_strategy;
+ } receive;
+ BufferDataStrategy buffer_data_strategy;
+ gsize n_bytes;
+ guint n_messages;
+
+ /* Test state. */
+ GRand *transmit_size_rand;
+ GRand *receive_size_rand;
+ gsize transmitted_bytes;
+ gsize received_bytes;
+ gsize *other_received_bytes;
+ guint transmitted_messages;
+ guint received_messages;
+ guint *other_received_messages;
+} TestData;
+
+/* Whether @stream_api is blocking (vs. non-blocking). */
+static gboolean
+stream_api_is_blocking (StreamApi stream_api)
+{
+ switch (stream_api) {
+ case STREAM_AGENT:
+ case STREAM_GIO:
+ return TRUE;
+ case STREAM_AGENT_NONBLOCKING:
+ case STREAM_GSOURCE:
+ return FALSE;
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+/* Whether @stream_api only works for reliable NiceAgents. */
+static gboolean
+stream_api_is_reliable_only (StreamApi stream_api)
+{
+ switch (stream_api) {
+ case STREAM_GSOURCE:
+ case STREAM_GIO:
+ return TRUE;
+ case STREAM_AGENT:
+ case STREAM_AGENT_NONBLOCKING:
+ return FALSE;
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+/* Whether @stream_api supports vectored I/O (multiple buffers or messages). */
+static gboolean
+stream_api_supports_vectored_io (StreamApi stream_api)
+{
+ switch (stream_api) {
+ case STREAM_AGENT:
+ case STREAM_AGENT_NONBLOCKING:
+ return TRUE;
+ case STREAM_GSOURCE:
+ case STREAM_GIO:
+ return FALSE;
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+/* Generate a size for the buffer containing the @buffer_offset-th byte.
+ * Guaranteed to be in the interval [1, 1 << 16). ((1 << 16) is the maximum
+ * message size.) */
+static gsize
+generate_buffer_size (BufferSizeStrategy strategy, GRand *grand,
+ gsize buffer_offset)
+{
+ switch (strategy) {
+ case BUFFER_SIZE_CONSTANT_LARGE:
+ return (1 << 16) - 1;
+
+ case BUFFER_SIZE_CONSTANT_SMALL:
+ return 4096;
+
+ case BUFFER_SIZE_CONSTANT_TINY:
+ return 1;
+
+ case BUFFER_SIZE_ASCENDING:
+ return CLAMP (1L << buffer_offset, 1, (1 << 16) - 1);
+
+ case BUFFER_SIZE_RANDOM:
+ return g_rand_int_range (grand, 1, 1 << 16);
+
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+/* Generate a number of buffers to allocate when receiving the @buffer_offset-th
+ * byte. Guaranteed to be in the interval [1, 100], where 100 was chosen
+ * arbitrarily.*/
+static guint
+generate_buffer_count (BufferCountStrategy strategy, GRand *grand,
+ gsize buffer_offset)
+{
+ switch (strategy) {
+ case BUFFER_COUNT_CONSTANT_ONE:
+ return 1;
+
+ case BUFFER_COUNT_CONSTANT_TWO:
+ return 2;
+
+ case BUFFER_COUNT_RANDOM:
+ return g_rand_int_range (grand, 1, 100 + 1);
+
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+/* Generate a number of messages to allocate and receive into when receiving the
+ * @buffer_offset-th byte. Guaranteed to be in the interval [1, 100], where 100
+ * was chosen arbitrarily.*/
+static guint
+generate_message_count (MessageCountStrategy strategy, GRand *grand,
+ guint buffer_index)
+{
+ switch (strategy) {
+ case MESSAGE_COUNT_CONSTANT_ONE:
+ return 1;
+
+ case MESSAGE_COUNT_CONSTANT_TWO:
+ return 2;
+
+ case MESSAGE_COUNT_RANDOM:
+ return g_rand_int_range (grand, 1, 100 + 1);
+
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+/* Fill the given @buf with @buf_len bytes of generated data. The data is
+ * deterministically generated, so that:
+ * generate_buffer_data(_, I, buf, 2)
+ * and
+ * generate_buffer_data(_, I+1, buf+1, 1)
+ * generate the same buf[I+1] byte, for all I.
+ *
+ * The generation strategies are generally chosen to produce data which makes
+ * send/receive errors (insertions, swaps, elisions) obvious. */
+static void
+generate_buffer_data (BufferDataStrategy strategy, gsize buffer_offset,
+ guint8 *buf, gsize buf_len)
+{
+ switch (strategy) {
+ case BUFFER_DATA_CONSTANT:
+ memset (buf, 0xfe, buf_len);
+ break;
+
+ case BUFFER_DATA_ASCENDING: {
+ gsize i;
+
+ for (i = 0; i < buf_len; i++) {
+ buf[i] = (i + buffer_offset) & 0xff;
+ }
+
+ break;
+ }
+
+ case BUFFER_DATA_PSEUDO_RANDOM: {
+ gsize i;
+
+ /* This can’t use GRand, because then the number of calls to g_rand_*()
+ * methods would affect its output, and the bytes generated here have to be
+ * entirely deterministic on @buffer_offset.
+ *
+ * Instead, use something akin to a LCG, except without any feedback
+ * (because that would make it non-deterministic). The objective is to
+ * generate numbers which are sufficiently pseudo-random that it’s likely
+ * transpositions, elisions and insertions will be detected.
+ *
+ * The constants come from ‘ANSI C’ in:
+ * http://en.wikipedia.org/wiki/Linear_congruential_generator
+ */
+ for (i = 0; i < buf_len; i++) {
+ buf[i] = (1103515245 * (buffer_offset + i) + 12345) & 0xff;
+ }
+
+ break;
+ }
+
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+/* Choose a size and allocate a receive buffer in @buf, ready to receive bytes
+ * starting at @buffer_offset into the stream. Fill the buffer with poison
+ * values to hopefully make incorrect writes/reads more obvious.
+ *
+ * @buf must be freed with g_free(). */
+static void
+generate_buffer_to_receive (TestIOStreamThreadData *data, gsize buffer_offset,
+ guint8 **buf, gsize *buf_len)
+{
+ TestData *test_data = data->user_data;
+
+ /* Allocate the buffer. */
+ *buf_len = generate_buffer_size (test_data->receive.buffer_size_strategy,
+ test_data->receive_size_rand, buffer_offset);
+ *buf = g_malloc (*buf_len);
+
+ /* Fill it with poison to try and detect incorrect writes. */
+ memset (*buf, 0xaa, *buf_len);
+}
+
+/* Similar to generate_buffer_to_receive(), but generate an entire message array
+ * with multiple buffers instead.
+ *
+ * @max_buffer_size may be used to limit the total size of all the buffers in
+ * all the messages, for example to avoid blocking on receiving data which will
+ * never be sent. This only applies for blocking, reliable stream APIs.
+ *
+ * @max_n_messages may be used to limit the number of messages generated, to
+ * avoid blocking on receiving messages which will never be sent. This only
+ * applies for blocking, non-reliable stream APIs.
+ *
+ * @messages must be freed with g_free(), as must all of the buffer arrays and
+ * the buffers themselves. */
+static void
+generate_messages_to_receive (TestIOStreamThreadData *data, gsize buffer_offset,
+ NiceInputMessage **messages, guint *n_messages, gsize max_buffer_size,
+ guint max_n_messages)
+{
+ TestData *test_data = data->user_data;
+ guint i;
+
+ /* Allocate the messages. */
+ *n_messages =
+ generate_message_count (test_data->receive.message_count_strategy,
+ test_data->receive_size_rand, buffer_offset);
+
+ if (!data->reliable)
+ *n_messages = MIN (*n_messages, max_n_messages);
+
+ *messages = g_malloc_n (*n_messages, sizeof (NiceInputMessage));
+
+ for (i = 0; i < *n_messages; i++) {
+ NiceInputMessage *message = &((*messages)[i]);
+ guint j;
+
+ message->n_buffers =
+ generate_buffer_count (test_data->receive.buffer_count_strategy,
+ test_data->receive_size_rand, buffer_offset);
+ message->buffers = g_malloc_n (message->n_buffers, sizeof (GInputVector));
+ message->from = NULL;
+ message->length = 0;
+
+ for (j = 0; j < (guint) message->n_buffers; j++) {
+ GInputVector *buffer = &message->buffers[j];
+ gsize buf_len;
+
+ buf_len =
+ generate_buffer_size (test_data->receive.buffer_size_strategy,
+ test_data->receive_size_rand, buffer_offset);
+
+ /* Trim the buffer length if it would otherwise cause the API to block. */
+ if (data->reliable) {
+ buf_len = MIN (buf_len, max_buffer_size);
+ max_buffer_size -= buf_len;
+ }
+
+ buffer->size = buf_len;
+ buffer->buffer = g_malloc (buffer->size);
+
+ /* Fill it with poison to try and detect incorrect writes. */
+ memset (buffer->buffer, 0xaa, buffer->size);
+
+ /* If we’ve hit the max_buffer_size, adjust the buffer and message counts
+ * and run away. */
+ if (data->reliable && max_buffer_size == 0) {
+ message->n_buffers = j + 1;
+ *n_messages = i + 1;
+ return;
+ }
+ }
+ }
+}
+
+/* Validate the length and data of a received buffer of length @buf_len, filled
+ * with @len valid bytes. Updates the internal state machine to mark the bytes
+ * as received. This consumes @buf. */
+static void
+validate_received_buffer (TestIOStreamThreadData *data, gsize buffer_offset,
+ guint8 **buf, gsize buf_len, gssize len)
+{
+ TestData *test_data = data->user_data;
+ guint8 *expected_buf;
+
+ g_assert_cmpint (len, <=, buf_len);
+ g_assert_cmpint (len, >=, 0);
+
+ if (stream_api_is_blocking (test_data->stream_api) && data->reliable)
+ g_assert_cmpint (len, ==, buf_len);
+
+ /* Validate the buffer contents.
+ *
+ * Note: Buffers can only be validated up to valid_len. The buffer may
+ * have been re-used internally (e.g. by receiving a STUN message, then
+ * overwriting it with a data packet), so we can’t guarantee that the
+ * bytes beyond valid_len have been untouched. */
+ expected_buf = g_malloc (buf_len);
+ memset (expected_buf, 0xaa, buf_len);
+ generate_buffer_data (test_data->buffer_data_strategy, buffer_offset,
+ expected_buf, len);
+ g_assert (memcmp (*buf, expected_buf, len) == 0);
+ g_free (expected_buf);
+
+ test_data->received_bytes += len;
+
+ g_free (*buf);
+}
+
+/* Similar to validate_received_buffer(), except it validates a message array
+ * instead of a single buffer. This consumes @messages. */
+static void
+validate_received_messages (TestIOStreamThreadData *data, gsize buffer_offset,
+ NiceInputMessage *messages, guint n_messages, gint n_valid_messages)
+{
+ TestData *test_data = data->user_data;
+ guint i;
+ gsize prev_message_len = G_MAXSIZE;
+
+ g_assert_cmpint (n_valid_messages, <=, n_messages);
+ g_assert_cmpint (n_valid_messages, >=, 0);
+
+ if (stream_api_is_blocking (test_data->stream_api))
+ g_assert_cmpint (n_valid_messages, ==, n_messages);
+
+ test_data->received_messages += n_valid_messages;
+
+ /* Validate the message contents. */
+ for (i = 0; i < (guint) n_valid_messages; i++) {
+ NiceInputMessage *message = &messages[i];
+ guint j;
+ gsize total_buf_len = 0;
+ gsize message_len_remaining = message->length;
+
+ g_assert_cmpint (message->n_buffers, >, 0);
+
+ for (j = 0; j < (guint) message->n_buffers; j++) {
+ GInputVector *buffer = &message->buffers[j];
+ gsize valid_len;
+
+ /* See note above about valid_len. */
+ total_buf_len += buffer->size;
+ valid_len = MIN (message_len_remaining, buffer->size);
+
+ /* Only validate buffer content for reliable mode, anything could
+ * be received in UDP mode
+ */
+ if (test_data->reliable) {
+ guint8 *expected_buf;
+
+ expected_buf = g_malloc (buffer->size);
+ memset (expected_buf, 0xaa, buffer->size);
+ generate_buffer_data (test_data->buffer_data_strategy, buffer_offset,
+ expected_buf, valid_len);
+ g_assert_cmpint (memcmp (buffer->buffer, expected_buf, valid_len), ==,
+ 0);
+ g_free (expected_buf);
+ buffer_offset += valid_len;
+ message_len_remaining -= valid_len;
+ }
+ test_data->received_bytes += valid_len;
+ }
+
+ g_assert_cmpuint (message->length, <=, total_buf_len);
+ g_assert_cmpuint (message->length, >=, 0);
+
+ /* No non-empty messages can follow an empty message. */
+ if (prev_message_len == 0)
+ g_assert_cmpuint (message->length, ==, 0);
+ prev_message_len = message->length;
+
+ /* If the API was blocking, it should have completely filled the message. */
+ if (stream_api_is_blocking (test_data->stream_api) && data->reliable)
+ g_assert_cmpuint (message->length, ==, total_buf_len);
+
+ g_assert (message->from == NULL);
+ }
+
+ /* Free all messages. */
+ for (i = 0; i < (guint) n_messages; i++) {
+ NiceInputMessage *message = &messages[i];
+ guint j;
+
+ for (j = 0; j < (guint) message->n_buffers; j++) {
+ GInputVector *buffer = &message->buffers[j];
+
+ g_free (buffer->buffer);
+ }
+
+ g_free (message->buffers);
+ }
+
+ g_free (messages);
+}
+
+/* Determine a size for the next transmit buffer, allocate it, and fill it with
+ * data to be transmitted. */
+static void
+generate_buffer_to_transmit (TestIOStreamThreadData *data, gsize buffer_offset,
+ guint8 **buf, gsize *buf_len)
+{
+ TestData *test_data = data->user_data;
+
+ /* Allocate the buffer. */
+ *buf_len = generate_buffer_size (test_data->transmit.buffer_size_strategy,
+ test_data->transmit_size_rand, buffer_offset);
+ *buf_len = MIN (*buf_len, test_data->n_bytes - test_data->transmitted_bytes);
+ *buf = g_malloc (*buf_len);
+
+ /* Fill it with data. */
+ generate_buffer_data (test_data->buffer_data_strategy, buffer_offset,
+ *buf, *buf_len);
+}
+
+/* Similar to generate_buffer_to_transmit(), except that it generates an array
+ * of NiceOutputMessages rather than a single buffer. */
+static void
+generate_messages_to_transmit (TestIOStreamThreadData *data,
+ gsize buffer_offset, NiceOutputMessage **messages, guint *n_messages)
+{
+ TestData *test_data = data->user_data;
+ guint i;
+ gsize total_buf_len = 0;
+
+ /* Determine the number of messages to send. */
+ *n_messages =
+ generate_message_count (test_data->transmit.message_count_strategy,
+ test_data->transmit_size_rand, buffer_offset);
+ *n_messages =
+ MIN (*n_messages,
+ test_data->n_messages - test_data->transmitted_messages);
+
+ *messages = g_malloc_n (*n_messages, sizeof (NiceOutputMessage));
+
+ for (i = 0; i < *n_messages; i++) {
+ NiceOutputMessage *message = &((*messages)[i]);
+ guint j;
+ gsize max_message_size;
+ gsize message_len = 0;
+
+ message->n_buffers =
+ generate_buffer_count (test_data->transmit.buffer_count_strategy,
+ test_data->transmit_size_rand, buffer_offset);
+ message->buffers = g_malloc_n (message->n_buffers, sizeof (GOutputVector));
+
+ /* Limit the overall message size to the smaller of (n_bytes / n_messages)
+ * and MAX_MESSAGE_SIZE, to ensure each message is non-empty. */
+ max_message_size =
+ MIN ((test_data->n_bytes / test_data->n_messages), MAX_MESSAGE_SIZE);
+
+ for (j = 0; j < (guint) message->n_buffers; j++) {
+ GOutputVector *buffer = &message->buffers[j];
+ gsize buf_len;
+ guint8 *buf;
+
+ buf_len =
+ generate_buffer_size (test_data->transmit.buffer_size_strategy,
+ test_data->transmit_size_rand, buffer_offset);
+ buf_len =
+ MIN (buf_len,
+ test_data->n_bytes - test_data->transmitted_bytes - total_buf_len);
+ buf_len = MIN (buf_len, max_message_size - message_len);
+
+ buffer->size = buf_len;
+ buf = g_malloc (buffer->size);
+ buffer->buffer = buf;
+ message_len += buf_len;
+ total_buf_len += buf_len;
+
+ /* Fill it with data. */
+ generate_buffer_data (test_data->buffer_data_strategy, buffer_offset,
+ buf, buf_len);
+
+ buffer_offset += buf_len;
+
+ /* Reached the maximum UDP payload size? */
+ if (message_len >= max_message_size) {
+ message->n_buffers = j + 1;
+ break;
+ }
+ }
+
+ g_assert_cmpuint (message_len, <=, max_message_size);
+ }
+}
+
+/* Validate the number of bytes transmitted, and update the test’s internal
+ * state machine. Consumes @buf. */
+static void
+notify_transmitted_buffer (TestIOStreamThreadData *data, gsize buffer_offset,
+ guint8 **buf, gsize buf_len, gssize len)
+{
+ TestData *test_data = data->user_data;
+
+ g_assert_cmpint (len, <=, buf_len);
+ g_assert_cmpint (len, >=, 0);
+
+ test_data->transmitted_bytes += len;
+
+ g_free (*buf);
+}
+
+static gsize
+output_message_get_size (const NiceOutputMessage *message)
+{
+ guint i;
+ gsize message_len = 0;
+
+ /* Find the total size of the message */
+ for (i = 0;
+ (message->n_buffers >= 0 && i < (guint) message->n_buffers) ||
+ (message->n_buffers < 0 && message->buffers[i].buffer != NULL);
+ i++)
+ message_len += message->buffers[i].size;
+
+ return message_len;
+}
+
+/* Similar to notify_transmitted_buffer(), except it operates on an array of
+ * messages from generate_messages_to_transmit(). */
+static void
+notify_transmitted_messages (TestIOStreamThreadData *data, gsize buffer_offset,
+ NiceOutputMessage **messages, guint n_messages, gint n_sent_messages)
+{
+ TestData *test_data = data->user_data;
+ guint i;
+
+ g_assert_cmpint (n_sent_messages, <=, n_messages);
+ g_assert_cmpint (n_sent_messages, >=, 0);
+
+ test_data->transmitted_messages += n_sent_messages;
+
+ for (i = 0; i < n_messages; i++) {
+ NiceOutputMessage *message = &((*messages)[i]);
+ guint j;
+
+ if (i < (guint) n_sent_messages)
+ test_data->transmitted_bytes += output_message_get_size (message);
+
+ for (j = 0; j < (guint) message->n_buffers; j++) {
+ GOutputVector *buffer = &message->buffers[j];
+
+ g_free ((guint8 *) buffer->buffer);
+ }
+
+ g_free (message->buffers);
+ }
+
+ g_free (*messages);
+}
+
+/*
+ * Implementation using nice_agent_recv_messages() and nice_agent_send().
+ */
+static void
+read_thread_agent_cb (GInputStream *input_stream, TestIOStreamThreadData *data)
+{
+ TestData *test_data = data->user_data;
+ guint stream_id, component_id;
+ gpointer tmp;
+
+ tmp = g_object_get_data (G_OBJECT (data->agent), "stream-id");
+ stream_id = GPOINTER_TO_UINT (tmp);
+ component_id = 1;
+
+ while (test_data->received_bytes < test_data->n_bytes) {
+ GError *error = NULL;
+ NiceInputMessage *messages;
+ guint n_messages;
+ gint n_valid_messages;
+
+ /* Initialise an array of messages to receive into. */
+ generate_messages_to_receive (data, test_data->received_bytes, &messages,
+ &n_messages, test_data->n_bytes - test_data->received_bytes,
+ test_data->n_messages - test_data->received_messages);
+
+ /* Block on receiving some data. */
+ n_valid_messages = nice_agent_recv_messages (data->agent, stream_id,
+ component_id, messages, n_messages, NULL, &error);
+ g_assert_no_error (error);
+
+ /* Check the messages and update the test’s state machine. */
+ validate_received_messages (data, test_data->received_bytes, messages,
+ n_messages, n_valid_messages);
+ }
+
+ check_for_termination (data, &test_data->received_bytes,
+ test_data->other_received_bytes, &test_data->transmitted_bytes,
+ test_data->n_bytes);
+}
+
+static void
+write_thread_agent_cb (GOutputStream *output_stream,
+ TestIOStreamThreadData *data)
+{
+ TestData *test_data = data->user_data;
+ guint stream_id, component_id;
+ gpointer tmp;
+
+ tmp = g_object_get_data (G_OBJECT (data->agent), "stream-id");
+ stream_id = GPOINTER_TO_UINT (tmp);
+ component_id = 1;
+
+ while (test_data->transmitted_bytes < test_data->n_bytes) {
+ GError *error = NULL;
+ NiceOutputMessage *messages;
+ guint n_messages;
+ gint n_sent_messages;
+
+ /* Generate a buffer to transmit. */
+ generate_messages_to_transmit (data, test_data->transmitted_bytes,
+ &messages, &n_messages);
+
+ /* Busy loop on receiving some data. */
+ do {
+ g_clear_error (&error);
+ n_sent_messages = nice_agent_send_messages_nonblocking (data->agent,
+ stream_id, component_id, messages, n_messages, NULL, &error);
+ } while (n_sent_messages == -1 &&
+ g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK));
+ g_assert_no_error (error);
+
+ /* Update the test’s buffer generation state machine. */
+ notify_transmitted_messages (data, test_data->transmitted_bytes, &messages,
+ n_messages, n_sent_messages);
+ }
+}
+
+/*
+ * Implementation using nice_agent_recv_nonblocking() and
+ * nice_agent_send_nonblocking().
+ */
+static void
+read_thread_agent_nonblocking_cb (GInputStream *input_stream,
+ TestIOStreamThreadData *data)
+{
+ TestData *test_data = data->user_data;
+ guint stream_id, component_id;
+ gpointer tmp;
+
+ tmp = g_object_get_data (G_OBJECT (data->agent), "stream-id");
+ stream_id = GPOINTER_TO_UINT (tmp);
+ component_id = 1;
+
+ while (test_data->received_bytes < test_data->n_bytes) {
+ GError *error = NULL;
+ NiceInputMessage *messages;
+ guint n_messages;
+ gint n_valid_messages;
+
+ /* Initialise an array of messages to receive into. */
+ generate_messages_to_receive (data, test_data->received_bytes, &messages,
+ &n_messages, test_data->n_bytes - test_data->received_bytes,
+ test_data->n_messages - test_data->received_messages);
+
+ /* Trim n_messages to avoid consuming the ‘done’ message. */
+ n_messages =
+ MIN (n_messages, test_data->n_messages - test_data->received_messages);
+
+ /* Busy loop on receiving some data. */
+ do {
+ g_clear_error (&error);
+ n_valid_messages = nice_agent_recv_messages_nonblocking (data->agent,
+ stream_id, component_id, messages, n_messages, NULL, &error);
+ } while (n_valid_messages == -1 &&
+ g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK));
+ g_assert_no_error (error);
+
+ /* Check the messages and update the test’s state machine. */
+ validate_received_messages (data, test_data->received_bytes, messages,
+ n_messages, n_valid_messages);
+ }
+
+ check_for_termination (data, &test_data->received_bytes,
+ test_data->other_received_bytes, &test_data->transmitted_bytes,
+ test_data->n_bytes);
+}
+
+static void
+wait_transmission_cb (NiceAgent *agent)
+{
+ guint stream_id;
+ gpointer tmp;
+ guint8 buffer[1024];
+ GInputVector v = { &buffer, sizeof (buffer) };
+ NiceInputMessage message = { &v, 1, NULL, 0};
+
+ tmp = g_object_get_data (G_OBJECT (agent), "stream-id");
+ stream_id = GPOINTER_TO_UINT (tmp);
+
+ /* While waiting for write thread to finish sending, keep also receiving so
+ * that any STUN messages from the peer still get processed. */
+ nice_agent_recv_messages_nonblocking (agent, stream_id, 1, &message, 1, NULL,
+ NULL);
+}
+
+static void
+write_thread_agent_nonblocking_cb (GOutputStream *output_stream,
+ TestIOStreamThreadData *data)
+{
+ /* FIXME: There is no nice_agent_send_nonblocking(); nice_agent_send() is
+ * non-blocking by default. */
+ write_thread_agent_cb (output_stream, data);
+}
+
+/*
+ * Implementation using NiceInputStream and NiceOutputStream.
+ */
+static void
+read_thread_gio_cb (GInputStream *input_stream, TestIOStreamThreadData *data)
+{
+ TestData *test_data = data->user_data;
+
+ while (test_data->received_bytes < test_data->n_bytes) {
+ GError *error = NULL;
+ guint8 *buf = NULL;
+ gsize buf_len = 0;
+ gssize len;
+
+ /* Initialise a receive buffer. */
+ generate_buffer_to_receive (data, test_data->received_bytes, &buf,
+ &buf_len);
+
+ /* Trim the receive buffer to avoid blocking on bytes which will never
+ * appear. */
+ buf_len = MIN (buf_len, test_data->n_bytes - test_data->received_bytes);
+
+ /* Block on receiving some data. */
+ len = g_input_stream_read (input_stream, buf, buf_len, NULL, &error);
+ g_assert_no_error (error);
+
+ /* Check the buffer and update the test’s state machine. */
+ validate_received_buffer (data, test_data->received_bytes, &buf, buf_len,
+ len);
+ }
+
+ check_for_termination (data, &test_data->received_bytes,
+ test_data->other_received_bytes, &test_data->transmitted_bytes,
+ test_data->n_bytes);
+}
+
+static void
+write_thread_gio_cb (GOutputStream *output_stream, TestIOStreamThreadData *data)
+{
+ TestData *test_data = data->user_data;
+
+ while (test_data->transmitted_bytes < test_data->n_bytes) {
+ GError *error = NULL;
+ guint8 *buf = NULL;
+ gsize buf_len = 0;
+ gssize len;
+ gsize total_len = 0;
+
+ /* Generate a buffer to transmit. */
+ generate_buffer_to_transmit (data, test_data->transmitted_bytes, &buf,
+ &buf_len);
+
+ /* Transmit it. */
+ do {
+ len = g_output_stream_write (output_stream, buf + total_len,
+ buf_len - total_len, NULL, &error);
+ g_assert_no_error (error);
+ total_len += len;
+ } while (total_len < buf_len);
+
+ /* Update the test’s buffer generation state machine. */
+ notify_transmitted_buffer (data, test_data->transmitted_bytes, &buf,
+ buf_len, total_len);
+ }
+}
+
+/*
+ * Implementation using GPollableInputStream and GPollableOutputStream.
+ *
+ * GSourceData is effectively the closure for the ‘for’ loop in other stream API
+ * implementations.
+ */
+typedef struct {
+ TestIOStreamThreadData *data;
+ GMainLoop *main_loop;
+} GSourceData;
+
+static gboolean
+read_stream_cb (GObject *pollable_stream, gpointer _user_data)
+{
+ GSourceData *gsource_data = _user_data;
+ TestIOStreamThreadData *data = gsource_data->data;
+ TestData *test_data = data->user_data;
+ GError *error = NULL;
+ guint8 *buf = NULL;
+ gsize buf_len = 0;
+ gssize len;
+
+ /* Initialise a receive buffer. */
+ generate_buffer_to_receive (data, test_data->received_bytes, &buf, &buf_len);
+
+ /* Trim the receive buffer to avoid consuming the ‘done’ message. */
+ buf_len = MIN (buf_len, test_data->n_bytes - test_data->received_bytes);
+
+ /* Try to receive some data. */
+ len = g_pollable_input_stream_read_nonblocking (
+ G_POLLABLE_INPUT_STREAM (pollable_stream), buf, buf_len, NULL, &error);
+
+ if (len == -1) {
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK);
+ g_error_free (error);
+ g_free (buf);
+ return G_SOURCE_CONTINUE;
+ }
+
+ g_assert_no_error (error);
+
+ /* Check the buffer and update the test’s state machine. */
+ validate_received_buffer (data, test_data->received_bytes, &buf, buf_len,
+ len);
+
+ /* Termination time? */
+ if (test_data->received_bytes == test_data->n_bytes) {
+ g_main_loop_quit (gsource_data->main_loop);
+ return G_SOURCE_REMOVE;
+ }
+
+ return G_SOURCE_CONTINUE;
+}
+
+static void
+read_thread_gsource_cb (GInputStream *input_stream,
+ TestIOStreamThreadData *data)
+{
+ TestData *test_data = data->user_data;
+ GSourceData gsource_data;
+ GMainContext *main_context;
+ GMainLoop *main_loop;
+ GSource *stream_source;
+
+ main_context = g_main_context_ref_thread_default ();
+ main_loop = g_main_loop_new (main_context, FALSE);
+
+ gsource_data.data = data;
+ gsource_data.main_loop = main_loop;
+
+ stream_source =
+ g_pollable_input_stream_create_source (
+ G_POLLABLE_INPUT_STREAM (input_stream), NULL);
+
+ g_source_set_callback (stream_source, G_SOURCE_FUNC (read_stream_cb),
+ &gsource_data, NULL);
+ g_source_attach (stream_source, main_context);
+
+ /* Run the main loop. */
+ g_main_loop_run (main_loop);
+
+ g_source_destroy (stream_source);
+ g_source_unref (stream_source);
+ g_main_loop_unref (main_loop);
+ g_main_context_unref (main_context);
+
+ /* Termination? */
+ check_for_termination (data, &test_data->received_bytes,
+ test_data->other_received_bytes, &test_data->transmitted_bytes,
+ test_data->n_bytes);
+}
+
+static gboolean
+write_stream_cb (GObject *pollable_stream, gpointer _user_data)
+{
+ GSourceData *gsource_data = _user_data;
+ TestIOStreamThreadData *data = gsource_data->data;
+ TestData *test_data = data->user_data;
+ GError *error = NULL;
+ guint8 *buf = NULL;
+ gsize buf_len = 0;
+ gssize len;
+
+ /* Initialise a receive buffer. */
+ generate_buffer_to_transmit (data, test_data->transmitted_bytes, &buf,
+ &buf_len);
+
+ /* Try to transmit some data. */
+ len = g_pollable_output_stream_write_nonblocking (
+ G_POLLABLE_OUTPUT_STREAM (pollable_stream), buf, buf_len, NULL, &error);
+
+ if (len == -1) {
+ g_assert_error (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK);
+ g_free (buf);
+ return G_SOURCE_CONTINUE;
+ }
+
+ g_assert_no_error (error);
+
+ /* Update the test’s buffer generation state machine. */
+ notify_transmitted_buffer (data, test_data->transmitted_bytes, &buf, buf_len,
+ len);
+
+ /* Termination time? */
+ if (test_data->transmitted_bytes == test_data->n_bytes) {
+ g_main_loop_quit (gsource_data->main_loop);
+ return G_SOURCE_REMOVE;
+ }
+
+ return G_SOURCE_CONTINUE;
+}
+
+static void
+write_thread_gsource_cb (GOutputStream *output_stream,
+ TestIOStreamThreadData *data)
+{
+ GSourceData gsource_data;
+ GMainContext *main_context;
+ GMainLoop *main_loop;
+ GSource *stream_source;
+
+ main_context = g_main_context_ref_thread_default ();
+ main_loop = g_main_loop_new (main_context, FALSE);
+
+ gsource_data.data = data;
+ gsource_data.main_loop = main_loop;
+
+ stream_source =
+ g_pollable_output_stream_create_source (
+ G_POLLABLE_OUTPUT_STREAM (output_stream), NULL);
+
+ g_source_set_callback (stream_source, G_SOURCE_FUNC (write_stream_cb),
+ &gsource_data, NULL);
+ g_source_attach (stream_source, main_context);
+
+ /* Run the main loop. */
+ g_main_loop_run (main_loop);
+
+ g_source_destroy (stream_source);
+ g_source_unref (stream_source);
+ g_main_loop_unref (main_loop);
+ g_main_context_unref (main_context);
+}
+
+static void
+test_data_init (TestData *data, gboolean reliable, StreamApi stream_api,
+ gsize n_bytes, guint n_messages,
+ BufferSizeStrategy transmit_buffer_size_strategy,
+ BufferCountStrategy transmit_buffer_count_strategy,
+ MessageCountStrategy transmit_message_count_strategy,
+ BufferSizeStrategy receive_buffer_size_strategy,
+ BufferCountStrategy receive_buffer_count_strategy,
+ MessageCountStrategy receive_message_count_strategy,
+ BufferDataStrategy buffer_data_strategy, guint32 transmit_seed,
+ guint32 receive_seed, gsize *other_received_bytes,
+ guint *other_received_messages)
+{
+ data->reliable = reliable;
+ data->stream_api = stream_api;
+ data->n_bytes = n_bytes;
+ data->n_messages = n_messages;
+ data->transmit.buffer_size_strategy = transmit_buffer_size_strategy;
+ data->transmit.buffer_count_strategy = transmit_buffer_count_strategy;
+ data->transmit.message_count_strategy = transmit_message_count_strategy;
+ data->receive.buffer_size_strategy = receive_buffer_size_strategy;
+ data->receive.buffer_count_strategy = receive_buffer_count_strategy;
+ data->receive.message_count_strategy = receive_message_count_strategy;
+ data->buffer_data_strategy = buffer_data_strategy;
+ data->transmit_size_rand = g_rand_new_with_seed (transmit_seed);
+ data->receive_size_rand = g_rand_new_with_seed (receive_seed);
+ data->transmitted_bytes = 0;
+ data->received_bytes = 0;
+ data->other_received_bytes = other_received_bytes;
+ data->transmitted_messages = 0;
+ data->received_messages = 0;
+ data->other_received_messages = other_received_messages;
+}
+
+/*
+ * Test closures.
+ */
+static void
+test_data_clear (TestData *data)
+{
+ g_rand_free (data->receive_size_rand);
+ g_rand_free (data->transmit_size_rand);
+}
+
+static void
+test (gboolean reliable, StreamApi stream_api, gsize n_bytes, guint n_messages,
+ BufferSizeStrategy transmit_buffer_size_strategy,
+ BufferCountStrategy transmit_buffer_count_strategy,
+ MessageCountStrategy transmit_message_count_strategy,
+ BufferSizeStrategy receive_buffer_size_strategy,
+ BufferCountStrategy receive_buffer_count_strategy,
+ MessageCountStrategy receive_message_count_strategy,
+ BufferDataStrategy buffer_data_strategy,
+ guint32 transmit_seed, guint32 receive_seed,
+ guint deadlock_timeout)
+{
+ TestData l_data, r_data;
+
+ /* Indexed by StreamApi. */
+ const TestIOStreamCallbacks callbacks[] = {
+ { read_thread_agent_cb,
+ write_thread_agent_cb, NULL, NULL, wait_transmission_cb }, /* STREAM_AGENT */
+ { read_thread_agent_nonblocking_cb, write_thread_agent_nonblocking_cb,
+ NULL, NULL, wait_transmission_cb }, /* STREAM_AGENT_NONBLOCKING */
+ { read_thread_gio_cb, write_thread_gio_cb, NULL, NULL, NULL}, /* STREAM_GIO */
+ { read_thread_gsource_cb, write_thread_gsource_cb,
+ NULL, NULL, NULL }, /* STREAM_GSOURCE */
+ };
+
+ test_data_init (&l_data, reliable, stream_api, n_bytes, n_messages,
+ transmit_buffer_size_strategy, transmit_buffer_count_strategy,
+ transmit_message_count_strategy, receive_buffer_size_strategy,
+ receive_buffer_count_strategy, receive_message_count_strategy,
+ buffer_data_strategy, transmit_seed, receive_seed,
+ &r_data.received_bytes, &r_data.received_messages);
+ test_data_init (&r_data, reliable, stream_api, n_bytes, n_messages,
+ transmit_buffer_size_strategy, transmit_buffer_count_strategy,
+ transmit_message_count_strategy, receive_buffer_size_strategy,
+ receive_buffer_count_strategy, receive_message_count_strategy,
+ buffer_data_strategy, transmit_seed, receive_seed,
+ &l_data.received_bytes, &l_data.received_messages);
+
+ run_io_stream_test (deadlock_timeout, reliable, &callbacks[stream_api],
+ &l_data, NULL, &r_data, NULL);
+
+ test_data_clear (&r_data);
+ test_data_clear (&l_data);
+}
+
+/* Options with default values. */
+guint32 option_transmit_seed = 0;
+guint32 option_receive_seed = 0;
+gsize option_n_bytes = 10000;
+guint option_n_messages = 50;
+guint option_timeout = 15; /* seconds */
+gboolean option_long_mode = FALSE;
+
+static GOptionEntry entries[] = {
+ { "transmit-seed", 0, 0, G_OPTION_ARG_INT, &option_transmit_seed,
+ "Seed for transmission RNG", "S" },
+ { "receive-seed", 0, 0, G_OPTION_ARG_INT, &option_receive_seed,
+ "Seed for reception RNG", "S" },
+ { "n-bytes", 'n', 0, G_OPTION_ARG_INT64, &option_n_bytes,
+ "Number of bytes to send in each test (default 10000)", "N" },
+ { "n-messages", 'm', 0, G_OPTION_ARG_INT64, &option_n_messages,
+ "Number of messages to send in each test (default 50)", "M" },
+ { "timeout", 't', 0, G_OPTION_ARG_INT, &option_timeout,
+ "Deadlock detection timeout length, in seconds (default: 15)", "S" },
+ { "long-mode", 'l', 0, G_OPTION_ARG_NONE, &option_long_mode,
+ "Enable all tests, rather than a fast subset", NULL },
+ { NULL },
+};
+
+int
+main (int argc, char *argv[])
+{
+ gboolean reliable;
+ StreamApi stream_api;
+ BufferSizeStrategy transmit_buffer_size_strategy;
+ BufferCountStrategy transmit_buffer_count_strategy;
+ MessageCountStrategy transmit_message_count_strategy;
+ BufferSizeStrategy receive_buffer_size_strategy;
+ BufferCountStrategy receive_buffer_count_strategy;
+ MessageCountStrategy receive_message_count_strategy;
+ BufferDataStrategy buffer_data_strategy;
+ guint32 transmit_seed;
+ guint32 receive_seed;
+ gsize n_bytes;
+ guint n_messages;
+ guint deadlock_timeout;
+ gboolean long_mode;
+ GOptionContext *context;
+ GError *error = NULL;
+
+ /* Argument parsing. Allow some of the test parameters to be specified on the
+ * command line. */
+ context = g_option_context_new ("— test send()/recv() correctness");
+ g_option_context_add_main_entries (context, entries, NULL);
+
+ if (!g_option_context_parse (context, &argc, &argv, &error)) {
+ g_printerr ("Option parsing failed: %s\n", error->message);
+ g_error_free (error);
+ g_option_context_free (context);
+ exit (1);
+ }
+
+ /* Set up the defaults. */
+ transmit_seed = option_transmit_seed;
+ receive_seed = option_receive_seed;
+ n_bytes = option_n_bytes;
+ n_messages = option_n_messages;
+ deadlock_timeout = option_timeout;
+ long_mode = option_long_mode;
+
+#ifdef G_OS_WIN32
+ WSADATA w;
+ WSAStartup (0x0202, &w);
+#endif
+
+ if (!long_mode) {
+ /* Quick mode. Just test each of the stream APIs in reliable and
+ * non-reliable mode, with a single pair of buffer strategies, and a single
+ * data strategy. */
+
+ /* Reliability. */
+ for (reliable = 0; reliable < 2; reliable++) {
+ /* Stream API. */
+ for (stream_api = 0;
+ (guint) stream_api < STREAM_API_N_ELEMENTS;
+ stream_api++) {
+ /* GIO streams must always be reliable. */
+ if (!reliable && stream_api_is_reliable_only (stream_api))
+ continue;
+
+ /* Non-reliable socket receives require large buffers. */
+ if (reliable) {
+ receive_buffer_size_strategy = BUFFER_SIZE_RANDOM;
+ } else {
+ receive_buffer_size_strategy = BUFFER_SIZE_CONSTANT_LARGE;
+ }
+
+ transmit_buffer_size_strategy = BUFFER_SIZE_RANDOM;
+ buffer_data_strategy = BUFFER_DATA_PSEUDO_RANDOM;
+
+ if (stream_api_supports_vectored_io (stream_api)) {
+ transmit_buffer_count_strategy = BUFFER_COUNT_RANDOM;
+ transmit_message_count_strategy = MESSAGE_COUNT_RANDOM;
+ receive_buffer_count_strategy = BUFFER_COUNT_RANDOM;
+ receive_message_count_strategy = MESSAGE_COUNT_RANDOM;
+ } else {
+ transmit_buffer_count_strategy = BUFFER_COUNT_CONSTANT_ONE;
+ transmit_message_count_strategy = MESSAGE_COUNT_CONSTANT_ONE;
+ receive_buffer_count_strategy = BUFFER_COUNT_CONSTANT_ONE;
+ receive_message_count_strategy = MESSAGE_COUNT_CONSTANT_ONE;
+ }
+
+ g_debug ("Running test (%u, %u, %" G_GSIZE_FORMAT ", %u, %u, "
+ "%u, %u, %u, %u)…",
+ reliable, stream_api, n_bytes, n_messages,
+ transmit_buffer_size_strategy,
+ receive_buffer_size_strategy, buffer_data_strategy,
+ transmit_seed, receive_seed);
+ test (reliable, stream_api, n_bytes, n_messages,
+ transmit_buffer_size_strategy,
+ transmit_buffer_count_strategy, transmit_message_count_strategy,
+ receive_buffer_size_strategy, receive_buffer_count_strategy,
+ receive_message_count_strategy, buffer_data_strategy,
+ transmit_seed, receive_seed,
+ deadlock_timeout);
+ }
+ }
+
+ goto done;
+ }
+
+#define STRATEGY_LOOP(V, L) for (V = 0; (guint) V < L##_N_ELEMENTS; V++)
+ STRATEGY_LOOP(transmit_buffer_size_strategy, BUFFER_SIZE_STRATEGY)
+ STRATEGY_LOOP(transmit_buffer_count_strategy, BUFFER_COUNT_STRATEGY)
+ STRATEGY_LOOP(transmit_message_count_strategy, MESSAGE_COUNT_STRATEGY)
+ STRATEGY_LOOP(receive_buffer_size_strategy, BUFFER_SIZE_STRATEGY)
+ STRATEGY_LOOP(receive_buffer_count_strategy, BUFFER_COUNT_STRATEGY)
+ STRATEGY_LOOP(receive_message_count_strategy, MESSAGE_COUNT_STRATEGY)
+ STRATEGY_LOOP(buffer_data_strategy, BUFFER_DATA_STRATEGY)
+ /* Reliability. */
+ for (reliable = 0; reliable < 2; reliable++) {
+ /* Stream API. */
+ for (stream_api = 0;
+ (guint) stream_api < STREAM_API_N_ELEMENTS;
+ stream_api++) {
+ /* GIO streams must always be reliable. */
+ if (!reliable && stream_api_is_reliable_only (stream_api))
+ continue;
+
+ /* Non-reliable socket receives require large buffers. We don’t claim to
+ * support using them with small (< 65536B) buffers, so don’t test
+ * them. */
+ if (!reliable &&
+ receive_buffer_size_strategy != BUFFER_SIZE_CONSTANT_LARGE)
+ continue;
+
+ /* Non-reliable socket transmits will always block with huge buffers. */
+ if (!reliable &&
+ transmit_buffer_size_strategy == BUFFER_SIZE_CONSTANT_LARGE)
+ continue;
+
+ /* Stream APIs which don’t support vectored I/O must not be passed
+ * I/O vectors. */
+ if (!stream_api_supports_vectored_io (stream_api) &&
+ (transmit_buffer_count_strategy != BUFFER_COUNT_CONSTANT_ONE ||
+ transmit_message_count_strategy != MESSAGE_COUNT_CONSTANT_ONE ||
+ receive_buffer_count_strategy != BUFFER_COUNT_CONSTANT_ONE ||
+ receive_message_count_strategy != MESSAGE_COUNT_CONSTANT_ONE))
+ continue;
+
+ g_debug ("Running test (%u, %u, %" G_GSIZE_FORMAT ", %u, %u, "
+ "%u, %u, %u, %u, %u, %u, %u, %u)…",
+ reliable, stream_api, n_bytes, n_messages,
+ transmit_buffer_size_strategy,
+ transmit_buffer_count_strategy, transmit_message_count_strategy,
+ receive_buffer_size_strategy, receive_buffer_count_strategy,
+ receive_message_count_strategy, buffer_data_strategy,
+ transmit_seed, receive_seed);
+ test (reliable, stream_api, n_bytes, n_messages,
+ transmit_buffer_size_strategy,
+ transmit_buffer_count_strategy, transmit_message_count_strategy,
+ receive_buffer_size_strategy, receive_buffer_count_strategy,
+ receive_message_count_strategy, buffer_data_strategy,
+ transmit_seed, receive_seed,
+ deadlock_timeout);
+ }
+ }
+
+done:
+ g_option_context_free (context);
+
+#ifdef G_OS_WIN32
+ WSACleanup ();
+#endif
+
+ return 0;
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2016 Jakub Adam <jakub.adam@ktknet.cz>
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <locale.h>
+#include <gio/gnetworking.h>
+
+#include "socket.h"
+
+static NiceSocket *udp_bsd;
+static NiceSocket *tcp_active;
+static NiceSocket *pseudossl;
+static NiceSocket *udp_turn_over_tcp;
+
+static void
+socket_base_udp_bsd (void)
+{
+ g_assert (nice_socket_is_based_on (udp_bsd, udp_bsd));
+ g_assert (!nice_socket_is_based_on (udp_bsd, tcp_active));
+ g_assert (!nice_socket_is_based_on (udp_bsd, pseudossl));
+ g_assert (!nice_socket_is_based_on (udp_bsd, udp_turn_over_tcp));
+}
+
+static void
+socket_base_tcp_active (void)
+{
+ g_assert (!nice_socket_is_based_on (tcp_active, udp_bsd));
+ g_assert (nice_socket_is_based_on (tcp_active, tcp_active));
+ g_assert (!nice_socket_is_based_on (tcp_active, pseudossl));
+ g_assert (!nice_socket_is_based_on (tcp_active, udp_turn_over_tcp));
+}
+
+static void
+socket_base_pseudossl (void)
+{
+ g_assert (!nice_socket_is_based_on (pseudossl, udp_bsd));
+ g_assert (nice_socket_is_based_on (pseudossl, tcp_active));
+ g_assert (nice_socket_is_based_on (pseudossl, pseudossl));
+ g_assert (!nice_socket_is_based_on (pseudossl, udp_turn_over_tcp));
+}
+
+static void
+socket_base_udp_turn_over_tcp (void)
+{
+ g_assert (!nice_socket_is_based_on (udp_turn_over_tcp, udp_bsd));
+ g_assert (nice_socket_is_based_on (udp_turn_over_tcp, tcp_active));
+ g_assert (nice_socket_is_based_on (udp_turn_over_tcp, pseudossl));
+ g_assert (nice_socket_is_based_on (udp_turn_over_tcp, udp_turn_over_tcp));
+}
+
+int
+main (int argc, char *argv[])
+{
+ GMainLoop *mainloop = NULL;
+
+ NiceAddress addr;
+
+ g_networking_init ();
+
+ setlocale (LC_ALL, "");
+ g_test_init (&argc, &argv, NULL);
+
+ mainloop = g_main_loop_new (NULL, TRUE);
+
+ nice_address_set_from_string (&addr, "127.0.0.1");
+
+ /* Standalone socket */
+ udp_bsd = nice_udp_bsd_socket_new (&addr);
+
+ /* tcp_passive -> pseudossl -> udp_turn_over_tcp */
+ tcp_active = nice_tcp_active_socket_new (g_main_loop_get_context (mainloop),
+ &addr);
+ pseudossl = nice_pseudossl_socket_new (tcp_active,
+ NICE_PSEUDOSSL_SOCKET_COMPATIBILITY_GOOGLE);
+ udp_turn_over_tcp = nice_udp_turn_over_tcp_socket_new (pseudossl,
+ NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE);
+
+ g_test_add_func ("/socket/is-base-of/udp-bsd",
+ socket_base_udp_bsd);
+ g_test_add_func ("/socket/is-base-of/tcp-active",
+ socket_base_tcp_active);
+ g_test_add_func ("/socket/is-base-of/pseudossl",
+ socket_base_pseudossl);
+ g_test_add_func ("/socket/is-base-of/udp-turn-over-tcp",
+ socket_base_udp_turn_over_tcp);
+
+ g_test_run ();
+
+ nice_socket_free (udp_bsd);
+ nice_socket_free (udp_turn_over_tcp);
+
+ g_main_loop_unref (mainloop);
+
+ return 0;
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2012 Collabora Ltd.
+ * Contact: George Kiagiadakis
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * George Kiagiadakis, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include <stdio.h>
+#include <gio/gnetworking.h>
+
+#include "socket.h"
+
+GMainLoop *mainloop = NULL;
+NiceSocket *active_sock, *client;
+NiceSocket *passive_sock, *server;
+NiceAddress tmp;
+gchar buf[5];
+
+static gboolean
+on_server_connection_available (gpointer user_data)
+{
+ server = nice_tcp_passive_socket_accept (passive_sock);
+ g_assert (server);
+ nice_socket_free (passive_sock);
+ passive_sock = NULL;
+
+ g_main_loop_quit (mainloop);
+
+ return FALSE;
+}
+
+static gboolean
+on_server_input_available (gpointer user_data)
+{
+ g_assert (5 == nice_socket_recv (server, &tmp, 5, buf));
+ g_assert (nice_address_equal (&tmp, &client->addr));
+
+ g_main_loop_quit (mainloop);
+
+ return FALSE;
+}
+
+static gboolean
+on_client_input_available (gpointer user_data)
+{
+ g_assert (5 == nice_socket_recv (client, &tmp, 5, buf));
+ g_assert (nice_address_equal (&tmp, &server->addr));
+
+ g_main_loop_quit (mainloop);
+
+ return FALSE;
+}
+
+int
+main (void)
+{
+ NiceAddress active_bind_addr, passive_bind_addr;
+ GSource *srv_listen_source, *srv_input_source, *cli_input_source;
+
+ g_networking_init ();
+
+ mainloop = g_main_loop_new (NULL, FALSE);
+
+ nice_address_init (&active_bind_addr);
+ g_assert (nice_address_set_from_string (&active_bind_addr, "::1"));
+
+ nice_address_init (&passive_bind_addr);
+ g_assert (nice_address_set_from_string (&passive_bind_addr, "127.0.0.1"));
+ nice_address_set_port (&passive_bind_addr, 0);
+
+ nice_address_init (&tmp);
+
+ passive_sock = nice_tcp_passive_socket_new (g_main_loop_get_context (mainloop),
+ &passive_bind_addr);
+ g_assert (passive_sock);
+
+ srv_listen_source = g_socket_create_source (passive_sock->fileno,
+ G_IO_IN, NULL);
+ g_source_set_callback (srv_listen_source,
+ on_server_connection_available, NULL, NULL);
+ g_source_attach (srv_listen_source, g_main_loop_get_context (mainloop));
+
+ active_sock = nice_tcp_active_socket_new (g_main_loop_get_context (mainloop),
+ &active_bind_addr);
+ g_assert (active_sock);
+
+ client = nice_tcp_active_socket_connect (active_sock, &passive_sock->addr);
+ g_assert (client);
+ nice_socket_free (active_sock);
+ active_sock = NULL;
+
+ g_main_loop_run (mainloop); /* -> on_server_connection_available */
+ g_assert (server);
+
+ srv_input_source = g_socket_create_source (server->fileno, G_IO_IN, NULL);
+ g_source_set_callback (srv_input_source,
+ on_server_input_available, NULL, NULL);
+ g_source_attach (srv_input_source, g_main_loop_get_context (mainloop));
+
+ cli_input_source = g_socket_create_source (client->fileno, G_IO_IN, NULL);
+ g_source_set_callback (cli_input_source,
+ on_client_input_available, NULL, NULL);
+ g_source_attach (cli_input_source, g_main_loop_get_context (mainloop));
+
+ g_assert (nice_address_get_port (&client->addr) != 0);
+
+ g_assert (nice_address_set_from_string (&tmp, "127.0.0.1"));
+ nice_address_set_port (&tmp, nice_address_get_port (&server->addr));
+ g_assert (nice_address_get_port (&tmp) != 0);
+
+
+ g_assert (5 == nice_socket_send (client, &tmp, 5, "hello"));
+ g_main_loop_run (mainloop); /* -> on_server_input_available */
+ g_assert (0 == strncmp (buf, "hello", 5));
+
+ g_assert (5 == nice_socket_send (server, &tmp, 5, "uryyb"));
+ g_main_loop_run (mainloop); /* -> on_client_input_available */
+ g_assert (0 == strncmp (buf, "uryyb", 5));
+
+ nice_socket_free (client);
+ nice_socket_free (server);
+
+ g_source_unref (srv_listen_source);
+ g_source_unref (srv_input_source);
+ g_source_unref (cli_input_source);
+ g_main_loop_unref (mainloop);
+
+ return 0;
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * Unit test for ICE full-mode related features.
+ *
+ * (C) 2007 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Kai Vehmanen, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "agent.h"
+
+#include <stdlib.h>
+#include <string.h>
+#ifndef G_OS_WIN32
+#include <unistd.h>
+#endif
+
+GMainLoop *error_loop;
+
+volatile gint global_lagent_cands = 0;
+volatile gint global_ragent_cands = 0;
+
+volatile gint global_lagent_buffers = 0;
+volatile gint global_ragent_buffers = 0;
+
+/* Waits about 10 seconds for @var to be NULL/FALSE */
+#define WAIT_UNTIL_UNSET(var, context) \
+ if (var) \
+ { \
+ int _i; \
+ \
+ for (_i = 0; _i < 13 && (var); _i++) \
+ { \
+ g_usleep (1000 * (1 << _i)); \
+ g_main_context_iteration (context, FALSE); \
+ } \
+ \
+ g_assert (!(var)); \
+ }
+
+static gboolean timer_cb (gpointer pointer)
+{
+ g_debug ("test-thread:%s: %p", G_STRFUNC, pointer);
+
+ /* note: should not be reached, abort */
+ g_debug ("ERROR: test has got stuck, aborting...");
+ exit (-1);
+
+}
+
+static gpointer
+mainloop_thread (gpointer data)
+{
+ GMainLoop *loop = data;
+
+ /* Synchronise thread starting. */
+ while (!g_main_loop_is_running (error_loop));
+
+ g_main_loop_run (loop);
+
+ return NULL;
+}
+
+
+static void
+cb_new_selected_pair(NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ gchar *lfoundation,
+ gchar* rfoundation,
+ gpointer data)
+{
+ g_debug ("test-thread:%s: %p", G_STRFUNC, data);
+
+ if (GPOINTER_TO_UINT (data) == 1)
+ g_atomic_int_inc (&global_lagent_cands);
+ else if (GPOINTER_TO_UINT (data) == 2)
+ g_atomic_int_inc (&global_ragent_cands);
+}
+
+
+static void cb_candidate_gathering_done(NiceAgent *agent, guint stream_id, gpointer data)
+{
+ NiceAgent *other = g_object_get_data (G_OBJECT (agent), "other-agent");
+ gchar *ufrag = NULL, *password = NULL;
+ GSList *cands, *i;
+ guint id, other_id;
+ gpointer tmp;
+
+ g_debug ("test-thread:%s", G_STRFUNC);
+
+ tmp = g_object_get_data (G_OBJECT (agent), "id");
+ id = GPOINTER_TO_UINT (tmp);
+ tmp = g_object_get_data (G_OBJECT (other), "id");
+ other_id = GPOINTER_TO_UINT (tmp);
+
+ nice_agent_get_local_credentials(agent, id, &ufrag, &password);
+ nice_agent_set_remote_credentials (other,
+ other_id, ufrag, password);
+ g_free (ufrag);
+ g_free (password);
+
+ cands = nice_agent_get_local_candidates(agent, id, 1);
+ g_assert (cands != NULL);
+
+ nice_agent_set_remote_candidates (other, other_id, 1, cands);
+
+ for (i = cands; i; i = i->next)
+ nice_candidate_free ((NiceCandidate *) i->data);
+ g_slist_free (cands);
+}
+
+
+
+static void cb_nice_recv (NiceAgent *agent, guint stream_id, guint component_id, guint len, gchar *buf, gpointer user_data)
+{
+ gchar data[10];
+ volatile gint *count = NULL;
+ gint count_val;
+
+ if (GPOINTER_TO_UINT (user_data) == 1)
+ count = &global_lagent_buffers;
+ else if (GPOINTER_TO_UINT (user_data) == 2)
+ count = &global_ragent_buffers;
+ else
+ g_error ("Invalid agent ?");
+
+ count_val = g_atomic_int_get (count);
+ if (count_val == 10)
+ return;
+
+ g_assert (len == 10);
+
+ memset (data, count_val + '1', 10);
+
+ g_assert (memcmp (buf, data, 10) == 0);
+
+ g_atomic_int_inc (count);
+
+ if (g_atomic_int_get (&global_ragent_buffers) == 10 &&
+ g_atomic_int_get (&global_lagent_buffers) == 10)
+ g_main_loop_quit (error_loop);
+}
+
+
+static void cb_component_state_changed (NiceAgent *agent,
+ guint stream_id,
+ guint component_id,
+ guint state,
+ gpointer user_data)
+{
+ int i;
+ gchar data[10];
+
+ if (state != NICE_COMPONENT_STATE_READY)
+ return;
+
+ for (i=0; i<10; i++)
+ {
+ memset (data, i+'1', 10);
+
+ nice_agent_send (agent, stream_id, component_id, 10, data);
+ }
+}
+
+int main (void)
+{
+ NiceAgent *lagent, *ragent; /* agent's L and R */
+ NiceAddress baseaddr;
+ const char *stun_server = NULL, *stun_server_port = NULL;
+ GMainContext *lmainctx, *rmainctx;
+ GMainLoop *lmainloop, *rmainloop;
+ GThread *lthread, *rthread;
+ guint ls_id, rs_id;
+ GMainContext *ldmainctx, *rdmainctx;
+ GMainLoop *ldmainloop, *rdmainloop;
+ GThread *ldthread, *rdthread;
+
+#ifdef G_OS_WIN32
+ WSADATA w;
+ WSAStartup(0x0202, &w);
+#endif
+
+ lmainctx = g_main_context_new ();
+ rmainctx = g_main_context_new ();
+ lmainloop = g_main_loop_new (lmainctx, FALSE);
+ rmainloop = g_main_loop_new (rmainctx, FALSE);
+
+ ldmainctx = g_main_context_new ();
+ rdmainctx = g_main_context_new ();
+ ldmainloop = g_main_loop_new (ldmainctx, FALSE);
+ rdmainloop = g_main_loop_new (rdmainctx, FALSE);
+
+ error_loop = g_main_loop_new (NULL, FALSE);
+
+
+ /* step: create the agents L and R */
+ lagent = nice_agent_new (lmainctx, NICE_COMPATIBILITY_MSN);
+ ragent = nice_agent_new (rmainctx, NICE_COMPATIBILITY_MSN);
+
+ g_object_set_data (G_OBJECT (lagent), "other-agent", ragent);
+ g_object_set_data (G_OBJECT (ragent), "other-agent", lagent);
+
+ g_object_set (G_OBJECT (lagent), "controlling-mode", TRUE, NULL);
+ g_object_set (G_OBJECT (ragent), "controlling-mode", FALSE, NULL);
+ g_object_set (G_OBJECT (lagent), "upnp", FALSE, NULL);
+ g_object_set (G_OBJECT (ragent), "upnp", FALSE, NULL);
+
+ /* step: add a timer to catch state changes triggered by signals */
+ g_timeout_add (30000, timer_cb, NULL);
+
+ /* step: specify which local interface to use */
+ if (!nice_address_set_from_string (&baseaddr, "127.0.0.1"))
+ g_assert_not_reached ();
+ nice_agent_add_local_address (lagent, &baseaddr);
+ nice_agent_add_local_address (ragent, &baseaddr);
+
+ g_signal_connect (G_OBJECT (lagent), "candidate-gathering-done",
+ G_CALLBACK (cb_candidate_gathering_done), GUINT_TO_POINTER(1));
+ g_signal_connect (G_OBJECT (ragent), "candidate-gathering-done",
+ G_CALLBACK (cb_candidate_gathering_done), GUINT_TO_POINTER(2));
+ g_signal_connect (G_OBJECT (lagent), "component-state-changed",
+ G_CALLBACK (cb_component_state_changed), GUINT_TO_POINTER(1));
+ g_signal_connect (G_OBJECT (ragent), "component-state-changed",
+ G_CALLBACK (cb_component_state_changed), GUINT_TO_POINTER(2));
+ g_signal_connect (G_OBJECT (lagent), "new-selected-pair",
+ G_CALLBACK (cb_new_selected_pair), GUINT_TO_POINTER(1));
+ g_signal_connect (G_OBJECT (ragent), "new-selected-pair",
+ G_CALLBACK (cb_new_selected_pair), GUINT_TO_POINTER(2));
+
+ stun_server = getenv ("NICE_STUN_SERVER");
+ stun_server_port = getenv ("NICE_STUN_SERVER_PORT");
+ if (stun_server) {
+ g_object_set (G_OBJECT (lagent), "stun-server", stun_server, NULL);
+ g_object_set (G_OBJECT (lagent), "stun-server-port", atoi (stun_server_port), NULL);
+ g_object_set (G_OBJECT (ragent), "stun-server", stun_server, NULL);
+ g_object_set (G_OBJECT (ragent), "stun-server-port", atoi (stun_server_port), NULL);
+ }
+
+ /* step: test setter/getter functions for properties */
+ {
+ guint max_checks = 0;
+ gchar *string = NULL;
+ guint port = 0;
+ gboolean mode = FALSE;
+ g_object_get (G_OBJECT (lagent), "stun-server", &string, NULL);
+ g_assert (stun_server == NULL || strcmp (string, stun_server) == 0);
+ g_free (string);
+ g_object_get (G_OBJECT (lagent), "stun-server-port", &port, NULL);
+ g_assert (stun_server_port == NULL || port == (guint)atoi (stun_server_port));
+ g_object_get (G_OBJECT (lagent), "controlling-mode", &mode, NULL);
+ g_assert (mode == TRUE);
+ g_object_set (G_OBJECT (lagent), "max-connectivity-checks", 300, NULL);
+ g_object_get (G_OBJECT (lagent), "max-connectivity-checks", &max_checks, NULL);
+ g_assert (max_checks == 300);
+ }
+
+ /* step: run test the first time */
+ g_debug ("test-thread: TEST STARTS / running test for the 1st time");
+
+ lthread = g_thread_new ("lthread libnice", mainloop_thread, lmainloop);
+ rthread = g_thread_new ("rthread libnice", mainloop_thread, rmainloop);
+
+ g_assert (lthread);
+ g_assert (rthread);
+
+ ls_id = nice_agent_add_stream (lagent, 2);
+ rs_id = nice_agent_add_stream (ragent, 2);
+ g_assert (ls_id > 0);
+ g_assert (rs_id > 0);
+
+ g_object_set_data (G_OBJECT (lagent), "id", GUINT_TO_POINTER (ls_id));
+ g_object_set_data (G_OBJECT (ragent), "id", GUINT_TO_POINTER (rs_id));
+
+ nice_agent_gather_candidates (lagent, ls_id);
+ nice_agent_gather_candidates (ragent, rs_id);
+
+ nice_agent_attach_recv (lagent, ls_id, 1, ldmainctx, cb_nice_recv,
+ GUINT_TO_POINTER (1));
+ nice_agent_attach_recv (ragent, rs_id, 1, rdmainctx, cb_nice_recv,
+ GUINT_TO_POINTER (2));
+
+ ldthread = g_thread_new ("ldthread libnice", mainloop_thread, ldmainloop);
+ rdthread = g_thread_new ("rdthread libnice", mainloop_thread, rdmainloop);
+
+ g_assert (ldthread);
+ g_assert (rdthread);
+
+ /* Run loop for error timer */
+ g_main_loop_run (error_loop);
+
+ while (!g_main_loop_is_running (ldmainloop));
+ while (g_main_loop_is_running (ldmainloop))
+ g_main_loop_quit (ldmainloop);
+ while (!g_main_loop_is_running (rdmainloop));
+ while (g_main_loop_is_running (rdmainloop))
+ g_main_loop_quit (rdmainloop);
+ while (!g_main_loop_is_running (lmainloop));
+ while (g_main_loop_is_running (lmainloop))
+ g_main_loop_quit (lmainloop);
+ while (!g_main_loop_is_running (rmainloop));
+ while (g_main_loop_is_running (rmainloop))
+ g_main_loop_quit (rmainloop);
+
+ g_thread_join (ldthread);
+ g_thread_join (rdthread);
+ g_thread_join (lthread);
+ g_thread_join (rthread);
+
+ /* note: verify that correct number of local candidates were reported */
+ g_assert (g_atomic_int_get (&global_lagent_cands) == 1);
+ g_assert (g_atomic_int_get (&global_ragent_cands) == 1);
+
+ g_object_add_weak_pointer (G_OBJECT (lagent), (gpointer *) &lagent);
+ g_object_add_weak_pointer (G_OBJECT (ragent), (gpointer *) &ragent);
+
+ g_object_unref (lagent);
+ g_object_unref (ragent);
+
+ WAIT_UNTIL_UNSET (lagent, lmainctx);
+ WAIT_UNTIL_UNSET (ragent, rmainctx);
+
+ g_main_loop_unref (lmainloop);
+ g_main_loop_unref (rmainloop);
+ g_main_loop_unref (ldmainloop);
+ g_main_loop_unref (rdmainloop);
+
+ g_main_loop_unref (error_loop);
+#ifdef G_OS_WIN32
+ WSACleanup();
+#endif
+ return 0;
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * Unit test for ICE in trickle mode (adding remote candidates while the
+ * machine is running).
+ *
+ * (C) 2007 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Kai Vehmanen, Nokia
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "agent.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+
+static NiceComponentState global_lagent_state = NICE_COMPONENT_STATE_LAST;
+static NiceComponentState global_ragent_state = NICE_COMPONENT_STATE_LAST;
+static guint global_components_ready = 0;
+static guint global_components_ready_exit = 0;
+static guint global_components_failed = 0;
+static guint global_components_failed_exit = 0;
+static GMainLoop *global_mainloop = NULL;
+static gboolean global_lagent_gathering_done = FALSE;
+static gboolean global_ragent_gathering_done = FALSE;
+static gboolean global_lagent_ibr_received = FALSE;
+static gboolean global_ragent_ibr_received = FALSE;
+static int global_lagent_cands = 0;
+static int global_ragent_cands = 0;
+static gint global_ragent_read = 0;
+
+static void priv_print_global_status (void)
+{
+ g_debug ("\tgathering_done=%d", global_lagent_gathering_done && global_ragent_gathering_done);
+ g_debug ("\tlstate=%d", global_lagent_state);
+ g_debug ("\trstate=%d", global_ragent_state);
+ g_debug ("\tL cands=%d R cands=%d", global_lagent_cands, global_ragent_cands);
+}
+
+static gboolean timer_cb (gpointer pointer)
+{
+ g_debug ("test-trickle:%s: %p", G_STRFUNC, pointer);
+
+ /* signal status via a global variable */
+
+ /* note: should not be reached, abort */
+ g_error ("ERROR: test has got stuck, aborting...");
+
+ return FALSE;
+}
+
+static gboolean quit_loop_cb (gpointer pointer)
+{
+ g_debug ("test-trickle:%s: %p", G_STRFUNC, pointer);
+
+ g_main_loop_quit (global_mainloop);
+ return FALSE;
+}
+
+static void cb_nice_recv (NiceAgent *agent, guint stream_id, guint component_id, guint len, gchar *buf, gpointer user_data)
+{
+ g_debug ("test-trickle:%s: %p", G_STRFUNC, user_data);
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent; (void)stream_id; (void)component_id; (void)buf;
+
+ /*
+ * Lets ignore stun packets that got through
+ */
+ if (len < 8)
+ return;
+ if (strncmp ("12345678", buf, 8))
+ return;
+
+ if (GPOINTER_TO_UINT (user_data) == 2) {
+ global_ragent_read = len;
+ g_main_loop_quit (global_mainloop);
+ }
+}
+
+static void cb_candidate_gathering_done(NiceAgent *agent, guint stream_id, gpointer data)
+{
+ g_debug ("test-trickle:%s: %p", G_STRFUNC, data);
+
+ if (GPOINTER_TO_UINT (data) == 1)
+ global_lagent_gathering_done = TRUE;
+ else if (GPOINTER_TO_UINT (data) == 2)
+ global_ragent_gathering_done = TRUE;
+
+ if (global_lagent_gathering_done &&
+ global_ragent_gathering_done)
+ g_main_loop_quit (global_mainloop);
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent;
+}
+
+static void cb_component_state_changed (NiceAgent *agent, guint stream_id, guint component_id, guint state, gpointer data)
+{
+ gboolean ready_to_connected = FALSE;
+ g_debug ("test-trickle:%s: %p", G_STRFUNC, data);
+
+ if (GPOINTER_TO_UINT (data) == 1) {
+ if (global_lagent_state == NICE_COMPONENT_STATE_READY &&
+ state == NICE_COMPONENT_STATE_CONNECTED)
+ ready_to_connected = TRUE;
+ global_lagent_state = state;
+ } else if (GPOINTER_TO_UINT (data) == 2) {
+ if (global_ragent_state == NICE_COMPONENT_STATE_READY &&
+ state == NICE_COMPONENT_STATE_CONNECTED)
+ ready_to_connected = TRUE;
+ global_ragent_state = state;
+ }
+
+ if (state == NICE_COMPONENT_STATE_READY)
+ global_components_ready++;
+ else if (state == NICE_COMPONENT_STATE_CONNECTED && ready_to_connected)
+ global_components_ready--;
+ if (state == NICE_COMPONENT_STATE_FAILED)
+ global_components_failed++;
+
+ g_debug ("test-trickle: checks READY/EXIT-AT %u/%u.", global_components_ready, global_components_ready_exit);
+ g_debug ("test-trickle: checks FAILED/EXIT-AT %u/%u.", global_components_failed, global_components_failed_exit);
+
+ /* signal status via a global variable */
+ if (global_components_ready == global_components_ready_exit &&
+ global_components_failed == global_components_failed_exit) {
+ g_main_loop_quit (global_mainloop);
+ return;
+ }
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent; (void)stream_id; (void)data; (void)component_id;
+}
+
+static void cb_new_selected_pair(NiceAgent *agent, guint stream_id, guint component_id,
+ gchar *lfoundation, gchar* rfoundation, gpointer data)
+{
+ g_debug ("test-trickle:%s: %p", G_STRFUNC, data);
+
+ if (GPOINTER_TO_UINT (data) == 1)
+ ++global_lagent_cands;
+ else if (GPOINTER_TO_UINT (data) == 2)
+ ++global_ragent_cands;
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent; (void)stream_id; (void)component_id; (void)lfoundation; (void)rfoundation;
+}
+
+static void cb_new_candidate(NiceAgent *agent, guint stream_id, guint component_id,
+ gchar *foundation, gpointer data)
+{
+ g_debug ("test-trickle:%s: %p", G_STRFUNC, data);
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent; (void)stream_id; (void)data; (void)component_id; (void)foundation;
+}
+
+static void cb_initial_binding_request_received(NiceAgent *agent, guint stream_id, gpointer data)
+{
+ g_debug ("test-trickle:%s: %p", G_STRFUNC, data);
+
+ if (GPOINTER_TO_UINT (data) == 1)
+ global_lagent_ibr_received = TRUE;
+ else if (GPOINTER_TO_UINT (data) == 2)
+ global_ragent_ibr_received = TRUE;
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent; (void)stream_id; (void)data;
+}
+
+
+int main (void)
+{
+ NiceAgent *lagent, *ragent; /* agent's L and R */
+ NiceAddress baseaddr;
+ guint timer_id;
+ GSList *cands, *i;
+ guint ls_id, rs_id;
+
+#ifdef G_OS_WIN32
+ WSADATA w;
+
+ WSAStartup(0x0202, &w);
+#endif
+
+ global_mainloop = g_main_loop_new (NULL, FALSE);
+
+ /* step: create the agents L and R */
+ lagent = nice_agent_new (g_main_loop_get_context (global_mainloop),
+ NICE_COMPATIBILITY_GOOGLE);
+ ragent = nice_agent_new (g_main_loop_get_context (global_mainloop),
+ NICE_COMPATIBILITY_GOOGLE);
+
+ if (!nice_address_set_from_string (&baseaddr, "127.0.0.1"))
+ g_assert_not_reached ();
+ nice_agent_add_local_address (lagent, &baseaddr);
+ nice_agent_add_local_address (ragent, &baseaddr);
+
+ /* step: add a timer to catch state changes triggered by signals */
+ timer_id = g_timeout_add (30000, timer_cb, NULL);
+
+ g_signal_connect (G_OBJECT (lagent), "candidate-gathering-done",
+ G_CALLBACK (cb_candidate_gathering_done), GUINT_TO_POINTER(1));
+ g_signal_connect (G_OBJECT (ragent), "candidate-gathering-done",
+ G_CALLBACK (cb_candidate_gathering_done), GUINT_TO_POINTER (2));
+ g_signal_connect (G_OBJECT (lagent), "component-state-changed",
+ G_CALLBACK (cb_component_state_changed), GUINT_TO_POINTER (1));
+ g_signal_connect (G_OBJECT (ragent), "component-state-changed",
+ G_CALLBACK (cb_component_state_changed), GUINT_TO_POINTER (2));
+ g_signal_connect (G_OBJECT (lagent), "new-selected-pair",
+ G_CALLBACK (cb_new_selected_pair), GUINT_TO_POINTER(1));
+ g_signal_connect (G_OBJECT (ragent), "new-selected-pair",
+ G_CALLBACK (cb_new_selected_pair), GUINT_TO_POINTER (2));
+ g_signal_connect (G_OBJECT (lagent), "new-candidate",
+ G_CALLBACK (cb_new_candidate), GUINT_TO_POINTER (1));
+ g_signal_connect (G_OBJECT (ragent), "new-candidate",
+ G_CALLBACK (cb_new_candidate), GUINT_TO_POINTER (2));
+ g_signal_connect (G_OBJECT (lagent), "initial-binding-request-received",
+ G_CALLBACK (cb_initial_binding_request_received),
+ GUINT_TO_POINTER (1));
+ g_signal_connect (G_OBJECT (ragent), "initial-binding-request-received",
+ G_CALLBACK (cb_initial_binding_request_received),
+ GUINT_TO_POINTER (2));
+
+ /* step: run test */
+ g_debug ("test-trickle: running test");
+
+ /* step: initialize variables modified by the callbacks */
+ global_components_ready = 0;
+ global_components_ready_exit = 2;
+ global_components_failed = 0;
+ global_components_failed_exit = 0;
+ global_lagent_gathering_done = FALSE;
+ global_ragent_gathering_done = FALSE;
+ global_lagent_ibr_received =
+ global_ragent_ibr_received = FALSE;
+ global_lagent_cands =
+ global_ragent_cands = 0;
+
+ g_object_set (G_OBJECT (lagent), "controlling-mode", TRUE, NULL);
+ g_object_set (G_OBJECT (ragent), "controlling-mode", FALSE, NULL);
+
+ g_object_set (G_OBJECT (lagent), "ice-trickle", TRUE, NULL);
+ g_object_set (G_OBJECT (ragent), "ice-trickle", TRUE, NULL);
+
+ /* An application using more than one NiceAgent instance may crash due to
+ * a race in gUPnP.
+ *
+ * UPnP can be re-enabled here and in other libnice tests once gUPnP
+ * 1.1.2 / 1.0.4 is released.
+ *
+ * See https://gitlab.gnome.org/GNOME/gupnp/commit/0123e574595e0a547ce26422633df72d63d3d0e0
+ */
+ g_object_set (G_OBJECT (lagent), "upnp", FALSE, NULL);
+ g_object_set (G_OBJECT (ragent), "upnp", FALSE, NULL);
+
+ /* step: add one stream, with RTP+RTCP components, to each agent */
+ ls_id = nice_agent_add_stream (lagent, 1);
+
+ rs_id = nice_agent_add_stream (ragent, 1);
+ g_assert (ls_id > 0);
+ g_assert (rs_id > 0);
+
+
+ nice_agent_gather_candidates (lagent, ls_id);
+ nice_agent_gather_candidates (ragent, rs_id);
+
+ /* step: attach to mainloop (needed to register the fds) */
+ nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv,
+ GUINT_TO_POINTER (1));
+ nice_agent_attach_recv (ragent, rs_id, NICE_COMPONENT_TYPE_RTP,
+ g_main_loop_get_context (global_mainloop), cb_nice_recv,
+ GUINT_TO_POINTER (2));
+
+ /* step: run mainloop until local candidates are ready
+ * (see timer_cb() above) */
+ if (global_lagent_gathering_done != TRUE ||
+ global_ragent_gathering_done != TRUE) {
+ g_debug ("test-trickle: Added streams, running mainloop until 'candidate-gathering-done'...");
+ g_main_loop_run (global_mainloop);
+ g_assert (global_lagent_gathering_done == TRUE);
+ g_assert (global_ragent_gathering_done == TRUE);
+ }
+
+ {
+ gchar *ufrag = NULL, *password = NULL;
+ nice_agent_get_local_credentials(lagent, ls_id, &ufrag, &password);
+ nice_agent_set_remote_credentials (ragent,
+ rs_id, ufrag, password);
+ g_free (ufrag);
+ g_free (password);
+ nice_agent_get_local_credentials(ragent, rs_id, &ufrag, &password);
+ nice_agent_set_remote_credentials (lagent,
+ ls_id, ufrag, password);
+ g_free (ufrag);
+ g_free (password);
+ }
+ cands = nice_agent_get_local_candidates (ragent, rs_id, NICE_COMPONENT_TYPE_RTP);
+ nice_agent_set_remote_candidates (lagent, ls_id, NICE_COMPONENT_TYPE_RTP, cands);
+ for (i = cands; i; i = i->next)
+ nice_candidate_free ((NiceCandidate *) i->data);
+ g_slist_free (cands);
+ cands = nice_agent_get_local_candidates (lagent, ls_id, NICE_COMPONENT_TYPE_RTP);
+ nice_agent_set_remote_candidates (ragent, rs_id, NICE_COMPONENT_TYPE_RTP, cands);
+ for (i = cands; i; i = i->next)
+ nice_candidate_free ((NiceCandidate *) i->data);
+ g_slist_free (cands);
+
+ nice_agent_peer_candidate_gathering_done (lagent, ls_id);
+ nice_agent_peer_candidate_gathering_done (ragent, rs_id);
+
+ g_debug ("test-trickle: Set properties, next running mainloop until connectivity checks succeed...");
+
+ /* step: run the mainloop until connectivity checks succeed
+ * (see timer_cb() above) */
+ g_main_loop_run (global_mainloop);
+
+ /* note: verify that STUN binding requests were sent */
+ g_assert (global_lagent_ibr_received == TRUE);
+ g_assert (global_ragent_ibr_received == TRUE);
+
+ g_assert (global_lagent_state == NICE_COMPONENT_STATE_READY);
+ g_assert (global_ragent_state == NICE_COMPONENT_STATE_READY);
+ /* note: verify that correct number of local candidates were reported */
+ g_assert (global_lagent_cands == 1);
+ g_assert (global_ragent_cands == 1);
+
+ g_debug ("test-trickle: agents are ready.. now adding new buggy candidate");
+
+ g_timeout_add (500, quit_loop_cb, NULL);
+ g_main_loop_run (global_mainloop);
+
+ //global_components_ready--;
+
+ cands = nice_agent_get_local_candidates (ragent, rs_id, NICE_COMPONENT_TYPE_RTP);
+ nice_address_set_port(&((NiceCandidate *) cands->data)->addr, 80);
+ nice_agent_set_remote_candidates (lagent, ls_id, NICE_COMPONENT_TYPE_RTP, cands);
+ for (i = cands; i; i = i->next)
+ nice_candidate_free ((NiceCandidate *) i->data);
+ g_slist_free (cands);
+
+ g_assert (global_lagent_state == NICE_COMPONENT_STATE_CONNECTED);
+ g_main_loop_run (global_mainloop);
+ g_assert (global_lagent_state == NICE_COMPONENT_STATE_READY);
+
+ /*
+ g_debug ("test-trickle: buggy candidate worked, testing lower priority cand");
+
+ cands = nice_agent_get_local_candidates (ragent, rs_id, NICE_COMPONENT_TYPE_RTP);
+ nice_address_set_port(&((NiceCandidate *) cands->data)->addr, 80);
+ ((NiceCandidate *) cands->data)->priority -= 100;
+ nice_agent_set_remote_candidates (lagent, ls_id, NICE_COMPONENT_TYPE_RTP, cands);
+ for (i = cands; i; i = i->next)
+ nice_candidate_free ((NiceCandidate *) i->data);
+ g_slist_free (cands);
+
+ g_assert (global_lagent_state == NICE_COMPONENT_STATE_READY);*/
+
+ /* note: test payload send and receive */
+ global_ragent_read = 0;
+ g_assert (nice_agent_send (lagent, ls_id, 1, 16, "1234567812345678") == 16);
+ g_main_loop_run (global_mainloop);
+ g_assert (global_ragent_read == 16);
+
+ g_debug ("test-trickle: Ran mainloop, removing streams...");
+
+ /* step: clean up resources and exit */
+
+ nice_agent_remove_stream (lagent, ls_id);
+ nice_agent_remove_stream (ragent, rs_id);
+ priv_print_global_status ();
+ g_assert (global_lagent_state == NICE_COMPONENT_STATE_READY);
+ g_assert (global_ragent_state >= NICE_COMPONENT_STATE_CONNECTED);
+ /* note: verify that correct number of local candidates were reported */
+ g_assert (global_lagent_cands == 1);
+ g_assert (global_ragent_cands == 1);
+
+
+ g_object_unref (lagent);
+ g_object_unref (ragent);
+
+ g_main_loop_unref (global_mainloop);
+ global_mainloop = NULL;
+
+ g_source_remove (timer_id);
+
+#ifdef G_OS_WIN32
+ WSACleanup();
+#endif
+ return 0;
+}
--- /dev/null
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <gio/gio.h>
+#include <agent.h>
+
+static NiceComponentState global_lagent_state[2] = { NICE_COMPONENT_STATE_LAST, NICE_COMPONENT_STATE_LAST };
+static NiceComponentState global_ragent_state[2] = { NICE_COMPONENT_STATE_LAST, NICE_COMPONENT_STATE_LAST };
+static guint global_components_ready = 0;
+static gboolean global_lagent_gathering_done = FALSE;
+static gboolean global_ragent_gathering_done = FALSE;
+static int global_lagent_cands = 0;
+static int global_ragent_cands = 0;
+
+#define TURN_USER "toto"
+#define TURN_PASS "password"
+
+static gboolean timer_cb (gpointer pointer)
+{
+ g_debug ("test-turn:%s: %p", G_STRFUNC, pointer);
+
+ /* signal status via a global variable */
+
+ /* note: should not be reached, abort */
+ g_error ("ERROR: test has got stuck, aborting...");
+
+ return FALSE;
+}
+
+static void cb_nice_recv (NiceAgent *agent, guint stream_id, guint component_id, guint len, gchar *buf, gpointer user_data)
+{
+ g_debug ("test-fullmode:%s: %p", G_STRFUNC, user_data);
+
+ /* XXX: dear compiler, these are for you: */
+ (void)agent; (void)stream_id; (void)component_id; (void)buf;
+
+ /*
+ * Lets ignore stun packets that got through
+ */
+ if (len < 8)
+ return;
+ if (strncmp ("12345678", buf, 8))
+ return;
+
+ if (component_id != 1)
+ return;
+
+#if 0
+ if (GPOINTER_TO_UINT (user_data) == 2) {
+ global_ragent_read += len;
+ }
+#endif
+}
+
+static void cb_candidate_gathering_done(NiceAgent *agent, guint stream_id, gpointer data)
+{
+ g_debug ("test-fullmode:%s: %p", G_STRFUNC, data);
+
+ if (GPOINTER_TO_UINT (data) == 1)
+ global_lagent_gathering_done = TRUE;
+ else if (GPOINTER_TO_UINT (data) == 2)
+ global_ragent_gathering_done = TRUE;
+}
+
+
+static void cb_component_state_changed (NiceAgent *agent, guint stream_id, guint component_id, guint state, gpointer data)
+{
+ gboolean ready_to_connected = FALSE;
+ g_debug ("test-fullmode:%s: %p", G_STRFUNC, data);
+
+ if (GPOINTER_TO_UINT (data) == 1) {
+ if (global_lagent_state[component_id - 1] == NICE_COMPONENT_STATE_READY &&
+ state == NICE_COMPONENT_STATE_CONNECTED)
+ ready_to_connected = TRUE;
+ global_lagent_state[component_id - 1] = state;
+ } else if (GPOINTER_TO_UINT (data) == 2) {
+ if (global_ragent_state[component_id - 1] == NICE_COMPONENT_STATE_READY &&
+ state == NICE_COMPONENT_STATE_CONNECTED)
+ ready_to_connected = TRUE;
+ global_ragent_state[component_id - 1] = state;
+ }
+
+ if (state == NICE_COMPONENT_STATE_READY)
+ global_components_ready++;
+ else if (state == NICE_COMPONENT_STATE_CONNECTED && ready_to_connected)
+ global_components_ready--;
+ g_assert (state != NICE_COMPONENT_STATE_FAILED);
+
+ g_debug ("test-turn: checks READY %u.", global_components_ready);
+}
+
+static void cb_new_selected_pair(NiceAgent *agent, guint stream_id,
+ guint component_id, gchar *lfoundation, gchar* rfoundation, gpointer data)
+{
+ g_debug ("test-turn:%s: %p", G_STRFUNC, data);
+
+ if (GPOINTER_TO_UINT (data) == 1)
+ ++global_lagent_cands;
+ else if (GPOINTER_TO_UINT (data) == 2)
+ ++global_ragent_cands;
+}
+
+static void cb_closed (GObject *src, GAsyncResult *res, gpointer data)
+{
+ NiceAgent *agent = NICE_AGENT (src);
+ g_debug ("test-turn:%s: %p", G_STRFUNC, agent);
+
+ *((gboolean *)data) = TRUE;
+}
+
+static void set_candidates (NiceAgent *from, guint from_stream,
+ NiceAgent *to, guint to_stream, guint component, gboolean remove_non_relay,
+ gboolean force_relay)
+{
+ GSList *cands = NULL, *i;
+
+ cands = nice_agent_get_local_candidates (from, from_stream, component);
+ if (remove_non_relay) {
+ restart:
+ for (i = cands; i; i = i->next) {
+ NiceCandidate *cand = i->data;
+ if (force_relay)
+ g_assert (cand->type == NICE_CANDIDATE_TYPE_RELAYED);
+ if (cand->type != NICE_CANDIDATE_TYPE_RELAYED) {
+ cands = g_slist_remove (cands, cand);
+ nice_candidate_free (cand);
+ goto restart;
+ }
+ }
+ }
+ nice_agent_set_remote_candidates (to, to_stream, component, cands);
+
+ for (i = cands; i; i = i->next)
+ nice_candidate_free ((NiceCandidate *) i->data);
+ g_slist_free (cands);
+}
+
+static void set_credentials (NiceAgent *lagent, guint lstream,
+ NiceAgent *ragent, guint rstream)
+{
+ gchar *ufrag = NULL, *password = NULL;
+
+ nice_agent_get_local_credentials(lagent, lstream, &ufrag, &password);
+ nice_agent_set_remote_credentials (ragent, rstream, ufrag, password);
+ g_free (ufrag);
+ g_free (password);
+ nice_agent_get_local_credentials(ragent, rstream, &ufrag, &password);
+ nice_agent_set_remote_credentials (lagent, lstream, ufrag, password);
+ g_free (ufrag);
+ g_free (password);
+}
+
+static void
+run_test(guint turn_port, gboolean is_ipv6,
+ gboolean ice_udp, gboolean ice_tcp, gboolean force_relay,
+ gboolean remove_non_relay,
+ NiceRelayType turn_type)
+{
+ NiceAgent *lagent, *ragent; /* agent's L and R */
+ const gchar *localhost;
+ NiceAddress localaddr;
+ guint ls_id, rs_id;
+ gulong timer_id;
+ gboolean lagent_closed = FALSE;
+ gboolean ragent_closed = FALSE;
+
+ if (is_ipv6)
+ localhost = "::1";
+ else
+ localhost = "127.0.0.1";
+
+ /* step: initialize variables modified by the callbacks */
+ global_components_ready = 0;
+ global_lagent_gathering_done = FALSE;
+ global_ragent_gathering_done = FALSE;
+ global_lagent_cands = global_ragent_cands = 0;
+
+ lagent = nice_agent_new (NULL, NICE_COMPATIBILITY_RFC5245);
+ ragent = nice_agent_new (NULL, NICE_COMPATIBILITY_RFC5245);
+
+ g_object_set (G_OBJECT (lagent), "ice-tcp", ice_tcp, "ice-udp", ice_udp,
+ "force-relay", force_relay, NULL);
+ g_object_set (G_OBJECT (ragent), "ice-tcp", ice_tcp, "ice-udp", ice_udp,
+ "force-relay", force_relay, NULL);
+
+ g_object_set (G_OBJECT (lagent), "upnp", FALSE, NULL);
+ g_object_set (G_OBJECT (ragent), "upnp", FALSE, NULL);
+ nice_agent_set_software (lagent, "Test-turn, Left Agent");
+ nice_agent_set_software (ragent, "Test-turn, Right Agent");
+
+ timer_id = g_timeout_add (30000, timer_cb, NULL);
+
+
+ if (!nice_address_set_from_string (&localaddr, localhost))
+ g_assert_not_reached ();
+ nice_agent_add_local_address (lagent, &localaddr);
+ nice_agent_add_local_address (ragent, &localaddr);
+
+ g_signal_connect (G_OBJECT (lagent), "candidate-gathering-done",
+ G_CALLBACK (cb_candidate_gathering_done), GUINT_TO_POINTER(1));
+ g_signal_connect (G_OBJECT (ragent), "candidate-gathering-done",
+ G_CALLBACK (cb_candidate_gathering_done), GUINT_TO_POINTER (2));
+ g_signal_connect (G_OBJECT (lagent), "component-state-changed",
+ G_CALLBACK (cb_component_state_changed), GUINT_TO_POINTER (1));
+ g_signal_connect (G_OBJECT (ragent), "component-state-changed",
+ G_CALLBACK (cb_component_state_changed), GUINT_TO_POINTER (2));
+ g_signal_connect (G_OBJECT (lagent), "new-selected-pair",
+ G_CALLBACK (cb_new_selected_pair), GUINT_TO_POINTER(1));
+ g_signal_connect (G_OBJECT (ragent), "new-selected-pair",
+ G_CALLBACK (cb_new_selected_pair), GUINT_TO_POINTER (2));
+
+ g_object_set (G_OBJECT (lagent), "controlling-mode", TRUE, NULL);
+ g_object_set (G_OBJECT (ragent), "controlling-mode", FALSE, NULL);
+
+ ls_id = nice_agent_add_stream (lagent, 1);
+ rs_id = nice_agent_add_stream (ragent, 1);
+ g_assert (ls_id > 0);
+ g_assert (rs_id > 0);
+ nice_agent_set_relay_info(lagent, ls_id, 1,
+ localhost, turn_port, TURN_USER, TURN_PASS, turn_type);
+ nice_agent_set_relay_info(ragent, rs_id, 1,
+ localhost, turn_port, TURN_USER, TURN_PASS, turn_type);
+
+ /* Gather candidates and test nice_agent_set_port_range */
+ g_assert (nice_agent_gather_candidates (lagent, ls_id) == TRUE);
+ g_assert (nice_agent_gather_candidates (ragent, rs_id) == TRUE);
+
+ nice_agent_attach_recv (lagent, ls_id, NICE_COMPONENT_TYPE_RTP,
+ g_main_context_default (), cb_nice_recv, GUINT_TO_POINTER (1));
+ nice_agent_attach_recv (ragent, rs_id, NICE_COMPONENT_TYPE_RTP,
+ g_main_context_default (), cb_nice_recv, GUINT_TO_POINTER (2));
+
+ g_assert (global_lagent_gathering_done == FALSE);
+ g_assert (global_ragent_gathering_done == FALSE);
+ g_debug ("test-turn: Added streams, running context until 'candidate-gathering-done'...");
+ while (!global_lagent_gathering_done)
+ g_main_context_iteration (NULL, TRUE);
+ g_assert (global_lagent_gathering_done == TRUE);
+ while (!global_ragent_gathering_done)
+ g_main_context_iteration (NULL, TRUE);
+ g_assert (global_ragent_gathering_done == TRUE);
+
+ set_credentials (lagent, ls_id, ragent, rs_id);
+
+ set_candidates (ragent, rs_id, lagent, ls_id, NICE_COMPONENT_TYPE_RTP,
+ remove_non_relay, force_relay);
+ set_candidates (lagent, ls_id, ragent, rs_id, NICE_COMPONENT_TYPE_RTP,
+ remove_non_relay, force_relay);
+
+ while (global_lagent_state[0] != NICE_COMPONENT_STATE_READY ||
+ global_ragent_state[0] != NICE_COMPONENT_STATE_READY)
+ g_main_context_iteration (NULL, TRUE);
+ g_assert (global_lagent_state[0] == NICE_COMPONENT_STATE_READY);
+ g_assert (global_ragent_state[0] == NICE_COMPONENT_STATE_READY);
+
+ nice_agent_remove_stream (lagent, ls_id);
+ nice_agent_remove_stream (ragent, rs_id);
+
+ nice_agent_close_async (lagent, cb_closed, &lagent_closed);
+ nice_agent_close_async (ragent, cb_closed, &ragent_closed);
+
+ g_clear_object(&lagent);
+ g_clear_object(&ragent);
+
+ while (!lagent_closed || !ragent_closed) {
+ g_main_context_iteration (NULL, TRUE);
+ }
+
+ g_source_remove (timer_id);
+
+}
+
+guint global_turn_port;
+
+static void
+udp_no_force_no_remove_udp (void)
+{
+ run_test(global_turn_port, FALSE /* is_ipv6 */,
+ TRUE /* ice_udp */,
+ FALSE /* ice_tcp */,
+ FALSE /* force_relay */,
+ FALSE /* remove_non_relay */,
+ NICE_RELAY_TYPE_TURN_UDP);
+}
+
+static void
+udp_no_force_remove_udp (void)
+{
+ run_test(global_turn_port, FALSE /* is_ipv6 */,
+ TRUE /* ice_udp */,
+ FALSE /* ice_tcp */,
+ FALSE /* force_relay */,
+ TRUE /* remove_non_relay */,
+ NICE_RELAY_TYPE_TURN_UDP);
+}
+
+static void
+udp_force_no_remove_udp (void)
+{
+ run_test(global_turn_port, FALSE /* is_ipv6 */,
+ TRUE /* ice_udp */,
+ FALSE /* ice_tcp */,
+ TRUE /* force_relay */,
+ FALSE /* remove_non_relay */,
+ NICE_RELAY_TYPE_TURN_UDP);
+}
+
+static void
+udp_no_force_no_remove_tcp (void)
+{
+ run_test(global_turn_port, FALSE /* is_ipv6 */,
+ TRUE /* ice_udp */,
+ FALSE /* ice_tcp */,
+ FALSE /* force_relay */,
+ FALSE /* remove_non_relay */,
+ NICE_RELAY_TYPE_TURN_TCP);
+}
+
+static void
+udp_no_force_remove_tcp (void)
+{
+ run_test(global_turn_port, FALSE /* is_ipv6 */,
+ TRUE /* ice_udp */,
+ FALSE /* ice_tcp */,
+ FALSE /* force_relay */,
+ TRUE /* remove_non_relay */,
+ NICE_RELAY_TYPE_TURN_TCP);
+}
+
+static void
+udp_force_no_remove_tcp (void)
+{
+ run_test(global_turn_port, FALSE /* is_ipv6 */,
+ TRUE /* ice_udp */,
+ FALSE /* ice_tcp */,
+ TRUE /* force_relay */,
+ FALSE /* remove_non_relay */,
+ NICE_RELAY_TYPE_TURN_TCP);
+}
+
+
+
+
+
+int
+main (int argc, char **argv)
+{
+ GSubprocess *sp;
+ GError *error = NULL;
+ gchar portstr[10];
+ int ret;
+ gchar *out_str = NULL;
+ gchar *err_str = NULL;
+
+ g_test_init (&argc, &argv, NULL);
+
+ global_turn_port = g_random_int_range (10000, 60000);
+ snprintf(portstr, 9, "%u", global_turn_port);
+
+ if (g_spawn_command_line_sync ("turnserver --help", &out_str, &err_str, NULL,
+ NULL) && err_str) {
+ if (!strstr(err_str, "--user")) {
+ g_print ("rfc5766-turn-server not installed, skipping turn test\n");
+ return 0;
+ }
+ } else {
+ g_print ("rfc5766-turn-server not installed, skipping turn test\n");
+ return 0;
+ }
+ g_free (err_str);
+ g_free (out_str);
+
+ sp = g_subprocess_new (G_SUBPROCESS_FLAGS_STDOUT_SILENCE, &error,
+ "turnserver",
+ "--user", "toto:0xaae440b3348d50265b63703117c7bfd5",
+ "--realm", "realm",
+ "--listening-port", portstr,
+ NULL);
+
+ g_test_add_func ("/nice/turn/udp", udp_no_force_no_remove_udp);
+ g_test_add_func ("/nice/turn/udp/remove_non_turn",
+ udp_no_force_remove_udp);
+ g_test_add_func ("/nice/turn/udp/force_relay",
+ udp_force_no_remove_udp);
+ g_test_add_func ("/nice/turn/udp/over-tcp", udp_no_force_no_remove_tcp);
+ g_test_add_func ("/nice/turn/udp/over-tcp/remove_non_turn",
+ udp_no_force_remove_tcp);
+ g_test_add_func ("/nice/turn/udp/over-tcp/force_relay",
+ udp_force_no_remove_tcp);
+
+ ret = g_test_run ();
+
+ g_subprocess_force_exit (sp);
+ g_subprocess_wait (sp, NULL, NULL);
+ g_clear_object (&sp);
+
+ return ret;
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2018 Jakub Adam <jakub.adam@ktknet.cz>
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <gio/gnetworking.h>
+
+#include "agent-priv.h"
+#include "socket.h"
+
+static GRand *randg;
+
+static GSList *
+generate_test_messages(void)
+{
+ guint i;
+ GSList *result = NULL;
+
+ for (i = 0; i != 100; ++i) {
+ GInputVector *msg_data = g_new (GInputVector, 1);
+ gsize msg_size = g_rand_int_range (randg, 0, G_MAXUINT16);
+ gsize j;
+
+ msg_data->size = msg_size + sizeof (guint16);
+ msg_data->buffer = g_malloc (msg_data->size);
+ *(guint16 *)(msg_data->buffer) = htons (msg_size);
+
+ for (j = 2; j != msg_data->size; ++j) {
+ ((guint8 *)msg_data->buffer)[j] = g_rand_int(randg);
+ }
+
+ result = g_slist_append(result, msg_data);
+ }
+
+ return result;
+}
+
+typedef struct {
+ GSList *msg_data;
+ GSList *current_msg;
+ gsize offset;
+ guint8 send_buffer[G_MAXUINT16 + sizeof (guint16)];
+} TestSocketPriv;
+
+static gint
+test_socket_recv_messages (NiceSocket *sock, NiceInputMessage *recv_messages,
+ guint n_recv_messages) {
+ TestSocketPriv *priv = sock->priv;
+ guint i;
+
+ for (i = 0; priv->current_msg && i != n_recv_messages; ++i) {
+ gsize msg_size = g_rand_int_range (randg, 0, G_MAXUINT16) + sizeof (guint16);
+ gsize j;
+
+ j = sizeof (guint16);
+ while (priv->current_msg && j < msg_size) {
+ GInputVector *msg = priv->current_msg->data;
+ gsize cpylen = MIN (msg->size - priv->offset, msg_size - j);
+ memcpy (priv->send_buffer + j, (guint8 *)msg->buffer + priv->offset,
+ cpylen);
+ priv->offset += cpylen;
+ j += cpylen;
+
+ if (priv->offset == msg->size) {
+ priv->current_msg = priv->current_msg->next;
+ priv->offset = 0;
+ }
+ }
+
+ msg_size = j;
+ *(guint16 *)(priv->send_buffer) = htons (msg_size - sizeof (guint16));
+
+ memcpy_buffer_to_input_message (&recv_messages[i], priv->send_buffer, msg_size);
+ nice_address_set_from_string (recv_messages[i].from, "127.0.0.1");
+ }
+
+ return i;
+}
+
+static gboolean
+test_socket_is_reliable (NiceSocket *sock) {
+ return TRUE;
+}
+
+static void
+test_socket_close (NiceSocket *sock) {
+ g_free(sock->priv);
+}
+
+static NiceSocket *
+test_socket_new (GSList *msg_data)
+{
+ NiceSocket *sock = g_new0 (NiceSocket, 1);
+ TestSocketPriv *priv = g_new0 (TestSocketPriv, 1);
+ priv->msg_data = msg_data;
+ priv->current_msg = msg_data;
+ priv->offset = 0;
+
+ sock->type = NICE_SOCKET_TYPE_UDP_TURN_OVER_TCP;
+ sock->recv_messages = test_socket_recv_messages;
+ sock->is_reliable = test_socket_is_reliable;
+ sock->close = test_socket_close;
+ sock->priv = (void *) priv;
+
+ return sock;
+}
+
+#define N_RECV_MESSAGES 7
+
+static void
+tcp_turn_fragmentation (void)
+{
+ /* Generate some RFC4571-framed test messages. A dummy base socket will split
+ * them randomly into TCP-TURN messages. Test that tcp-turn socket can
+ * correctly extract and reassemble the original test data out of the TURN
+ * messages. */
+ GSList *test_messages = generate_test_messages ();
+ NiceAddress addr;
+ NiceSocket *turnsock;
+
+ NiceInputMessage recv_messages[N_RECV_MESSAGES];
+ GInputVector recv_vectors[N_RECV_MESSAGES];
+ NiceAddress recv_addr[N_RECV_MESSAGES];
+ guint8 recv_buffers[N_RECV_MESSAGES][G_MAXUINT16 + sizeof (guint16)];
+
+ gint n_messages;
+ guint i;
+ GSList *li;
+
+ for (i = 0; i != N_RECV_MESSAGES; ++i) {
+ recv_messages[i].buffers = &recv_vectors[i];
+ recv_messages[i].from = &recv_addr[i];
+ recv_messages[i].n_buffers = 1;
+ recv_messages[i].length = 0;
+ recv_vectors[i].buffer = &recv_buffers[i];
+ recv_vectors[i].size = sizeof (recv_buffers[i]);
+ }
+
+ nice_address_set_from_string (&addr, "127.0.0.1");
+
+ turnsock = nice_udp_turn_socket_new (NULL, &addr,
+ test_socket_new (test_messages), &addr, "", "",
+ NICE_TURN_SOCKET_COMPATIBILITY_OC2007);
+
+ li = test_messages;
+ while (li) {
+ n_messages = nice_socket_recv_messages (turnsock, recv_messages,
+ N_RECV_MESSAGES);
+
+ for (i = 0; i != (guint)n_messages; ++i) {
+ NiceInputMessage *message = &recv_messages[i];
+ GInputVector *vec = li->data;
+ if (message->length == 0) {
+ continue;
+ }
+ g_assert (message->length == vec->size);
+ g_assert (!memcmp (message->buffers->buffer, vec->buffer,
+ message->length));
+
+ li = li->next;
+ }
+ }
+
+ for (li = test_messages; li; li = li->next) {
+ GInputVector *v = li->data;
+ g_free (v->buffer);
+ g_free (v);
+ }
+ g_slist_free (test_messages);
+
+ nice_socket_free(turnsock);
+}
+
+int
+main (int argc, char *argv[])
+{
+ GMainLoop *mainloop;
+
+ g_networking_init ();
+
+ randg = g_rand_new();
+ g_test_init (&argc, &argv, NULL);
+
+ mainloop = g_main_loop_new (NULL, TRUE);
+
+ g_test_add_func ("/udp-turn/tcp-fragmentation", tcp_turn_fragmentation);
+
+ g_test_run ();
+
+ g_rand_free(randg);
+
+ g_main_loop_unref (mainloop);
+
+ return 0;
+}
--- /dev/null
+/*
+ * This file is part of the Nice GLib ICE library.
+ *
+ * (C) 2006, 2007 Collabora Ltd.
+ * Contact: Dafydd Harries
+ * (C) 2006, 2007 Nokia Corporation. All rights reserved.
+ * Contact: Kai Vehmanen
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Nice GLib ICE library.
+ *
+ * The Initial Developers of the Original Code are Collabora Ltd and Nokia
+ * Corporation. All Rights Reserved.
+ *
+ * Contributors:
+ * Dafydd Harries, Collabora Ltd.
+ *
+ * Alternatively, the contents of this file may be used under the terms of the
+ * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
+ * case the provisions of LGPL are applicable instead of those above. If you
+ * wish to allow use of your version of this file only under the terms of the
+ * LGPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replace
+ * them with the notice and other provisions required by the LGPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the LGPL.
+ */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#include "agent.h"
+#include "agent-priv.h"
+
+/* Waits about 10 seconds for @var to be NULL/FALSE */
+#define WAIT_UNTIL_UNSET(var, context) \
+ if (var) \
+ { \
+ int _i; \
+ \
+ for (_i = 0; _i < 13 && (var); _i++) \
+ { \
+ g_usleep (1000 * (1 << _i)); \
+ g_main_context_iteration (context, FALSE); \
+ } \
+ \
+ g_assert (!(var)); \
+ }
+
+gint
+main (void)
+{
+ NiceAgent *agent;
+ NiceAddress addr_local, addr_remote;
+ NiceCandidate *candidate;
+ GSList *candidates, *i;
+ guint stream_id;
+
+#ifdef G_OS_WIN32
+ WSADATA w;
+
+ WSAStartup(0x0202, &w);
+#endif
+
+ nice_address_init (&addr_local);
+ nice_address_init (&addr_remote);
+
+ g_assert (nice_address_set_from_string (&addr_local, "127.0.0.1"));
+ g_assert (nice_address_set_from_string (&addr_remote, "127.0.0.1"));
+ nice_address_set_port (&addr_remote, 2345);
+
+ agent = nice_agent_new ( NULL, NICE_COMPATIBILITY_RFC5245);
+ g_object_set (G_OBJECT (agent), "ice-tcp", FALSE, NULL);
+
+ g_assert (agent->local_addresses == NULL);
+
+ /* add one local address */
+ nice_agent_add_local_address (agent, &addr_local);
+
+ g_assert (agent->local_addresses != NULL);
+ g_assert (g_slist_length (agent->local_addresses) == 1);
+ g_assert (nice_address_equal (agent->local_addresses->data, &addr_local));
+
+ /* add a stream */
+ stream_id = nice_agent_add_stream (agent, 1);
+ nice_agent_gather_candidates (agent, stream_id);
+
+ /* adding a stream should cause host candidates to be generated */
+ candidates = nice_agent_get_local_candidates (agent, stream_id, 1);
+ g_assert (g_slist_length (candidates) == 1);
+ candidate = candidates->data;
+ /* socket manager uses random port number */
+ nice_address_set_port (&addr_local, 1);
+ nice_address_set_port (&(candidate->addr), 1);
+ g_assert (nice_address_equal (&(candidate->addr), &addr_local));
+ g_assert (strncmp (candidate->foundation, "1", 1) == 0);
+ for (i = candidates; i; i = i->next)
+ nice_candidate_free ((NiceCandidate *) i->data);
+ g_slist_free (candidates);
+
+ /* clean up */
+ nice_agent_remove_stream (agent, stream_id);
+
+ g_object_add_weak_pointer (G_OBJECT (agent), (gpointer *) &agent);
+ g_object_unref (agent);
+ WAIT_UNTIL_UNSET (agent, NULL);
+
+#ifdef G_OS_WIN32
+ WSACleanup();
+#endif
+ return 0;
+}
+